diff --git a/exec/pom.xml b/exec/pom.xml index ee38ce5d..ad60b973 100755 --- a/exec/pom.xml +++ b/exec/pom.xml @@ -21,7 +21,7 @@ com.google.fhir.gateway fhir-gateway - 0.1.26 + 0.1.27 exec diff --git a/plugins/pom.xml b/plugins/pom.xml index ac118be3..d4288199 100755 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -23,7 +23,7 @@ implementations do not have to do this; they can redeclare those deps. --> com.google.fhir.gateway fhir-gateway - 0.1.26 + 0.1.27 plugins diff --git a/plugins/src/main/java/com/google/fhir/gateway/plugin/OpenSRPHelper.java b/plugins/src/main/java/com/google/fhir/gateway/plugin/OpenSRPHelper.java new file mode 100644 index 00000000..f3841772 --- /dev/null +++ b/plugins/src/main/java/com/google/fhir/gateway/plugin/OpenSRPHelper.java @@ -0,0 +1,477 @@ +package com.google.fhir.gateway.plugin; + +import static org.smartregister.utils.Constants.EMPTY_STRING; + +import ca.uhn.fhir.rest.client.api.IGenericClient; +import ca.uhn.fhir.rest.gclient.ReferenceClientParam; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.lang3.StringUtils; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.r4.model.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.smartregister.model.location.LocationHierarchy; +import org.smartregister.model.location.ParentChildrenMap; +import org.smartregister.model.practitioner.FhirPractitionerDetails; +import org.smartregister.model.practitioner.PractitionerDetails; +import org.smartregister.utils.Constants; +import org.springframework.lang.Nullable; + +public class OpenSRPHelper { + private static final Logger logger = LoggerFactory.getLogger(OpenSRPHelper.class); + public static final String PRACTITIONER_GROUP_CODE = "405623001"; + public static final String HTTP_SNOMED_INFO_SCT = "http://snomed.info/sct"; + public static final Bundle EMPTY_BUNDLE = new Bundle(); + private IGenericClient r4FHIRClient; + + public OpenSRPHelper(IGenericClient fhirClient) { + this.r4FHIRClient = fhirClient; + } + + private IGenericClient getFhirClientForR4() { + return r4FHIRClient; + } + + public PractitionerDetails getPractitionerDetailsByKeycloakId(String keycloakUUID) { + PractitionerDetails practitionerDetails = new PractitionerDetails(); + + logger.info("Searching for practitioner with identifier: " + keycloakUUID); + IBaseResource practitioner = getPractitionerByIdentifier(keycloakUUID); + String practitionerId = EMPTY_STRING; + + if (practitioner.getIdElement() != null && practitioner.getIdElement().getIdPart() != null) { + practitionerId = practitioner.getIdElement().getIdPart(); + } + + if (StringUtils.isNotBlank(practitionerId)) { + + practitionerDetails = getPractitionerDetailsByPractitionerId(practitionerId); + + } else { + logger.error("Practitioner with KC identifier: " + keycloakUUID + " not found"); + practitionerDetails.setId(Constants.PRACTITIONER_NOT_FOUND); + } + + return practitionerDetails; + } + + public Bundle getSupervisorPractitionerDetailsByKeycloakId(String keycloakUUID) { + Bundle bundle = new Bundle(); + + logger.info("Searching for practitioner with identifier: " + keycloakUUID); + IBaseResource practitioner = getPractitionerByIdentifier(keycloakUUID); + String practitionerId = EMPTY_STRING; + + if (practitioner.getIdElement() != null && practitioner.getIdElement().getIdPart() != null) { + practitionerId = practitioner.getIdElement().getIdPart(); + } + + if (StringUtils.isNotBlank(practitionerId)) { + + bundle = getAttributedPractitionerDetailsByPractitionerId(practitionerId); + + } else { + logger.error("Practitioner with KC identifier: " + keycloakUUID + " not found"); + } + + return bundle; + } + + private Bundle getAttributedPractitionerDetailsByPractitionerId(String practitionerId) { + Bundle responseBundle = new Bundle(); + List attributedPractitionerIds = new ArrayList<>(); + PractitionerDetails practitionerDetails = + getPractitionerDetailsByPractitionerId(practitionerId); + + List careTeamList = practitionerDetails.getFhirPractitionerDetails().getCareTeams(); + // Get other guys. + + List careTeamManagingOrganizationIds = + getManagingOrganizationsOfCareTeamIds(careTeamList); + List supervisorCareTeamOrganizationLocationIds = + getLocationIdentifiersByOrganizationIds(careTeamManagingOrganizationIds); + List officialLocationIds = + getOfficialLocationIdentifiersByLocationIds(supervisorCareTeamOrganizationLocationIds); + List locationHierarchies = + getLocationsHierarchyByOfficialLocationIdentifiers(officialLocationIds); + List parentChildrenList = + locationHierarchies.stream() + .flatMap( + locationHierarchy -> + locationHierarchy + .getLocationHierarchyTree() + .getLocationsHierarchy() + .getParentChildren() + .stream()) + .collect(Collectors.toList()); + List attributedLocationsList = + parentChildrenList.stream() + .flatMap(parentChildren -> parentChildren.children().stream()) + .map(it -> it.getName()) + .collect(Collectors.toList()); + List attributedOrganizationIds = + getOrganizationIdsByLocationIds(attributedLocationsList); + + // Get care teams by organization Ids + List attributedCareTeams = getCareTeamsByOrganizationIds(attributedOrganizationIds); + careTeamList.addAll(attributedCareTeams); + + for (CareTeam careTeam : careTeamList) { + // Add current supervisor practitioners + attributedPractitionerIds.addAll( + careTeam.getParticipant().stream() + .filter( + it -> + it.hasMember() + && it.getMember() + .getReference() + .startsWith(Enumerations.ResourceType.PRACTITIONER.toCode())) + .map(it -> getReferenceIDPart(it.getMember().getReference())) + .collect(Collectors.toList())); + } + + List bundleEntryComponentList = new ArrayList<>(); + + for (String attributedPractitionerId : attributedPractitionerIds) { + bundleEntryComponentList.add( + new Bundle.BundleEntryComponent() + .setResource(getPractitionerDetailsByPractitionerId(attributedPractitionerId))); + } + + responseBundle.setEntry(bundleEntryComponentList); + responseBundle.setTotal(bundleEntryComponentList.size()); + return responseBundle; + } + + private List getOrganizationIdsByLocationIds(List attributedLocationsList) { + if (attributedLocationsList == null || attributedLocationsList.isEmpty()) { + return new ArrayList<>(); + } + + Bundle organizationAffiliationsBundle = + getFhirClientForR4() + .search() + .forResource(OrganizationAffiliation.class) + .where(OrganizationAffiliation.LOCATION.hasAnyOfIds(attributedLocationsList)) + .returnBundle(Bundle.class) + .execute(); + + return organizationAffiliationsBundle.getEntry().stream() + .map( + bundleEntryComponent -> + getReferenceIDPart( + ((OrganizationAffiliation) bundleEntryComponent.getResource()) + .getOrganization() + .getReference())) + .collect(Collectors.toList()); + } + + private PractitionerDetails getPractitionerDetailsByPractitionerId(String practitionerId) { + + PractitionerDetails practitionerDetails = new PractitionerDetails(); + FhirPractitionerDetails fhirPractitionerDetails = new FhirPractitionerDetails(); + + logger.info("Searching for care teams for practitioner with id: " + practitionerId); + Bundle careTeams = getCareTeams(practitionerId); + List careTeamsList = mapBundleToCareTeams(careTeams); + fhirPractitionerDetails.setCareTeams(careTeamsList); + + StringType practitionerIdString = new StringType(practitionerId); + fhirPractitionerDetails.setPractitionerId(practitionerIdString); + + logger.info("Searching for Organizations tied with CareTeams: "); + List careTeamManagingOrganizationIds = + getManagingOrganizationsOfCareTeamIds(careTeamsList); + + Bundle careTeamManagingOrganizations = getOrganizationsById(careTeamManagingOrganizationIds); + logger.info("Managing Organization are fetched"); + + List managingOrganizationTeams = + mapBundleToOrganizations(careTeamManagingOrganizations); + + logger.info("Searching for organizations of practitioner with id: " + practitionerId); + + List practitionerRoleList = + getPractitionerRolesByPractitionerId(practitionerId); + logger.info("Practitioner Roles are fetched"); + + List practitionerOrganizationIds = + getOrganizationIdsByPractitionerRoles(practitionerRoleList); + + Bundle practitionerOrganizations = getOrganizationsById(practitionerOrganizationIds); + + List teams = mapBundleToOrganizations(practitionerOrganizations); + // TODO Fix Distinct + List bothOrganizations = + Stream.concat(managingOrganizationTeams.stream(), teams.stream()) + .distinct() + .collect(Collectors.toList()); + + fhirPractitionerDetails.setOrganizations(bothOrganizations); + + fhirPractitionerDetails.setPractitionerRoles(practitionerRoleList); + + Bundle groupsBundle = getGroupsAssignedToPractitioner(practitionerId); + logger.info("Groups are fetched"); + + List groupsList = mapBundleToGroups(groupsBundle); + fhirPractitionerDetails.setGroups(groupsList); + fhirPractitionerDetails.setId(practitionerIdString.getValue()); + + logger.info("Searching for locations by organizations"); + + List locationIds = + getLocationIdentifiersByOrganizationIds( + Stream.concat( + careTeamManagingOrganizationIds.stream(), practitionerOrganizationIds.stream()) + .distinct() + .collect(Collectors.toList())); + + List locationsIdentifiers = + getOfficialLocationIdentifiersByLocationIds( + locationIds); // TODO Investigate why the Location ID and official identifiers are + // different + + logger.info("Searching for location hierarchy list by locations identifiers"); + List locationHierarchyList = + getLocationsHierarchyByOfficialLocationIdentifiers(locationsIdentifiers); + fhirPractitionerDetails.setLocationHierarchyList(locationHierarchyList); + + logger.info("Searching for locations by ids"); + List locationsList = getLocationsByIds(locationIds); + fhirPractitionerDetails.setLocations(locationsList); + + practitionerDetails.setId(practitionerId); + practitionerDetails.setFhirPractitionerDetails(fhirPractitionerDetails); + + return practitionerDetails; + } + + private List mapBundleToOrganizations(Bundle organizationBundle) { + return organizationBundle.getEntry().stream() + .map(bundleEntryComponent -> (Organization) bundleEntryComponent.getResource()) + .collect(Collectors.toList()); + } + + private Bundle getGroupsAssignedToPractitioner(String practitionerId) { + return getFhirClientForR4() + .search() + .forResource(Group.class) + .where(Group.MEMBER.hasId(practitionerId)) + .where(Group.CODE.exactly().systemAndCode(HTTP_SNOMED_INFO_SCT, PRACTITIONER_GROUP_CODE)) + .returnBundle(Bundle.class) + .execute(); + } + + public static Predicate distinctByKey(Function keyExtractor) { + Set seen = ConcurrentHashMap.newKeySet(); + return t -> seen.add(keyExtractor.apply(t)); + } + + private List getPractitionerRolesByPractitionerId(String practitionerId) { + Bundle practitionerRoles = getPractitionerRoles(practitionerId); + return mapBundleToPractitionerRolesWithOrganization(practitionerRoles); + } + + private List getOrganizationIdsByPractitionerRoles( + List practitionerRoles) { + return practitionerRoles.stream() + .filter(practitionerRole -> practitionerRole.hasOrganization()) + .map(it -> getReferenceIDPart(it.getOrganization().getReference())) + .collect(Collectors.toList()); + } + + private Practitioner getPractitionerByIdentifier(String identifier) { + Bundle resultBundle = + getFhirClientForR4() + .search() + .forResource(Practitioner.class) + .where(Practitioner.IDENTIFIER.exactly().identifier(identifier)) + .returnBundle(Bundle.class) + .execute(); + + return resultBundle != null + ? (Practitioner) resultBundle.getEntryFirstRep().getResource() + : null; + } + + private List getCareTeamsByOrganizationIds(List organizationIds) { + if (organizationIds.isEmpty()) return new ArrayList<>(); + + Bundle bundle = + getFhirClientForR4() + .search() + .forResource(CareTeam.class) + .where( + CareTeam.PARTICIPANT.hasAnyOfIds( + organizationIds.stream() + .map( + it -> + Enumerations.ResourceType.ORGANIZATION.toCode() + + Constants.FORWARD_SLASH + + it) + .collect(Collectors.toList()))) + .returnBundle(Bundle.class) + .execute(); + + return bundle.getEntry().stream() + .filter(it -> ((CareTeam) it.getResource()).hasManagingOrganization()) + .map(it -> ((CareTeam) it.getResource())) + .collect(Collectors.toList()); + } + + private Bundle getCareTeams(String practitionerId) { + logger.info("Searching for Care Teams with practitioner id :" + practitionerId); + + return getFhirClientForR4() + .search() + .forResource(CareTeam.class) + .where( + CareTeam.PARTICIPANT.hasId( + Enumerations.ResourceType.PRACTITIONER.toCode() + + Constants.FORWARD_SLASH + + practitionerId)) + .returnBundle(Bundle.class) + .execute(); + } + + private Bundle getPractitionerRoles(String practitionerId) { + logger.info("Searching for Practitioner roles with practitioner id :" + practitionerId); + return getFhirClientForR4() + .search() + .forResource(PractitionerRole.class) + .where(PractitionerRole.PRACTITIONER.hasId(practitionerId)) + .returnBundle(Bundle.class) + .execute(); + } + + private String getReferenceIDPart(String reference) { + return reference.substring(reference.indexOf(Constants.FORWARD_SLASH) + 1); + } + + private Bundle getOrganizationsById(List organizationIds) { + return organizationIds.isEmpty() + ? EMPTY_BUNDLE + : getFhirClientForR4() + .search() + .forResource(Organization.class) + .where(new ReferenceClientParam(BaseResource.SP_RES_ID).hasAnyOfIds(organizationIds)) + .returnBundle(Bundle.class) + .execute(); + } + + private @Nullable List getLocationsByIds(List locationIds) { + if (locationIds == null || locationIds.isEmpty()) { + return new ArrayList<>(); + } + + Bundle locationsBundle = + getFhirClientForR4() + .search() + .forResource(Location.class) + .where(new ReferenceClientParam(BaseResource.SP_RES_ID).hasAnyOfIds(locationIds)) + .returnBundle(Bundle.class) + .execute(); + + return locationsBundle.getEntry().stream() + .map(bundleEntryComponent -> ((Location) bundleEntryComponent.getResource())) + .collect(Collectors.toList()); + } + + private @Nullable List getOfficialLocationIdentifiersByLocationIds( + List locationIds) { + if (locationIds == null || locationIds.isEmpty()) { + return new ArrayList<>(); + } + + List locations = getLocationsByIds(locationIds); + + return locations.stream() + .map( + it -> + it.getIdentifier().stream() + .filter( + id -> id.hasUse() && id.getUse().equals(Identifier.IdentifierUse.OFFICIAL)) + .map(it2 -> it2.getValue()) + .collect(Collectors.toList())) + .flatMap(it3 -> it3.stream()) + .collect(Collectors.toList()); + } + + private List getLocationIdentifiersByOrganizationIds(List organizationIds) { + if (organizationIds == null || organizationIds.isEmpty()) { + return new ArrayList<>(); + } + + Bundle locationsBundle = + getFhirClientForR4() + .search() + .forResource(OrganizationAffiliation.class) + .where(OrganizationAffiliation.PRIMARY_ORGANIZATION.hasAnyOfIds(organizationIds)) + .returnBundle(Bundle.class) + .execute(); + + return locationsBundle.getEntry().stream() + .map( + bundleEntryComponent -> + getReferenceIDPart( + ((OrganizationAffiliation) bundleEntryComponent.getResource()) + .getLocation().stream().findFirst().get().getReference())) + .collect(Collectors.toList()); + } + + private List getManagingOrganizationsOfCareTeamIds(List careTeamsList) { + logger.info("Searching for Organizations with care teams list of size:" + careTeamsList.size()); + return careTeamsList.stream() + .filter(careTeam -> careTeam.hasManagingOrganization()) + .flatMap(it -> it.getManagingOrganization().stream()) + .map(it -> getReferenceIDPart(it.getReference())) + .collect(Collectors.toList()); + } + + private List mapBundleToCareTeams(Bundle careTeams) { + return careTeams.getEntry().stream() + .map(bundleEntryComponent -> (CareTeam) bundleEntryComponent.getResource()) + .collect(Collectors.toList()); + } + + private List mapBundleToPractitionerRolesWithOrganization( + Bundle practitionerRoles) { + return practitionerRoles.getEntry().stream() + .filter( + bundleEntryComponent -> + ((PractitionerRole) bundleEntryComponent.getResource()).hasOrganization()) + .map(it -> (PractitionerRole) it.getResource()) + .collect(Collectors.toList()); + } + + private List mapBundleToGroups(Bundle groupsBundle) { + return groupsBundle.getEntry().stream() + .map(bundleEntryComponent -> (Group) bundleEntryComponent.getResource()) + .collect(Collectors.toList()); + } + + private List getLocationsHierarchyByOfficialLocationIdentifiers( + List officialLocationIdentifiers) { + if (officialLocationIdentifiers.isEmpty()) return new ArrayList<>(); + + Bundle bundle = + getFhirClientForR4() + .search() + .forResource(LocationHierarchy.class) + .where(LocationHierarchy.IDENTIFIER.exactly().codes(officialLocationIdentifiers)) + .returnBundle(Bundle.class) + .execute(); + + return bundle.getEntry().stream() + .map(it -> ((LocationHierarchy) it.getResource())) + .collect(Collectors.toList()); + } +} diff --git a/plugins/src/main/java/com/google/fhir/gateway/plugin/OpenSRPSyncAccessDecision.java b/plugins/src/main/java/com/google/fhir/gateway/plugin/OpenSRPSyncAccessDecision.java index 4a5e868f..86f7f17c 100755 --- a/plugins/src/main/java/com/google/fhir/gateway/plugin/OpenSRPSyncAccessDecision.java +++ b/plugins/src/main/java/com/google/fhir/gateway/plugin/OpenSRPSyncAccessDecision.java @@ -15,8 +15,6 @@ */ package com.google.fhir.gateway.plugin; -import static com.google.fhir.gateway.plugin.PermissionAccessChecker.Factory.PROXY_TO_ENV; - import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.api.RequestTypeEnum; @@ -65,32 +63,46 @@ public class OpenSRPSyncAccessDecision implements AccessDecision { private final String syncStrategy; private final String applicationId; private final boolean accessGranted; - private final List careTeamIds; - private final List locationIds; - private final List organizationIds; + private final List roles; private IgnoredResourcesConfig config; + private String keycloakUUID; private Gson gson = new Gson(); - private FhirContext fhirR4Context = FhirContext.forR4(); private IParser fhirR4JsonParser = fhirR4Context.newJsonParser(); + private IGenericClient fhirR4Client; + + private OpenSRPHelper openSRPHelper; public OpenSRPSyncAccessDecision( + String keycloakUUID, String applicationId, boolean accessGranted, List locationIds, List careTeamIds, List organizationIds, - String syncStrategy) { + String syncStrategy, + List roles) { + this.keycloakUUID = keycloakUUID; this.applicationId = applicationId; this.accessGranted = accessGranted; this.careTeamIds = careTeamIds; this.locationIds = locationIds; this.organizationIds = organizationIds; this.syncStrategy = syncStrategy; - config = getSkippedResourcesConfigs(); + this.config = getSkippedResourcesConfigs(); + this.roles = roles; + try { + setFhirR4Client( + fhirR4Context.newRestfulGenericClient( + System.getenv(PermissionAccessChecker.Factory.PROXY_TO_ENV))); + } catch (NullPointerException e) { + logger.error(e.getMessage()); + } + + this.openSRPHelper = new OpenSRPHelper(fhirR4Client); } @Override @@ -181,9 +193,21 @@ public String postProcess(RequestDetailsReader request, HttpResponse response) resultContent = fhirR4JsonParser.encodeResourceToString(resultContentBundle); } + if (includeAttributedPractitioners(request.getRequestPath())) { + Bundle practitionerDetailsBundle = + this.openSRPHelper.getSupervisorPractitionerDetailsByKeycloakId(keycloakUUID); + resultContent = fhirR4JsonParser.encodeResourceToString(practitionerDetailsBundle); + } + return resultContent; } + private boolean includeAttributedPractitioners(String requestPath) { + return Constants.SYNC_STRATEGY_LOCATION.equalsIgnoreCase(syncStrategy) + && roles.contains(Constants.ROLE_SUPERVISOR) + && Constants.ENDPOINT_PRACTITIONER_DETAILS.equals(requestPath); + } + @NotNull private static OperationOutcome createOperationOutcome(String exception) { OperationOutcome operationOutcome = new OperationOutcome(); @@ -264,7 +288,7 @@ private Bundle postProcessModeListEntries(IBaseResource responseResource) { requestBundle = processListEntriesGatewayModeByBundle(responseResource); } - return createFhirClientForR4().transaction().withBundle(requestBundle).execute(); + return fhirR4Client.transaction().withBundle(requestBundle).execute(); } /** @@ -415,10 +439,6 @@ private boolean shouldSkipDataFiltering(RequestDetailsReader requestDetailsReade return false; } - private IGenericClient createFhirClientForR4() { - return fhirR4Context.newRestfulGenericClient(System.getenv(PROXY_TO_ENV)); - } - @VisibleForTesting protected void setSkippedResourcesConfig(IgnoredResourcesConfig config) { this.config = config; @@ -429,6 +449,11 @@ protected void setFhirR4Context(FhirContext fhirR4Context) { this.fhirR4Context = fhirR4Context; } + @VisibleForTesting + public void setFhirR4Client(IGenericClient fhirR4Client) { + this.fhirR4Client = fhirR4Client; + } + class IgnoredResourcesConfig { @Getter List entries; @Getter private String path; @@ -450,5 +475,8 @@ public String toString() { public static final class Constants { public static final String FHIR_GATEWAY_MODE = "fhir-gateway-mode"; public static final String LIST_ENTRIES = "list-entries"; + public static final String ROLE_SUPERVISOR = "SUPERVISOR"; + public static final String ENDPOINT_PRACTITIONER_DETAILS = "practitioner-details"; + public static final String SYNC_STRATEGY_LOCATION = "Location"; } } diff --git a/plugins/src/main/java/com/google/fhir/gateway/plugin/PermissionAccessChecker.java b/plugins/src/main/java/com/google/fhir/gateway/plugin/PermissionAccessChecker.java index 7b5144d8..283af2d6 100755 --- a/plugins/src/main/java/com/google/fhir/gateway/plugin/PermissionAccessChecker.java +++ b/plugins/src/main/java/com/google/fhir/gateway/plugin/PermissionAccessChecker.java @@ -46,17 +46,10 @@ public class PermissionAccessChecker implements AccessChecker { private static final Logger logger = LoggerFactory.getLogger(PermissionAccessChecker.class); private final ResourceFinder resourceFinder; private final List userRoles; - private final String applicationId; - - private final List careTeamIds; - - private final List locationIds; - - private final List organizationIds; - - private final String syncStrategy; + private OpenSRPSyncAccessDecision openSRPSyncAccessDecision; private PermissionAccessChecker( + String keycloakUUID, List userRoles, ResourceFinderImp resourceFinder, String applicationId, @@ -73,11 +66,16 @@ private PermissionAccessChecker( Preconditions.checkNotNull(syncStrategy); this.resourceFinder = resourceFinder; this.userRoles = userRoles; - this.applicationId = applicationId; - this.careTeamIds = careTeamIds; - this.organizationIds = organizationIds; - this.locationIds = locationIds; - this.syncStrategy = syncStrategy; + this.openSRPSyncAccessDecision = + new OpenSRPSyncAccessDecision( + keycloakUUID, + applicationId, + true, + locationIds, + careTeamIds, + organizationIds, + syncStrategy, + userRoles); } @Override @@ -125,10 +123,7 @@ private AccessDecision processDelete(boolean userHasRole) { } private AccessDecision getAccessDecision(boolean userHasRole) { - return userHasRole - ? new OpenSRPSyncAccessDecision( - applicationId, true, locationIds, careTeamIds, organizationIds, syncStrategy) - : NoOpAccessDecision.accessDenied(); + return userHasRole ? openSRPSyncAccessDecision : NoOpAccessDecision.accessDenied(); } private AccessDecision processPost(boolean userHasRole) { @@ -362,6 +357,7 @@ public AccessChecker create( } } return new PermissionAccessChecker( + jwt.getSubject(), userRoles, ResourceFinderImp.getInstance(fhirContext), applicationId, diff --git a/plugins/src/test/java/com/google/fhir/gateway/plugin/OpenSRPSyncAccessDecisionTest.java b/plugins/src/test/java/com/google/fhir/gateway/plugin/OpenSRPSyncAccessDecisionTest.java index 9f7a6b0c..7fde39cd 100755 --- a/plugins/src/test/java/com/google/fhir/gateway/plugin/OpenSRPSyncAccessDecisionTest.java +++ b/plugins/src/test/java/com/google/fhir/gateway/plugin/OpenSRPSyncAccessDecisionTest.java @@ -15,7 +15,6 @@ */ package com.google.fhir.gateway.plugin; -import static com.google.fhir.gateway.plugin.PermissionAccessChecker.Factory.PROXY_TO_ENV; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -61,6 +60,8 @@ public class OpenSRPSyncAccessDecisionTest { private List organisationIds = new ArrayList<>(); + private List userRoles = new ArrayList<>(); + private OpenSRPSyncAccessDecision testInstance; @Test @@ -369,9 +370,9 @@ public void testPostProcessWithListModeHeaderShouldFetchListEntriesBundle() thro IGenericClient iGenericClient = mock(IGenericClient.class); ITransaction iTransaction = mock(ITransaction.class); ITransactionTyped iClientExecutable = mock(ITransactionTyped.class); + testInstance.setFhirR4Client(iGenericClient); + testInstance.setFhirR4Context(fhirR4Context); - Mockito.when(fhirR4Context.newRestfulGenericClient(System.getenv(PROXY_TO_ENV))) - .thenReturn(iGenericClient); Mockito.when(iGenericClient.transaction()).thenReturn(iTransaction); Mockito.when(iTransaction.withBundle(any(Bundle.class))).thenReturn(iClientExecutable); @@ -449,8 +450,6 @@ public void testPostProcessWithListModeHeaderSearchByTagShouldFetchListEntriesBu ITransaction iTransaction = mock(ITransaction.class); ITransactionTyped iClientExecutable = mock(ITransactionTyped.class); - Mockito.when(fhirR4Context.newRestfulGenericClient(System.getenv(PROXY_TO_ENV))) - .thenReturn(iGenericClient); Mockito.when(iGenericClient.transaction()).thenReturn(iTransaction); Mockito.when(iTransaction.withBundle(any(Bundle.class))).thenReturn(iClientExecutable); @@ -487,6 +486,8 @@ public void testPostProcessWithListModeHeaderSearchByTagShouldFetchListEntriesBu TestUtil.setUpFhirResponseMock( fhirResponseMock, realFhirContext.newJsonParser().encodeResourceToString(bundle)); + testInstance.setFhirR4Client(iGenericClient); + testInstance.setFhirR4Context(fhirR4Context); String resultContent = testInstance.postProcess(requestDetailsSpy, fhirResponseMock); Mockito.verify(iTransaction).withBundle(bundleArgumentCaptor.capture()); @@ -523,7 +524,14 @@ public void cleanUp() { private OpenSRPSyncAccessDecision createOpenSRPSyncAccessDecisionTestInstance() { OpenSRPSyncAccessDecision accessDecision = new OpenSRPSyncAccessDecision( - "sample-application-id", true, locationIds, careTeamIds, organisationIds, null); + "sample-keycloak-id", + "sample-application-id", + true, + locationIds, + careTeamIds, + organisationIds, + null, + userRoles); URL configFileUrl = Resources.getResource("hapi_sync_filter_ignored_queries.json"); OpenSRPSyncAccessDecision.IgnoredResourcesConfig skippedDataFilterConfig = diff --git a/pom.xml b/pom.xml index ee2d4993..b03bd77a 100755 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ com.google.fhir.gateway fhir-gateway - 0.1.26 + 0.1.27 pom FHIR Information Gateway diff --git a/server/pom.xml b/server/pom.xml index 9c9dcd77..17c0db4f 100755 --- a/server/pom.xml +++ b/server/pom.xml @@ -21,7 +21,7 @@ com.google.fhir.gateway fhir-gateway - 0.1.26 + 0.1.27 server