Skip to content

Commit

Permalink
avoid creating stub patientss and/or local patient unless strictly re…
Browse files Browse the repository at this point in the history
…quired due to request to create new resource in patient compartment
  • Loading branch information
timcoffman committed Jun 6, 2024
1 parent b82de1e commit 96e9f40
Show file tree
Hide file tree
Showing 27 changed files with 1,478 additions and 364 deletions.
69 changes: 69 additions & 0 deletions src/main/java/edu/ohsu/cmp/ecp/sds/Permissions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package edu.ohsu.cmp.ecp.sds;

import java.util.Optional;

import org.hl7.fhir.instance.model.api.IIdType;

public final class Permissions {
private final IIdType authorizedUserId;
private final Optional<Permissions.ReadAllPatients> readAllPatients ;
private final Optional<Permissions.ReadAndWriteSpecificPatient> readAndWriteSpecificPatient ;

public Permissions( Permissions.ReadAllPatients readAllPatients ) {
this.readAllPatients = Optional.of(readAllPatients);
authorizedUserId = readAllPatients.authorizedUserId() ;
this.readAndWriteSpecificPatient = Optional.empty();
}

public Permissions( Permissions.ReadAndWriteSpecificPatient readAndWriteSpecificPatient) {
this.readAllPatients = Optional.empty();
this.readAndWriteSpecificPatient = Optional.of( readAndWriteSpecificPatient );
authorizedUserId = readAndWriteSpecificPatient.authorizedUserId() ;
}

public IIdType authorizedUserId() {
return authorizedUserId ;
}

public Optional<Permissions.ReadAllPatients> readAllPatients() {
return readAllPatients ;
}
public Optional<Permissions.ReadAndWriteSpecificPatient> readAndWriteSpecificPatient() {
return readAndWriteSpecificPatient ;
}

public static final class ReadAllPatients {
private final IIdType authorizedUserId;

public ReadAllPatients(IIdType authorizedUserId) {
this.authorizedUserId = authorizedUserId;
}

public IIdType authorizedUserId() {
return authorizedUserId ;
}
}

public static final class ReadAndWriteSpecificPatient {
private final IIdType authorizedUserId;

private final UserIdentity patientId;

public ReadAndWriteSpecificPatient(IIdType authorizedUserId, UserIdentity patientId) {
this.authorizedUserId = authorizedUserId;
this.patientId = patientId;
}

public IIdType authorizedUserId() {
return authorizedUserId ;
}

public UserIdentity patientId() {
return patientId ;
}

public Permissions.ReadAndWriteSpecificPatient withUpdatedPatientIdentity( UserIdentity replacementPatientId ) {
return new ReadAndWriteSpecificPatient( authorizedUserId, replacementPatientId ) ;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package edu.ohsu.cmp.ecp.sds;

import static edu.ohsu.cmp.ecp.sds.SupplementalDataStoreLinkingInterceptor.getPermissions;
import static edu.ohsu.cmp.ecp.sds.SupplementalDataStorePermissionsInterceptor.getPermissions;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -16,7 +16,6 @@
import ca.uhn.fhir.rest.server.interceptor.auth.IAuthRule;
import ca.uhn.fhir.rest.server.interceptor.auth.IAuthRuleBuilder;
import ca.uhn.fhir.rest.server.interceptor.auth.RuleBuilder;
import edu.ohsu.cmp.ecp.sds.SupplementalDataStoreLinkingInterceptor.Permissions;

@Interceptor
@Component
Expand Down Expand Up @@ -73,7 +72,7 @@ private List<IAuthRule> buildRuleListForPermissions(Permissions permissions) {

/* no details of the patient identity are available */
return ruleBuilder()
.denyAll("expected user \"" + permissions.authorizedNonLocalUserId() + "\" to be authorized for patient read and/or write")
.denyAll("expected user \"" + permissions.authorizedUserId() + "\" to be authorized for patient read and/or write")
.build();
}

Expand Down Expand Up @@ -102,15 +101,32 @@ private List<IAuthRule> buildRuleListForPermissions( Permissions.ReadAllPatients

private List<IAuthRule> buildRuleListForPermissions( Permissions.ReadAndWriteSpecificPatient readAndWriteSpecificPatients ) {
List<IAuthRule> rules = new ArrayList<>() ;

IIdType localPatientId = readAndWriteSpecificPatients.patientId().localUserId() ;

/* permit access to all sds-local records for specific patient */
managePatientCompartment( true, localPatientId )
.forEach( rules::add );
/* permit access to all sds-local linkages that link to specific patient */
manageLinkages( true, localPatientId )
.forEach( rules::add ) ;
if ( !readAndWriteSpecificPatients.patientId().localUserId().isPresent() ) {

/* permit creating a new patient */
ruleBuilder()
.allow( describePatientPermission("create", true, null) )
.create().resourcesOfType("Patient").withAnyId()
.build().forEach( rules::add )
;

}

readAndWriteSpecificPatients.patientId().localUserId().ifPresent( localPatientId -> {

/* permit access to all sds-local records for specific patient */
managePatientCompartment( true, localPatientId )
.forEach( rules::add );
if ( localPatientId.hasBaseUrl() ) {
managePatientCompartment( true, localPatientId.toUnqualifiedVersionless() )
.forEach( rules::add );
}
/* permit access to all sds-local linkages that link to specific patient */
manageLinkages( true, localPatientId.toUnqualifiedVersionless() )
.forEach( rules::add ) ;

});

/* permit access to all sds-foreign records for specific patient in each partition */
for (IIdType nonLocalPatientId : readAndWriteSpecificPatients.patientId().nonLocalUserIds() ) {
Expand Down Expand Up @@ -144,7 +160,7 @@ private String describePatientPermission( String operation, boolean isLocal, IId
"%1$s %2$s patient %3$s",
operation,
isLocal ? "local" : "non-local",
patientId
null != patientId ? patientId : "-new-"
);
return patientRelatedOperationDesc ;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ public interface SupplementalDataStoreLinkage {
Set<? extends IBaseReference> patientsLinkedTo(IIdType sourcePatientId);
Set<? extends IBaseReference> patientsLinkedFrom(IIdType alternatePatientId);

boolean patientCompartmentIsClaimed(IIdType patientCompartment );

Optional<IIdType> lookupLocalUserFor(IIdType userId);
IIdType establishLocalUser(String userResourceType);
IIdType establishLocalUserFor(IIdType userId);
IIdType establishNonLocalUser(IIdType nonLocalUserId);

void linkNonLocalPatientToLocalPatient(IIdType localPatientId, IIdType nonLocalPatientId);
}
Loading

0 comments on commit 96e9f40

Please sign in to comment.