From 4285a7a0a9da8626687de2856bf512cf8f492b86 Mon Sep 17 00:00:00 2001 From: sergiupacurariu <62688603+sergiupacurariu@users.noreply.github.com> Date: Fri, 19 Jan 2024 19:49:55 +0200 Subject: [PATCH 1/6] #12697 - Assign case(s) to a User and allow them to see the data of only the assigned case(s) in the system - additional logic - web --- .../jurisdiction/JurisdictionValidator.java | 17 +- ...ormDataJurisdictionPredicateValidator.java | 5 + .../sormas/backend/caze/CaseFacadeEjb.java | 8 +- .../CaseJurisdictionPredicateValidator.java | 15 +- .../backend/caze/CaseListCriteriaBuilder.java | 3 - .../sormas/backend/caze/CaseService.java | 12 +- .../backend/caze/CaseUserFilterCriteria.java | 9 - .../sormas/backend/common/BaseAdoService.java | 4 +- ...ContactJurisdictionPredicateValidator.java | 16 +- .../backend/contact/ContactService.java | 8 +- ...ronmentJurisdictionPredicateValidator.java | 14 +- .../environment/EnvironmentService.java | 6 +- ...nvironmentSampleJurisdictionValidator.java | 20 +- .../EnvironmentSampleService.java | 7 +- .../EventJurisdictionPredicateValidator.java | 18 +- ...icipantJurisdictionPredicateValidator.java | 16 +- .../sormas/backend/event/EventService.java | 6 +- ...izationJurisdictionPredicateValidator.java | 20 +- .../DirectoryImmunizationService.java | 35 ++- ...izationJurisdictionPredicateValidator.java | 30 +++ .../immunization/ImmunizationService.java | 50 ++-- ...MessageJurisdictionPredicateValidator.java | 7 +- .../PersonJurisdictionPredicateValidator.java | 14 ++ .../sormas/backend/person/PersonService.java | 42 ++-- .../SampleJurisdictionPredicateValidator.java | 14 +- .../sormas/backend/sample/SampleService.java | 10 +- .../TaskJurisdictionPredicateValidator.java | 30 ++- .../sormas/backend/task/TaskService.java | 16 +- ...elEntryJurisdictionPredicateValidator.java | 40 +++- .../services/BaseTravelEntryService.java | 23 ++ .../backend/user/CurrentUserService.java | 12 +- .../sormas/backend/user/UserFacadeEjb.java | 6 + .../sormas/backend/user/UserHelper.java | 15 ++ .../UserJurisdictionPredicateValidator.java | 5 + .../sormas/backend/user/UserService.java | 6 +- .../util/PredicateJurisdictionValidator.java | 3 +- .../CaseFacadeEjbPseudonymizationTest.java | 73 ++++++ .../backend/caze/CaseFacadeEjbTest.java | 2 +- .../ContactFacadeEjbPseudonymizationTest.java | 60 +++++ .../backend/contact/ContactFacadeEjbTest.java | 2 +- ...ironmentFacadeEjbPseudonymizationTest.java | 102 ++++++++ .../environment/EnvironmentFacadeEjbTest.java | 2 +- ...ntSampleFacadeEjbPseudonymizationTest.java | 170 ++++++++++++++ .../EnvironmentSampleFacadeEjbTest.java | 8 +- .../EventFacadeEjbPseudonymizationTest.java | 77 +++++++ .../backend/event/EventFacadeEjbTest.java | 2 +- ...ticipantFacadeEjbPseudonymizationTest.java | 83 +++++++ ...nizationFacadeEjbPseudonymizationTest.java | 217 ++++++++++++++++++ .../SampleFacadeEjbPseudonymizationTest.java | 87 +++++++ .../backend/sample/SampleFacadeEjbTest.java | 2 +- .../backend/task/TaskFacadeEjbTest.java | 2 +- ...velEntryFacadeEjbPseudonymizationTest.java | 163 +++++++++++++ .../symeda/sormas/ui/caze/CaseController.java | 2 +- .../symeda/sormas/ui/caze/CasePersonView.java | 5 +- .../filter/ImmunizationFilterForm.java | 4 +- .../sormas/ui/user/UserRoleCreateForm.java | 4 +- .../sormas/ui/user/UserRoleEditForm.java | 4 +- 57 files changed, 1495 insertions(+), 138 deletions(-) create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserHelper.java create mode 100644 sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbPseudonymizationTest.java create mode 100644 sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbPseudonymizationTest.java create mode 100644 sormas-backend/src/test/java/de/symeda/sormas/backend/immunization/ImmunizationFacadeEjbPseudonymizationTest.java create mode 100644 sormas-backend/src/test/java/de/symeda/sormas/backend/travelentry/TravelEntryFacadeEjbPseudonymizationTest.java diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/utils/jurisdiction/JurisdictionValidator.java b/sormas-api/src/main/java/de/symeda/sormas/api/utils/jurisdiction/JurisdictionValidator.java index d3dd839a003..6421c683438 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/utils/jurisdiction/JurisdictionValidator.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/utils/jurisdiction/JurisdictionValidator.java @@ -23,21 +23,23 @@ public abstract class JurisdictionValidator { protected List> associatedJurisdictionValidators; + private boolean userHasRestrictedAccess; - public JurisdictionValidator(List> associatedJurisdictionValidators) { + public JurisdictionValidator(List> associatedJurisdictionValidators, boolean userHasRestrictedAccess) { this.associatedJurisdictionValidators = associatedJurisdictionValidators; + this.userHasRestrictedAccess = userHasRestrictedAccess; } // disease restriction overrules entity ownership public T inJurisdictionOrOwned() { - T rootInJurisdictionOrOwned = isRootInJurisdictionOrOwned(); + T rootInJurisdictionOrOwned = isRootAccessible(); T rootHasLimitedDisease = hasUserLimitedDisease(); if (associatedJurisdictionValidators != null && !associatedJurisdictionValidators.isEmpty()) { final List jurisdictionTypes = new ArrayList<>(); jurisdictionTypes.add(and(rootInJurisdictionOrOwned, rootHasLimitedDisease)); for (JurisdictionValidator jurisdictionValidator : associatedJurisdictionValidators) { if (jurisdictionValidator != null) { - T associatedInJurisdictionOrOwned = jurisdictionValidator.isRootInJurisdictionOrOwned(); + T associatedInJurisdictionOrOwned = jurisdictionValidator.isRootAccessible(); T associatedHasLimitedDisease = jurisdictionValidator.hasUserLimitedDisease(); jurisdictionTypes.add(and(associatedInJurisdictionOrOwned, associatedHasLimitedDisease)); } @@ -68,12 +70,21 @@ public T inJurisdiction() { } } + public T isRootAccessible() { + if (userHasRestrictedAccess) { + return isRootInJurisdictionForRestrictedAccess(); + } + return isRootInJurisdictionOrOwned(); + } + public abstract T isRootInJurisdiction(); public abstract T isRootInJurisdictionOrOwned(); public abstract T hasUserLimitedDisease(); + public abstract T isRootInJurisdictionForRestrictedAccess(); + protected T isInJurisdictionByJurisdictionLevel(JurisdictionLevel jurisdictionLevel) { switch (jurisdictionLevel) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/data/CampaignFormDataJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/data/CampaignFormDataJurisdictionPredicateValidator.java index ba800042423..a77f7bd2afd 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/data/CampaignFormDataJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/data/CampaignFormDataJurisdictionPredicateValidator.java @@ -46,6 +46,11 @@ public Predicate isRootInJurisdictionOrOwned() { return cb.or(reportedByCurrentUser, isRootInJurisdiction()); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + return cb.disjunction(); + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseFacadeEjb.java index 26983a1d7fe..876f0906da5 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseFacadeEjb.java @@ -345,6 +345,7 @@ import de.symeda.sormas.backend.travelentry.services.TravelEntryService; import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.user.UserFacadeEjb; +import de.symeda.sormas.backend.user.UserHelper; import de.symeda.sormas.backend.user.UserReference; import de.symeda.sormas.backend.user.UserRoleFacadeEjb; import de.symeda.sormas.backend.user.UserRoleService; @@ -2437,7 +2438,12 @@ public void setCaseResponsible( Random rand = new Random(); if (!hospitalUsers.isEmpty()) { - caze.setSurveillanceOfficer(hospitalUsers.get(rand.nextInt(hospitalUsers.size())).getAssociatedOfficer()); + caze.setSurveillanceOfficer( + hospitalUsers.stream() + .filter(user -> !UserHelper.isRestrictedToAssignEntities(user)) + .collect(Collectors.toList()) + .get(rand.nextInt(hospitalUsers.size())) + .getAssociatedOfficer()); } else { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseJurisdictionPredicateValidator.java index f9a4f579690..ed445687126 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseJurisdictionPredicateValidator.java @@ -80,13 +80,26 @@ public Predicate isRootInJurisdiction() { @Override public Predicate isRootInJurisdictionOrOwned() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); + } + + private Predicate getReportedByCurrentUser() { final Predicate reportedByCurrentUser = cb.and( cb.isNotNull(joins.getRoot().get(Case.REPORTING_USER)), user != null ? cb.equal(joins.getRoot().get(Case.REPORTING_USER).get(User.ID), user.getId()) : cb.equal(joins.getRoot().get(Case.REPORTING_USER).get(User.ID), userPath.get(User.ID))); + return reportedByCurrentUser; + } - return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + final Predicate restrictedAccess = user != null + ? cb.equal(joins.getRoot().get(Case.SURVEILLANCE_OFFICER).get(User.ID), user.getId()) + : cb.equal(joins.getRoot().get(Case.SURVEILLANCE_OFFICER).get(User.ID), userPath.get(User.ID)); + return cb.or(reportedByCurrentUser, restrictedAccess); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseListCriteriaBuilder.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseListCriteriaBuilder.java index c2b8d5bd89d..3e13e0e79af 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseListCriteriaBuilder.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseListCriteriaBuilder.java @@ -185,9 +185,6 @@ private CriteriaQuery buildIndexCriteria( caseUserFilterCriteria.setIncludeCasesFromOtherJurisdictions(caseCriteria.getIncludeCasesFromOtherJurisdictions()); } - if (currentUserService.hasRestrictedAccessToAssignedEntities()) { - caseUserFilterCriteria.setRestrictAccessToAssignedEntities(true); - } Predicate filter = caseService.createUserFilter(caseQueryContext, caseUserFilterCriteria); if (!prefetchIds) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseService.java index 9ebaf4ffbf6..8003d85444a 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseService.java @@ -1395,7 +1395,7 @@ public Predicate createUserFilter(CaseQueryContext caseQueryContext, CaseUserFil final JurisdictionLevel jurisdictionLevel = currentUser.getJurisdictionLevel(); - if (currentUserHasRestrictedAccessToAssignedEntities()) { + if (isRestrictedToAssignedEntities()) { filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(casePath.get(Case.SURVEILLANCE_OFFICER).get(User.ID), currentUser.getId())); } @@ -1410,7 +1410,7 @@ public Predicate createUserFilter(CaseQueryContext caseQueryContext, CaseUserFil filterResponsible = cb.disjunction(); } - if (!currentUserHasRestrictedAccessToAssignedEntities()) { + if (!isRestrictedToAssignedEntities()) { switch (jurisdictionLevel) { case REGION: final Region region = currentUser.getRegion(); @@ -1687,20 +1687,12 @@ public EditPermissionType isAddContactAllowed(Case caze) { return EditPermissionType.REFUSED; } - if (currentUserHasRestrictedAccessToAssignedEntities() && !DataHelper.equal(caze.getSurveillanceOfficer(), getCurrentUser())) { - return EditPermissionType.REFUSED; - } - return super.getEditPermissionType(caze); } @Override public EditPermissionType getEditPermissionType(Case caze) { - if (currentUserHasRestrictedAccessToAssignedEntities() && !DataHelper.equal(caze.getSurveillanceOfficer(), getCurrentUser())) { - return EditPermissionType.REFUSED; - } - if (!inJurisdictionOrOwned(caze)) { return EditPermissionType.OUTSIDE_JURISDICTION; } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseUserFilterCriteria.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseUserFilterCriteria.java index 58a9cbe5687..0fa3eb01809 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseUserFilterCriteria.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseUserFilterCriteria.java @@ -8,7 +8,6 @@ public class CaseUserFilterCriteria { private boolean excludeCasesFromContacts; private Boolean includeCasesFromOtherJurisdictions = Boolean.FALSE; private boolean excludeLimitedSyncRestrictions; - private boolean restrictAccessToAssignedEntities; public boolean isExcludeCasesFromContacts() { return excludeCasesFromContacts; @@ -40,12 +39,4 @@ public CaseUserFilterCriteria excludeLimitedSyncRestrictions(boolean excludeLimi this.excludeLimitedSyncRestrictions = excludeLimitedSyncRestrictions; return this; } - - public boolean isRestrictAccessToAssignedEntities() { - return restrictAccessToAssignedEntities; - } - - public void setRestrictAccessToAssignedEntities(boolean restrictAccessToAssignedEntities) { - this.restrictAccessToAssignedEntities = restrictAccessToAssignedEntities; - } } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/common/BaseAdoService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/common/BaseAdoService.java index 1c8d252c7ae..518ea9237c9 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/common/BaseAdoService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/common/BaseAdoService.java @@ -94,8 +94,8 @@ public User getCurrentUser() { return currentUserService.getCurrentUser(); } - public boolean currentUserHasRestrictedAccessToAssignedEntities() { - return currentUserService.hasRestrictedAccessToAssignedEntities(); + public boolean isRestrictedToAssignedEntities() { + return currentUserService.isRestrictedToAssignedEntities(); } public boolean hasRight(UserRight right) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactJurisdictionPredicateValidator.java index c6fd995a537..579dc89aa2d 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactJurisdictionPredicateValidator.java @@ -77,13 +77,27 @@ public static ContactJurisdictionPredicateValidator of(ContactQueryContext qc, P @Override public Predicate isRootInJurisdictionOrOwned() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + + return cb.or(reportedByCurrentUser, inJurisdiction()); + } + + private Predicate getReportedByCurrentUser() { final Predicate reportedByCurrentUser = cb.and( cb.isNotNull(joins.getRoot().get(Contact.REPORTING_USER)), user != null ? cb.equal(joins.getRoot().get(Contact.REPORTING_USER).get(User.ID), user.getId()) : cb.equal(joins.getRoot().get(Contact.REPORTING_USER).get(User.ID), userPath.get(User.ID))); + return reportedByCurrentUser; + } - return cb.or(reportedByCurrentUser, inJurisdiction()); + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + final Predicate restrictedAccess = user != null + ? cb.equal(joins.getRoot().get(Contact.CONTACT_OFFICER).get(User.ID), user.getId()) + : cb.equal(joins.getRoot().get(Contact.CONTACT_OFFICER).get(User.ID), userPath.get(User.ID)); + return cb.or(reportedByCurrentUser, restrictedAccess); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java index c09e4a77a67..f90d0c83a6f 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java @@ -1082,7 +1082,7 @@ public Predicate createUserFilterWithoutCase(ContactQueryContext qc, ContactCrit Predicate filter = null; - if (currentUserHasRestrictedAccessToAssignedEntities()) { + if (isRestrictedToAssignedEntities()) { filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(contactRoot.get(Contact.CONTACT_OFFICER).get(User.ID), getCurrentUser().getId())); } @@ -1098,7 +1098,7 @@ public Predicate createUserFilterWithoutCase(ContactQueryContext qc, ContactCrit filter = cb.or(filter, cb.equal(contactRoot.get(Contact.CONTACT_OFFICER), currentUser)); } - if (!currentUserHasRestrictedAccessToAssignedEntities()) { + if (!isRestrictedToAssignedEntities()) { switch (jurisdictionLevel) { case REGION: final Region region = currentUser.getRegion(); @@ -1846,10 +1846,6 @@ public EditPermissionType getEditPermissionType(Contact contact) { return EditPermissionType.OUTSIDE_JURISDICTION; } - if (currentUserHasRestrictedAccessToAssignedEntities() && !DataHelper.equal(contact.getContactOfficer(), (getCurrentUser()))) { - return EditPermissionType.REFUSED; - } - if (sormasToSormasShareInfoService.isContactOwnershipHandedOver(contact) || (contact.getSormasToSormasOriginInfo() != null && !contact.getSormasToSormasOriginInfo().isOwnershipHandedOver())) { return EditPermissionType.WITHOUT_OWNERSHIP; diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentJurisdictionPredicateValidator.java index af2996049e1..df5418203d1 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentJurisdictionPredicateValidator.java @@ -51,14 +51,26 @@ public static EnvironmentJurisdictionPredicateValidator of(EnvironmentQueryConte @Override public Predicate isRootInJurisdictionOrOwned() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + return cb.or(reportedByCurrentUser, isRootInJurisdiction()); + } + private Predicate getReportedByCurrentUser() { final Predicate reportedByCurrentUser = cb.and( cb.isNotNull(joins.getRoot().get(Environment.REPORTING_USER)), user != null ? cb.equal(joins.getRoot().get(Environment.REPORTING_USER).get(User.ID), user.getId()) : cb.equal(joins.getRoot().get(Environment.REPORTING_USER).get(User.ID), userPath.get(User.ID))); + return reportedByCurrentUser; + } - return cb.or(reportedByCurrentUser, isRootInJurisdiction()); + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + final Predicate restrictedAccess = user != null + ? cb.equal(joins.getRoot().get(Environment.RESPONSIBLE_USER).get(User.ID), user.getId()) + : cb.equal(joins.getRoot().get(Environment.RESPONSIBLE_USER).get(User.ID), userPath.get(User.ID)); + return cb.or(reportedByCurrentUser, restrictedAccess); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentService.java index a0caaeb09dc..1136e2dc7c8 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentService.java @@ -90,7 +90,7 @@ public Predicate createUserFilter(EnvironmentQueryContext queryContext) { final EnvironmentJoins environmentJoins = queryContext.getJoins(); final From environmentJoin = queryContext.getRoot(); - if (currentUserHasRestrictedAccessToAssignedEntities()) { + if (isRestrictedToAssignedEntities()) { filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(environmentJoin.get(Environment.RESPONSIBLE_USER).get(User.ID), currentUser.getId())); } else { @@ -403,10 +403,6 @@ public EditPermissionType getEditPermissionType(Environment environment) { return EditPermissionType.OUTSIDE_JURISDICTION; } - if (currentUserHasRestrictedAccessToAssignedEntities() && !DataHelper.equal(environment.getResponsibleUser(), getCurrentUser())) { - return EditPermissionType.REFUSED; - } - return super.getEditPermissionType(environment); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleJurisdictionValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleJurisdictionValidator.java index 5ca583b4a31..83f0fe4497b 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleJurisdictionValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleJurisdictionValidator.java @@ -46,17 +46,6 @@ public static EnvironmentSampleJurisdictionValidator of(EnvironmentSampleQueryCo return new EnvironmentSampleJurisdictionValidator(qc.getCriteriaBuilder(), user, qc.getJoins(), null); } - public Predicate isRootInJurisdictionOrOwned(boolean currentHasUserRestrictedAccess) { - if (currentHasUserRestrictedAccess) { - final Predicate reportedByCurrentUser = getReportedByCurrentUserPredicate(); - final Predicate restrictedAccess = - cb.equal(joins.getEnvironment().get(Environment.RESPONSIBLE_USER).get(User.ID), user.getChangeUser().getId()); - return cb.or(reportedByCurrentUser, restrictedAccess); - } else { - return isRootInJurisdictionOrOwned(); - } - } - private Predicate getReportedByCurrentUserPredicate() { return cb.and( cb.isNotNull(joins.getRoot().get(EnvironmentSample.REPORTING_USER)), @@ -71,6 +60,15 @@ public Predicate isRootInJurisdictionOrOwned() { return cb.or(reportedByCurrentUser, isRootInJurisdiction()); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate reportedByCurrentUser = getReportedByCurrentUserPredicate(); + final Predicate restrictedAccess = user != null + ? cb.equal(joins.getEnvironment().get(Environment.RESPONSIBLE_USER).get(User.ID), user.getId()) + : cb.equal(joins.getEnvironment().get(Environment.RESPONSIBLE_USER).get(User.ID), userPath.get(User.ID)); + return cb.or(reportedByCurrentUser, restrictedAccess); + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleService.java index e443f2320b4..d961e7dbb30 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleService.java @@ -197,9 +197,14 @@ public Predicate buildCriteriaFilter(EnvironmentSampleCriteria criteria, Environ } private Predicate inJurisdictionOrOwned(CriteriaBuilder cb, CriteriaQuery cq, From from) { + if (isRestrictedToAssignedEntities()) { + return EnvironmentSampleJurisdictionValidator + .of(new EnvironmentSampleQueryContext(cb, cq, from, new EnvironmentSampleJoins(from)), userService.getCurrentUser()) + .isRootInJurisdictionForRestrictedAccess(); + } return EnvironmentSampleJurisdictionValidator .of(new EnvironmentSampleQueryContext(cb, cq, from, new EnvironmentSampleJoins(from)), userService.getCurrentUser()) - .isRootInJurisdictionOrOwned(currentUserHasRestrictedAccessToAssignedEntities()); + .isRootInJurisdictionOrOwned(); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventJurisdictionPredicateValidator.java index 16873d588c5..40921480a93 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventJurisdictionPredicateValidator.java @@ -59,20 +59,34 @@ public Predicate isRootInJurisdiction() { @Override public Predicate isRootInJurisdictionOrOwned() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + final Predicate currentUserResponsible = getCurrentUserResponsible(); + return cb.or(reportedByCurrentUser, currentUserResponsible, this.isRootInJurisdiction()); + } + + private Predicate getReportedByCurrentUser() { final Predicate reportedByCurrentUser = cb.and( cb.isNotNull(joins.getRoot().get(Event.REPORTING_USER)), user != null ? cb.equal(joins.getRoot().get(Event.REPORTING_USER).get(User.ID), user.getId()) : cb.equal(joins.getRoot().get(Event.REPORTING_USER).get(User.ID), userPath.get(User.ID))); + return reportedByCurrentUser; + } - final Predicate currentUserResponsible = cb.and( + private Predicate getCurrentUserResponsible() { + return cb.and( cb.isNotNull(joins.getRoot().get(Event.RESPONSIBLE_USER)), user != null ? cb.equal(joins.getRoot().get(Event.RESPONSIBLE_USER).get(User.ID), user.getId()) : cb.equal(joins.getRoot().get(Event.RESPONSIBLE_USER).get(User.ID), userPath.get(User.ID))); + } - return cb.or(reportedByCurrentUser, currentUserResponsible, this.isRootInJurisdiction()); + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + final Predicate currentUserResponsible = getCurrentUserResponsible(); + return cb.or(reportedByCurrentUser, currentUserResponsible); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantJurisdictionPredicateValidator.java index 25a3b376a8a..51ab0b440e8 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantJurisdictionPredicateValidator.java @@ -46,10 +46,24 @@ public static EventParticipantJurisdictionPredicateValidator of(EventParticipant @Override public Predicate isRootInJurisdictionOrOwned() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); + } + + private Predicate getReportedByCurrentUser() { final Predicate reportedByCurrentUser = cb.and( cb.isNotNull(joins.getRoot().get(EventParticipant.REPORTING_USER)), cb.equal(joins.getRoot().get(EventParticipant.REPORTING_USER).get(User.ID), user.getId())); - return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); + return reportedByCurrentUser; + } + + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + final Predicate restrictedAccess = user != null + ? cb.equal(joins.getEvent().get(Event.RESPONSIBLE_USER).get(User.ID), user.getId()) + : cb.equal(joins.getEvent().get(Event.RESPONSIBLE_USER).get(User.ID), userPath.get(User.ID)); + return cb.or(reportedByCurrentUser, restrictedAccess); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventService.java index a6173b103d0..7f3af660e3a 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventService.java @@ -466,7 +466,7 @@ public Predicate createUserFilter(final EventQueryContext queryContext, final Ev final EventJoins eventJoins = queryContext.getJoins(); final From eventJoin = queryContext.getRoot(); - if (currentUserHasRestrictedAccessToAssignedEntities()) { + if (isRestrictedToAssignedEntities()) { filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(eventJoin.get(Event.RESPONSIBLE_USER).get(User.ID), currentUser.getId())); } else { if (jurisdictionLevel != JurisdictionLevel.NATION) { @@ -1067,10 +1067,6 @@ public EditPermissionType getEditPermissionType(Event event) { return EditPermissionType.OUTSIDE_JURISDICTION; } - if (currentUserHasRestrictedAccessToAssignedEntities() && !DataHelper.equal(event.getResponsibleUser(), getCurrentUser())) { - return EditPermissionType.REFUSED; - } - if (sormasToSormasShareInfoService.isEventOwnershipHandedOver(event) || event.getSormasToSormasOriginInfo() != null && !event.getSormasToSormasOriginInfo().isOwnershipHandedOver()) { return EditPermissionType.WITHOUT_OWNERSHIP; diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationJurisdictionPredicateValidator.java index fc30cdb99dc..0f9d5450b60 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationJurisdictionPredicateValidator.java @@ -17,18 +17,21 @@ public final class DirectoryImmunizationJurisdictionPredicateValidator extends PredicateJurisdictionValidator { private final DirectoryImmunizationJoins joins; + private final DirectoryImmunizationQueryContext queryContext; private DirectoryImmunizationJurisdictionPredicateValidator( CriteriaBuilder cb, DirectoryImmunizationJoins joins, User user, - List associatedJurisdictionValidators) { + List associatedJurisdictionValidators, + DirectoryImmunizationQueryContext queryContext) { super(cb, user, null, associatedJurisdictionValidators); this.joins = joins; + this.queryContext = queryContext; } public static DirectoryImmunizationJurisdictionPredicateValidator of(DirectoryImmunizationQueryContext qc, User user) { - return new DirectoryImmunizationJurisdictionPredicateValidator(qc.getCriteriaBuilder(), qc.getJoins(), user, null); + return new DirectoryImmunizationJurisdictionPredicateValidator(qc.getCriteriaBuilder(), qc.getJoins(), user, null, qc); } @Override @@ -38,9 +41,20 @@ public Predicate isRootInJurisdiction() { @Override public Predicate isRootInJurisdictionOrOwned() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); + } + + private Predicate getReportedByCurrentUser() { final Path reportingUserPath = joins.getRoot().get(Immunization.REPORTING_USER); final Predicate reportedByCurrentUser = cb.and(cb.isNotNull(reportingUserPath), cb.equal(reportingUserPath.get(User.ID), user.getId())); - return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); + return reportedByCurrentUser; + } + + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + //for restricted access the immunization is only accessible when the associated person is accessible + return cb.disjunction(); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationService.java index e13631acc9c..fe7e74052d1 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationService.java @@ -3,7 +3,9 @@ import static de.symeda.sormas.backend.common.CriteriaBuilderHelper.andEquals; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -12,6 +14,7 @@ import javax.ejb.LocalBean; import javax.ejb.Stateless; import javax.persistence.Tuple; +import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; @@ -33,6 +36,8 @@ import de.symeda.sormas.api.immunization.ImmunizationDateType; import de.symeda.sormas.api.immunization.ImmunizationIndexDto; import de.symeda.sormas.api.immunization.ImmunizationManagementStatus; +import de.symeda.sormas.api.person.PersonAssociation; +import de.symeda.sormas.api.person.PersonCriteria; import de.symeda.sormas.api.person.PersonIndexDto; import de.symeda.sormas.api.utils.DataHelper; import de.symeda.sormas.api.utils.DateHelper; @@ -143,7 +148,7 @@ public List getIndexList(ImmunizationCriteria criteria, In private List getIndexListIds(ImmunizationCriteria criteria, Integer first, Integer max, List sortProperties) { final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createTupleQuery();; + final CriteriaQuery cq = cb.createTupleQuery(); final Root immunization = cq.from(DirectoryImmunization.class); DirectoryImmunizationQueryContext directoryImmunizationQueryContext = new DirectoryImmunizationQueryContext(cb, cq, immunization); @@ -396,8 +401,27 @@ private Predicate createUserFilter(DirectoryImmunizationQueryContext qc) { return null; } final CriteriaBuilder cb = qc.getCriteriaBuilder(); + Predicate filter = null; + + if (isRestrictedToAssignedEntities()) { + final PersonQueryContext personQueryContext = new PersonQueryContext(cb, qc.getQuery(), qc.getJoins().getPersonJoins()); + + final PersonCriteria personCaseCriteria = new PersonCriteria(); + personCaseCriteria.setPersonAssociation(PersonAssociation.CASE); + final Predicate personCaseUserFilter = personService.createUserFilter(personQueryContext, personCaseCriteria); + + final PersonCriteria personContactCriteria = new PersonCriteria(); + personContactCriteria.setPersonAssociation(PersonAssociation.CONTACT); + final Predicate personContactUserFilter = personService.createUserFilter(personQueryContext, personContactCriteria); - Predicate filter = isInJurisdictionOrOwned(qc); + final PersonCriteria personEventParticipantCriteria = new PersonCriteria(); + personEventParticipantCriteria.setPersonAssociation(PersonAssociation.EVENT_PARTICIPANT); + final Predicate personEventParticipantUserFilter = personService.createUserFilter(personQueryContext, personEventParticipantCriteria); + + filter = CriteriaBuilderHelper.and(cb, filter, cb.or(personCaseUserFilter, personContactUserFilter, personEventParticipantUserFilter)); + } else { + filter = isInJurisdictionOrOwned(qc); + } filter = CriteriaBuilderHelper .and(cb, filter, CriteriaBuilderHelper.limitedDiseasePredicate(cb, currentUser, qc.getRoot().get(Immunization.DISEASE))); @@ -417,7 +441,12 @@ private Predicate isInJurisdictionOrOwned(DirectoryImmunizationQueryContext qc) cb, cb.equal(qc.getRoot().get(Immunization.REPORTING_USER), currentUser), PersonJurisdictionPredicateValidator - .of(qc.getQuery(), cb, new PersonJoins(qc.getJoins().getPerson()), currentUser, personService.getPermittedAssociations()) + .of( + qc.getQuery(), + cb, + new PersonJoins(qc.getJoins().getPerson()), + currentUser, + new HashSet<>(Arrays.asList(PersonAssociation.CASE, PersonAssociation.CONTACT, PersonAssociation.EVENT_PARTICIPANT))) .inJurisdictionOrOwned()); } return filter; diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationJurisdictionPredicateValidator.java index c3d93818271..0c4a4adec42 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationJurisdictionPredicateValidator.java @@ -15,24 +15,32 @@ package de.symeda.sormas.backend.immunization; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import javax.persistence.criteria.Subquery; +import de.symeda.sormas.api.person.PersonAssociation; +import de.symeda.sormas.backend.common.AbstractDomainObject; import de.symeda.sormas.backend.immunization.entity.Immunization; import de.symeda.sormas.backend.infrastructure.community.Community; import de.symeda.sormas.backend.infrastructure.district.District; import de.symeda.sormas.backend.infrastructure.facility.Facility; import de.symeda.sormas.backend.infrastructure.region.Region; +import de.symeda.sormas.backend.person.PersonJurisdictionPredicateValidator; import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.util.PredicateJurisdictionValidator; public class ImmunizationJurisdictionPredicateValidator extends PredicateJurisdictionValidator { private final ImmunizationJoins joins; + private final CriteriaQuery cq; private ImmunizationJurisdictionPredicateValidator( CriteriaQuery cq, @@ -43,6 +51,7 @@ private ImmunizationJurisdictionPredicateValidator( super(cb, user, null, associatedJurisdictionValidators); this.joins = joins; + this.cq = cq; } public static ImmunizationJurisdictionPredicateValidator of(ImmunizationQueryContext qc, User user) { @@ -61,6 +70,27 @@ public Predicate isRootInJurisdictionOrOwned() { return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + Predicate isRootInJurisdiction = isRootInJurisdictionOrOwned(); + + Subquery personSubquery = cq.subquery(Boolean.class); + final Root from = personSubquery.from(Immunization.class); + ImmunizationJoins immunizationJoins = new ImmunizationJoins(from); + final Predicate isPersonInJurisdiction = PersonJurisdictionPredicateValidator + .of( + cq, + cb, + immunizationJoins.getPersonJoins(), + user, + new HashSet<>(Arrays.asList(PersonAssociation.CASE, PersonAssociation.CONTACT, PersonAssociation.EVENT_PARTICIPANT))) + .isRootInJurisdictionForRestrictedAccess(); + personSubquery.select(from.get(AbstractDomainObject.ID)); + personSubquery.where(isPersonInJurisdiction, cb.equal(from.get(AbstractDomainObject.ID), joins.getRoot().get(AbstractDomainObject.ID))); + + return and(isRootInJurisdiction, cb.exists(personSubquery)); + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationService.java index 9d300d907a6..aaff5434809 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationService.java @@ -17,9 +17,12 @@ import java.sql.Timestamp; import java.time.Instant; +import java.util.Arrays; import java.util.Date; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.stream.Collectors; import javax.ejb.EJB; import javax.ejb.LocalBean; @@ -49,6 +52,8 @@ import de.symeda.sormas.api.immunization.ImmunizationSimilarityCriteria; import de.symeda.sormas.api.immunization.ImmunizationStatus; import de.symeda.sormas.api.immunization.MeansOfImmunization; +import de.symeda.sormas.api.person.PersonAssociation; +import de.symeda.sormas.api.person.PersonCriteria; import de.symeda.sormas.api.sormastosormas.share.incoming.ShareRequestStatus; import de.symeda.sormas.backend.caze.Case; import de.symeda.sormas.backend.common.AbstractCoreAdoService; @@ -65,6 +70,7 @@ import de.symeda.sormas.backend.person.Person; import de.symeda.sormas.backend.person.PersonJoins; import de.symeda.sormas.backend.person.PersonJurisdictionPredicateValidator; +import de.symeda.sormas.backend.person.PersonQueryContext; import de.symeda.sormas.backend.person.PersonService; import de.symeda.sormas.backend.sormastosormas.origin.SormasToSormasOriginInfo; import de.symeda.sormas.backend.sormastosormas.share.outgoing.ShareRequestInfo; @@ -80,6 +86,7 @@ import de.symeda.sormas.backend.util.QueryHelper; import de.symeda.sormas.backend.vaccination.LastVaccinationDate; import de.symeda.sormas.backend.vaccination.Vaccination; +import org.hibernate.query.Query; @Stateless @LocalBean @@ -170,24 +177,17 @@ public Predicate inJurisdictionOrOwned(ImmunizationQueryContext qc) { cb, cb.equal(qc.getRoot().get(Immunization.REPORTING_USER), currentUser), PersonJurisdictionPredicateValidator - .of(qc.getQuery(), cb, new PersonJoins(qc.getJoins().getPerson()), currentUser, personService.getPermittedAssociations()) + .of( + qc.getQuery(), + cb, + new PersonJoins(qc.getJoins().getPerson()), + currentUser, + new HashSet<>(Arrays.asList(PersonAssociation.CASE, PersonAssociation.CONTACT, PersonAssociation.EVENT_PARTICIPANT))) .inJurisdictionOrOwned()); } return filter; } - @Override - public boolean inJurisdictionOrOwned(Immunization immunization) { - - CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaQuery cq = cb.createQuery(Boolean.class); - Root root = cq.from(Immunization.class); - // Deviation from super implementation: createUserFilter - cq.multiselect(JurisdictionHelper.booleanSelector(cb, createUserFilter(new ImmunizationQueryContext(cb, cq, root)))); - cq.where(cb.equal(root.get(Immunization.UUID), immunization.getUuid())); - return em.createQuery(cq).getResultStream().anyMatch(isInJurisdiction -> isInJurisdiction); - } - public Predicate createActiveImmunizationsFilter(CriteriaBuilder cb, From root) { return cb.and(cb.isFalse(root.get(Immunization.ARCHIVED)), cb.isFalse(root.get(Immunization.DELETED))); } @@ -557,9 +557,29 @@ public Predicate createUserFilter(ImmunizationQueryContext qc) { return null; } - Predicate filter = inJurisdictionOrOwned(qc); - final CriteriaBuilder cb = qc.getCriteriaBuilder(); + Predicate filter = null; + if (isRestrictedToAssignedEntities()) { + final PersonQueryContext personQueryContext = new PersonQueryContext(cb, qc.getQuery(), qc.getJoins().getPersonJoins()); + + final PersonCriteria personCaseCriteria = new PersonCriteria(); + personCaseCriteria.setPersonAssociation(PersonAssociation.CASE); + final Predicate personCaseUserFilter = personService.createUserFilter(personQueryContext, personCaseCriteria); + + final PersonCriteria personContactCriteria = new PersonCriteria(); + personContactCriteria.setPersonAssociation(PersonAssociation.CONTACT); + final Predicate personContactUserFilter = personService.createUserFilter(personQueryContext, personContactCriteria); + + final PersonCriteria personEventParticipantCriteria = new PersonCriteria(); + personEventParticipantCriteria.setPersonAssociation(PersonAssociation.EVENT_PARTICIPANT); + final Predicate personEventParticipantUserFilter = personService.createUserFilter(personQueryContext, personEventParticipantCriteria); + + filter = CriteriaBuilderHelper.and(cb, filter, cb.or(personCaseUserFilter, personContactUserFilter, personEventParticipantUserFilter)); + + } else { + filter = inJurisdictionOrOwned(qc); + } + filter = CriteriaBuilderHelper .and(cb, filter, CriteriaBuilderHelper.limitedDiseasePredicate(cb, currentUser, qc.getRoot().get(Immunization.DISEASE))); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/manualmessagelog/ManualMessageJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/manualmessagelog/ManualMessageJurisdictionPredicateValidator.java index 1af826fbde6..3c118343850 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/manualmessagelog/ManualMessageJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/manualmessagelog/ManualMessageJurisdictionPredicateValidator.java @@ -56,9 +56,14 @@ public Predicate isRootInJurisdictionOrOwned() { throw new UnsupportedOperationException("Jurisdiction validation should woprk through person"); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + throw new UnsupportedOperationException("Jurisdiction validation should work through person"); + } + @Override protected Predicate whenNotAllowed() { - throw new UnsupportedOperationException("Jurisdiction validation should woprk through person"); + throw new UnsupportedOperationException("Jurisdiction validation should work through person"); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonJurisdictionPredicateValidator.java index 71f3bd93bc8..7f6800a33db 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonJurisdictionPredicateValidator.java @@ -24,6 +24,7 @@ import javax.persistence.criteria.Predicate; import de.symeda.sormas.api.person.PersonAssociation; +import de.symeda.sormas.api.utils.jurisdiction.JurisdictionValidator; import de.symeda.sormas.backend.caze.CaseJurisdictionPredicateValidator; import de.symeda.sormas.backend.caze.CaseQueryContext; import de.symeda.sormas.backend.contact.ContactJurisdictionPredicateValidator; @@ -101,6 +102,19 @@ public Predicate isRootInJurisdiction() { return cb.disjunction(); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + List associationPredicates = new ArrayList<>(associatedJurisdictionValidators.size()); + for (JurisdictionValidator associatedJurisdictionValidator : associatedJurisdictionValidators) { + if (!TravelEntryJurisdictionPredicateValidator.class.isAssignableFrom(associatedJurisdictionValidator.getClass()) + && !ImmunizationJurisdictionPredicateValidator.class.isAssignableFrom(associatedJurisdictionValidator.getClass())) { + associationPredicates.add(associatedJurisdictionValidator.isRootInJurisdictionForRestrictedAccess()); + } + } + return or(associationPredicates); + + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonService.java index d4c09b19fe2..49e5b749550 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonService.java @@ -116,6 +116,7 @@ import de.symeda.sormas.backend.user.UserService; import de.symeda.sormas.backend.util.ExternalDataUtil; import de.symeda.sormas.backend.util.IterableHelper; +import de.symeda.sormas.backend.util.JurisdictionHelper; import de.symeda.sormas.backend.util.ModelConstants; import de.symeda.sormas.backend.visit.VisitService; @@ -294,8 +295,17 @@ public Predicate createUserFilter(PersonQueryContext queryContext, PersonCriteri createAssociationPredicate(queryContext, PersonAssociation.TRAVEL_ENTRY)); break; case CASE: + userFilter = + CriteriaBuilderHelper.or(queryContext.getCriteriaBuilder(), createAssociationPredicate(queryContext, PersonAssociation.CASE)); + break; case CONTACT: + userFilter = + CriteriaBuilderHelper.or(queryContext.getCriteriaBuilder(), createAssociationPredicate(queryContext, PersonAssociation.CONTACT)); + break; case EVENT_PARTICIPANT: + userFilter = CriteriaBuilderHelper + .or(queryContext.getCriteriaBuilder(), createAssociationPredicate(queryContext, PersonAssociation.EVENT_PARTICIPANT)); + break; case IMMUNIZATION: case TRAVEL_ENTRY: userFilter = createAssociationPredicate(queryContext, personAssociation); @@ -352,16 +362,24 @@ private Predicate createAssociationPredicate(@NotNull PersonQueryContext queryCo eventParticipantService.createDefaultFilter(cb, joins.getEventParticipant())); break; case IMMUNIZATION: - associationPredicate = CriteriaBuilderHelper.and( - cb, - immunizationService.createUserFilter(new ImmunizationQueryContext(cb, cq, joins.getImmunizationJoins())), - immunizationService.createDefaultFilter(cb, joins.getImmunization())); + if (!isRestrictedToAssignedEntities()) { + associationPredicate = CriteriaBuilderHelper.and( + cb, + immunizationService.createUserFilter(new ImmunizationQueryContext(cb, cq, joins.getImmunizationJoins())), + immunizationService.createDefaultFilter(cb, joins.getImmunization())); + } else { + associationPredicate = CriteriaBuilderHelper.and(cb, cb.disjunction()); + } break; case TRAVEL_ENTRY: - associationPredicate = CriteriaBuilderHelper.and( - cb, - travelEntryService.createUserFilter(new TravelEntryQueryContext(cb, cq, joins.getTravelEntryJoins())), - travelEntryService.createDefaultFilter(cb, joins.getTravelEntry())); + if (!isRestrictedToAssignedEntities()) { + associationPredicate = CriteriaBuilderHelper.and( + cb, + travelEntryService.createUserFilter(new TravelEntryQueryContext(cb, cq, joins.getTravelEntryJoins())), + travelEntryService.createDefaultFilter(cb, joins.getTravelEntry())); + } else { + associationPredicate = CriteriaBuilderHelper.and(cb, cb.disjunction()); + } break; case ALL: default: @@ -1093,14 +1111,10 @@ public boolean isEditAllowed(String personUuid) { cq.where( cb.equal(from.get(Person.UUID), personUuid), + cb.equal(JurisdictionHelper.booleanSelector(cb, inJurisdictionOrOwned(new PersonQueryContext(cb, cq, from))), true), cb.or( cb.and( - cb.and( - cb.isNotNull(joins.getCaze()), - cb.isFalse(joins.getCaze().get(Case.DELETED)), - currentUserHasRestrictedAccessToAssignedEntities() - ? cb.equal(joins.getCaze().get(Case.SURVEILLANCE_OFFICER).get(User.ID), getCurrentUser().getId()) - : cb.conjunction()), + cb.and(cb.isNotNull(joins.getCaze()), cb.isFalse(joins.getCaze().get(Case.DELETED))), caseService.createOwnershipPredicate(true, joins.getCaze(), cb, cq)), cb.and( cb.and(cb.isNotNull(joins.getContact()), cb.isFalse(joins.getContact().get(Contact.DELETED))), diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleJurisdictionPredicateValidator.java index 790bb1ba7ca..1a0b98cb8f6 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleJurisdictionPredicateValidator.java @@ -92,7 +92,8 @@ public Predicate isRootInJurisdictionOrOwned() { @Override public Predicate inJurisdictionOrOwned() { - Predicate rootInJurisdictionOrOwned = isRootInJurisdictionOrOwned(); +// Predicate rootInJurisdictionOrOwned = isRootInJurisdictionOrOwned(); + Predicate rootInJurisdictionOrOwned = isRootAccessible(); Predicate rootHasLimitedDisease = hasUserLimitedDisease(); if (associatedJurisdictionValidators != null && !associatedJurisdictionValidators.isEmpty()) { final List jurisdictionTypes = new ArrayList<>(); @@ -101,7 +102,7 @@ public Predicate inJurisdictionOrOwned() { diseaseJurisdictionTypes.add(rootHasLimitedDisease); for (JurisdictionValidator jurisdictionValidator : associatedJurisdictionValidators) { if (jurisdictionValidator != null) { - Predicate associatedInJurisdictionOrOwned = jurisdictionValidator.isRootInJurisdictionOrOwned(); + Predicate associatedInJurisdictionOrOwned = jurisdictionValidator.isRootAccessible(); Predicate associatedHasLimitedDisease = jurisdictionValidator.hasUserLimitedDisease(); jurisdictionTypes.add(associatedInJurisdictionOrOwned); diseaseJurisdictionTypes.add(associatedHasLimitedDisease); @@ -135,6 +136,15 @@ public Predicate inJurisdiction() { } } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + List associationPredicates = new ArrayList<>(associatedJurisdictionValidators.size()); + for (JurisdictionValidator associatedJurisdictionValidator : associatedJurisdictionValidators) { + associationPredicates.add(associatedJurisdictionValidator.isRootInJurisdictionForRestrictedAccess()); + } + return or(associationPredicates); + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleService.java index 98be6064c07..1c02c6e4ed2 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleService.java @@ -660,10 +660,10 @@ public Predicate createUserFilter(SampleQueryContext sampleQueryContext, SampleC cb, filter, caseService.createUserFilter(new CaseQueryContext(cb, cq, joins.getCaseJoins()), null), - RequestContextHolder.isMobileSync() + RequestContextHolder.isMobileSync() && !isRestrictedToAssignedEntities() ? null : contactService.createUserFilter(new ContactQueryContext(cb, cq, joins.getContactJoins()), null), - RequestContextHolder.isMobileSync() + RequestContextHolder.isMobileSync() && !isRestrictedToAssignedEntities() ? null : eventParticipantService.createUserFilter(new EventParticipantQueryContext(cb, cq, joins.getEventParticipantJoins()))); } @@ -723,16 +723,18 @@ public Subquery exists(CriteriaBuilder cb, CriteriaQuery cq, Join @Override public SampleJurisdictionFlagsDto getJurisdictionFlags(Sample entity) { - return getJurisdictionsFlags(Collections.singletonList(entity)).get(entity.getId()); + final SampleJurisdictionFlagsDto sampleJurisdictionFlagsDto = getJurisdictionsFlags(Collections.singletonList(entity)).get(entity.getId()); + return sampleJurisdictionFlagsDto; } @Override public Map getJurisdictionsFlags(List entities) { - return getSelectionAttributes( + final Map selectionAttributes = getSelectionAttributes( entities, (cb, cq, from) -> getJurisdictionSelections(new SampleQueryContext(cb, cq, from)), e -> new SampleJurisdictionFlagsDto(e)); + return selectionAttributes; } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskJurisdictionPredicateValidator.java index 6fdcc1ef91d..a1389874152 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskJurisdictionPredicateValidator.java @@ -21,12 +21,15 @@ import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.Predicate; +import de.symeda.sormas.api.utils.jurisdiction.JurisdictionValidator; import de.symeda.sormas.backend.caze.CaseJurisdictionPredicateValidator; import de.symeda.sormas.backend.caze.CaseQueryContext; import de.symeda.sormas.backend.contact.ContactJurisdictionPredicateValidator; import de.symeda.sormas.backend.contact.ContactQueryContext; import de.symeda.sormas.backend.event.EventJurisdictionPredicateValidator; import de.symeda.sormas.backend.event.EventQueryContext; +import de.symeda.sormas.backend.immunization.ImmunizationJurisdictionPredicateValidator; +import de.symeda.sormas.backend.travelentry.TravelEntryJurisdictionPredicateValidator; import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.util.PredicateJurisdictionValidator; @@ -61,11 +64,19 @@ public static TaskJurisdictionPredicateValidator of(TaskQueryContext qc, User us @Override public Predicate isRootInJurisdictionOrOwned() { - final Predicate createdByCurrentUser = cb.and(cb.isNotNull(joins.getCreator()), cb.equal(joins.getCreator().get(User.UUID), user.getUuid())); + final Predicate createdByCurrentUser = getCreatedByCurrentUser(); + final Predicate assignedToCurrentUser = getAssignedToCurrentUser(); + return cb.or(createdByCurrentUser, assignedToCurrentUser, isRootInJurisdiction()); + } + private Predicate getAssignedToCurrentUser() { final Predicate assignedToCurrentUser = cb.and(cb.isNotNull(joins.getAssignee()), cb.equal(joins.getAssignee().get(User.UUID), user.getUuid())); - return cb.or(createdByCurrentUser, assignedToCurrentUser, isRootInJurisdiction()); + return assignedToCurrentUser; + } + + private Predicate getCreatedByCurrentUser() { + return cb.and(cb.isNotNull(joins.getCreator()), cb.equal(joins.getCreator().get(User.UUID), user.getUuid())); } @Override @@ -73,6 +84,21 @@ public Predicate isRootInJurisdiction() { return isInJurisdictionByJurisdictionLevel(user.getJurisdictionLevel()); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate createdByCurrentUser = getCreatedByCurrentUser(); + final Predicate assignedToCurrentUser = getAssignedToCurrentUser(); + + List associationPredicates = new ArrayList<>(associatedJurisdictionValidators.size()); + for (JurisdictionValidator associatedJurisdictionValidator : associatedJurisdictionValidators) { + if (!TravelEntryJurisdictionPredicateValidator.class.isAssignableFrom(associatedJurisdictionValidator.getClass()) + && !ImmunizationJurisdictionPredicateValidator.class.isAssignableFrom(associatedJurisdictionValidator.getClass())) { + associationPredicates.add(associatedJurisdictionValidator.isRootInJurisdictionForRestrictedAccess()); + } + } + return cb.or(createdByCurrentUser, assignedToCurrentUser, or(associationPredicates)); + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskService.java index cdf58fa3342..27bc27c9653 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskService.java @@ -41,7 +41,9 @@ import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.persistence.criteria.Selection; +import javax.persistence.criteria.Subquery; +import de.symeda.sormas.backend.util.JurisdictionHelper; import org.apache.commons.lang3.ArrayUtils; import de.symeda.sormas.api.EditPermissionType; @@ -90,7 +92,6 @@ import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.user.UserRole; import de.symeda.sormas.backend.user.UserService; -import de.symeda.sormas.backend.util.JurisdictionHelper; @Stateless @LocalBean @@ -220,7 +221,7 @@ public Predicate createUserFilter(TaskQueryContext taskQueryContext, TaskCriteri TaskJoins joins = taskQueryContext.getJoins(); Predicate assigneeFilter; - if (currentUserHasRestrictedAccessToAssignedEntities()) { + if (isRestrictedToAssignedEntities()) { assigneeFilter = cb.disjunction(); } else { assigneeFilter = createAssigneeFilter(cb, joins.getAssignee()); @@ -863,6 +864,17 @@ public List> getJurisdictionSelections(TaskQueryContext qc) { environmentService.inJurisdictionOrOwned(new EnvironmentQueryContext(cb, qc.getQuery(), joins.getEnvironmentJoins()))))); } + private Predicate getObjectSubquery(TaskQueryContext qc, CriteriaBuilder cb, Function jurisdictionPredicate) { + Subquery inJurisditionSubquery = qc.getQuery().subquery(Object.class); + final Root from = inJurisditionSubquery.from(Task.class); + TaskJoins taskJoins = new TaskJoins(from); + inJurisditionSubquery.select(from.get(AbstractDomainObject.ID)); + inJurisditionSubquery + .where(jurisdictionPredicate.apply(taskJoins), cb.equal(from.get(AbstractDomainObject.ID), qc.getRoot().get(AbstractDomainObject.ID))); + + return cb.exists(inJurisditionSubquery); + } + @Override public Predicate inJurisdictionOrOwned(TaskQueryContext qc) { final User currentUser = userService.getCurrentUser(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/TravelEntryJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/TravelEntryJurisdictionPredicateValidator.java index 925cf35e6a8..61f9a7f53d3 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/TravelEntryJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/TravelEntryJurisdictionPredicateValidator.java @@ -1,26 +1,34 @@ package de.symeda.sormas.backend.travelentry; +import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import javax.persistence.criteria.Subquery; +import de.symeda.sormas.api.person.PersonAssociation; import de.symeda.sormas.backend.caze.CaseJurisdictionPredicateValidator; import de.symeda.sormas.backend.caze.CaseQueryContext; +import de.symeda.sormas.backend.common.AbstractDomainObject; import de.symeda.sormas.backend.common.CriteriaBuilderHelper; import de.symeda.sormas.backend.infrastructure.community.Community; import de.symeda.sormas.backend.infrastructure.district.District; import de.symeda.sormas.backend.infrastructure.pointofentry.PointOfEntry; import de.symeda.sormas.backend.infrastructure.region.Region; +import de.symeda.sormas.backend.person.PersonJurisdictionPredicateValidator; import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.util.PredicateJurisdictionValidator; public class TravelEntryJurisdictionPredicateValidator extends PredicateJurisdictionValidator { private final TravelEntryJoins joins; + private final CriteriaQuery cq; private TravelEntryJurisdictionPredicateValidator( CriteriaQuery cq, @@ -30,6 +38,7 @@ private TravelEntryJurisdictionPredicateValidator( List associatedJurisdictionValidators) { super(cb, user, null, associatedJurisdictionValidators); this.joins = joins; + this.cq = cq; } private TravelEntryJurisdictionPredicateValidator( @@ -40,6 +49,7 @@ private TravelEntryJurisdictionPredicateValidator( List associatedJurisdictionValidators) { super(cb, null, userPath, associatedJurisdictionValidators); this.joins = joins; + this.cq = cq; } public static TravelEntryJurisdictionPredicateValidator of(TravelEntryQueryContext qc, User user) { @@ -50,7 +60,7 @@ public static TravelEntryJurisdictionPredicateValidator of(TravelEntryQueryConte user, Collections.singletonList( CaseJurisdictionPredicateValidator - .of(new CaseQueryContext(qc.getCriteriaBuilder(), qc.getQuery(), ((TravelEntryJoins) qc.getJoins()).getResultingCase()), user))); + .of(new CaseQueryContext(qc.getCriteriaBuilder(), qc.getQuery(), (qc.getJoins()).getResultingCase()), user))); } public static TravelEntryJurisdictionPredicateValidator of(TravelEntryQueryContext qc, Path userPath) { @@ -60,9 +70,8 @@ public static TravelEntryJurisdictionPredicateValidator of(TravelEntryQueryConte qc.getJoins(), userPath, Collections.singletonList( - CaseJurisdictionPredicateValidator.of( - new CaseQueryContext(qc.getCriteriaBuilder(), qc.getQuery(), ((TravelEntryJoins) qc.getJoins()).getResultingCase()), - userPath))); + CaseJurisdictionPredicateValidator + .of(new CaseQueryContext(qc.getCriteriaBuilder(), qc.getQuery(), (qc.getJoins()).getResultingCase()), userPath))); } @Override @@ -81,6 +90,29 @@ public Predicate isRootInJurisdictionOrOwned() { return cb.or(reportedByCurrentUser, isRootInJurisdiction()); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + Predicate isRootInJurisdiction = isRootInJurisdictionOrOwned(); + + Subquery personSubquery = cq.subquery(Boolean.class); + final Root from = personSubquery.from(TravelEntry.class); + TravelEntryJoins travelEntryJoins = new TravelEntryJoins(from); + + final Predicate isPersonInJurisdiction = PersonJurisdictionPredicateValidator + .of( + cq, + cb, + travelEntryJoins.getPersonJoins(), + user, + new HashSet<>(Arrays.asList(PersonAssociation.CASE, PersonAssociation.CONTACT, PersonAssociation.EVENT_PARTICIPANT))) + .isRootInJurisdictionForRestrictedAccess(); + + personSubquery.select(from.get(AbstractDomainObject.ID)); + personSubquery.where(isPersonInJurisdiction, cb.equal(from.get(AbstractDomainObject.ID), joins.getRoot().get(AbstractDomainObject.ID))); + + return and(isRootInJurisdiction, cb.exists(personSubquery)); + } + @Override protected Predicate getLimitedDiseasePredicate() { return CriteriaBuilderHelper.limitedDiseasePredicate(cb, user, joins.getRoot().get(TravelEntry.DISEASE)); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/BaseTravelEntryService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/BaseTravelEntryService.java index 746567ec458..4db129708d9 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/BaseTravelEntryService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/BaseTravelEntryService.java @@ -8,9 +8,13 @@ import de.symeda.sormas.api.common.DeletableEntityType; import de.symeda.sormas.api.deletionconfiguration.DeletionReference; +import de.symeda.sormas.api.person.PersonAssociation; +import de.symeda.sormas.api.person.PersonCriteria; import de.symeda.sormas.backend.common.AbstractCoreAdoService; import de.symeda.sormas.backend.common.ChangeDateBuilder; import de.symeda.sormas.backend.common.CriteriaBuilderHelper; +import de.symeda.sormas.backend.person.PersonQueryContext; +import de.symeda.sormas.backend.person.PersonService; import de.symeda.sormas.backend.travelentry.TravelEntry; import de.symeda.sormas.backend.travelentry.TravelEntryJoins; import de.symeda.sormas.backend.travelentry.TravelEntryJurisdictionPredicateValidator; @@ -22,6 +26,8 @@ public abstract class BaseTravelEntryService extends AbstractCoreAdoService userRights) { return getCurrentUser().hasAnyUserRight(userRights); } - public boolean hasRestrictedAccessToAssignedEntities() { - if (getCurrentUser() != null && !getCurrentUser().getUserRoles().isEmpty()) { - return getCurrentUser().getUserRoles() - .stream() - .allMatch(UserRole::isRestrictAccessToAssignedEntities); - } - return false; + public boolean isRestrictedToAssignedEntities() { + return isRestrictedToAssignEntities(getCurrentUser()); } // We need a clean transaction as we do not want call potential entity listeners which would lead to recursion diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserFacadeEjb.java index 0ee6d43ccaf..7f5ba09b4bc 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserFacadeEjb.java @@ -128,6 +128,7 @@ import de.symeda.sormas.backend.location.Location; import de.symeda.sormas.backend.location.LocationFacadeEjb; import de.symeda.sormas.backend.location.LocationFacadeEjb.LocationFacadeEjbLocal; +import de.symeda.sormas.backend.person.PersonService; import de.symeda.sormas.backend.task.TaskFacadeEjb; import de.symeda.sormas.backend.travelentry.TravelEntry; import de.symeda.sormas.backend.travelentry.TravelEntryJoins; @@ -178,6 +179,8 @@ public class UserFacadeEjb implements UserFacade { private UserRoleFacadeEjbLocal userRoleFacade; @EJB private UserRoleService userRoleService; + @EJB + private PersonService personService; @Inject private Event userCreateEvent; @Inject @@ -953,6 +956,9 @@ private List getUsersFromCasesByDistricts(List districtsUuidsAmong Arrays.asList(UserRight.CASE_RESPONSIBLE)) .stream() .map(userReference -> userService.getByUuid(userReference.getUuid())) + .collect(Collectors.toList()) + .stream() + .filter(user -> !UserHelper.isRestrictedToAssignEntities(user)) .collect(Collectors.toList()); return possibleUserForReplacement; } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserHelper.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserHelper.java new file mode 100644 index 00000000000..056a857bf0b --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserHelper.java @@ -0,0 +1,15 @@ +package de.symeda.sormas.backend.user; + +public class UserHelper { + + private UserHelper() { + } + + public static boolean isRestrictedToAssignEntities(User user) { + if (user != null && !user.getUserRoles().isEmpty()) { + return user.getUserRoles().stream().allMatch(UserRole::isRestrictAccessToAssignedEntities); + } + return false; + } + +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserJurisdictionPredicateValidator.java index e505958a903..ae13f3cc58e 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserJurisdictionPredicateValidator.java @@ -42,6 +42,11 @@ public Predicate isRootInJurisdictionOrOwned() { return isRootInJurisdiction(); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + return cb.disjunction(); + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserService.java index 0961f9fa9c4..237211d19ea 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserService.java @@ -497,6 +497,9 @@ public List getUserReferencesByJurisdictions( filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(root.get(UserReference.ID), userRoot.get(AbstractDomainObject.ID))); } + Join rolesJoin = root.join(User.USER_ROLES, JoinType.LEFT); + filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(rolesJoin.get(UserRole.RESTRICT_ACCESS_TO_ASSIGNED_ENTITIES), false)); + if (filter != null) { cq.where(filter); } @@ -504,7 +507,8 @@ public List getUserReferencesByJurisdictions( cq.distinct(true); cq.orderBy(cb.asc(root.get(AbstractDomainObject.ID))); - return em.createQuery(cq).setHint(ModelConstants.READ_ONLY, true).getResultList(); + final List resultList = em.createQuery(cq).setHint(ModelConstants.READ_ONLY, true).getResultList(); + return resultList; } public List getUserReferencesByIds(Collection userIds) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/util/PredicateJurisdictionValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/util/PredicateJurisdictionValidator.java index bb299d3b7af..e0c6cef926c 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/util/PredicateJurisdictionValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/util/PredicateJurisdictionValidator.java @@ -25,6 +25,7 @@ import de.symeda.sormas.api.utils.jurisdiction.JurisdictionValidator; import de.symeda.sormas.backend.common.CriteriaBuilderHelper; import de.symeda.sormas.backend.user.User; +import de.symeda.sormas.backend.user.UserHelper; public abstract class PredicateJurisdictionValidator extends JurisdictionValidator { @@ -33,7 +34,7 @@ public abstract class PredicateJurisdictionValidator extends JurisdictionValidat protected final Path userPath; public PredicateJurisdictionValidator(CriteriaBuilder cb, User user, Path userPath, List jurisdictionValidators) { - super(jurisdictionValidators); + super(jurisdictionValidators, UserHelper.isRestrictedToAssignEntities(user)); this.cb = cb; this.user = user; this.userPath = userPath; diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbPseudonymizationTest.java index 6124f987568..7e9a386605c 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbPseudonymizationTest.java @@ -29,8 +29,11 @@ import java.util.Calendar; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; +import javax.persistence.Query; + import org.junit.jupiter.api.Test; import de.symeda.sormas.api.Disease; @@ -44,6 +47,9 @@ import de.symeda.sormas.api.caze.CaseIndexDto; import de.symeda.sormas.api.caze.InvestigationStatus; import de.symeda.sormas.api.contact.ContactDto; +import de.symeda.sormas.api.feature.FeatureConfigurationIndexDto; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.infrastructure.area.AreaType; import de.symeda.sormas.api.infrastructure.community.CommunityDto; import de.symeda.sormas.api.infrastructure.facility.FacilityDto; @@ -60,8 +66,10 @@ import de.symeda.sormas.api.user.UserDto; import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.api.user.UserRoleReferenceDto; +import de.symeda.sormas.api.utils.DataHelper; import de.symeda.sormas.backend.AbstractBeanTest; import de.symeda.sormas.backend.TestDataCreator; +import de.symeda.sormas.backend.feature.FeatureConfiguration; public class CaseFacadeEjbPseudonymizationTest extends AbstractBeanTest { @@ -129,6 +137,71 @@ public void testGetCaseOutsideJurisdiction() { assertPseudonymized(getCaseFacade().getCaseDataByUuid(caze.getUuid())); } + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + // deactivate AUTOMATIC_RESPONSIBILITY_ASSIGNMENT in order to assign the limited user to a case from outside jurisdiction + FeatureConfigurationIndexDto featureConfiguration = + new FeatureConfigurationIndexDto(DataHelper.createUuid(), null, null, null, null, null, true, null); + getFeatureConfigurationFacade().saveFeatureConfiguration(featureConfiguration, FeatureType.CASE_SURVEILANCE); + + executeInTransaction(em -> { + Query query = em.createQuery("select f from featureconfiguration f"); + FeatureConfiguration singleResult = (FeatureConfiguration) query.getSingleResult(); + HashMap properties = new HashMap<>(); + properties.put(FeatureTypeProperty.AUTOMATIC_RESPONSIBILITY_ASSIGNMENT, false); + singleResult.setProperties(properties); + em.persist(singleResult); + }); + + loginWith(nationalAdmin); + + //case with same jurisdiction as limitedUser's + CaseDataDto caze1 = createCase(rdcf1, user1); + + //case with different jurisdiction from limited User's + CaseDataDto caze2 = createCase(rdcf2, user2); + + loginWith(nationalAdmin); + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + CaseDataDto testCase = getCaseFacade().getCaseDataByUuid(caze1.getUuid()); + assertThat(testCase.isPseudonymized(), is(true)); + assertThat(testCase.getPerson().getFirstName(), is(emptyString())); + CaseDataDto testCase2 = getCaseFacade().getCaseDataByUuid(caze2.getUuid()); + assertThat(testCase2.isPseudonymized(), is(true)); + assertThat(testCase2.getPerson().getFirstName(), is(emptyString())); + + //case created by limited user in the same jurisdiction + CaseDataDto caze3 = createCase(rdcf1, surveillanceOfficerWithRestrictedAccessToAssignedEntities); + //case created by limited user outside limited user's jurisdiction + CaseDataDto caze4 = createCase(rdcf2, surveillanceOfficerWithRestrictedAccessToAssignedEntities); + + loginWith(nationalAdmin); + caze1.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(caze1); + caze2.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(caze2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + CaseDataDto testForCase1 = getCaseFacade().getCaseDataByUuid(caze1.getUuid()); + assertThat(testForCase1.isPseudonymized(), is(false)); + assertThat(testForCase1.getPerson().getFirstName(), is("James")); + + CaseDataDto testForCase2 = getCaseFacade().getCaseDataByUuid(caze2.getUuid()); + assertThat(testForCase2.isPseudonymized(), is(false)); + assertThat(testForCase2.getPerson().getFirstName(), is("James")); + + CaseDataDto testForCase3 = getCaseFacade().getCaseDataByUuid(caze3.getUuid()); + assertThat(testForCase3.isPseudonymized(), is(false)); + assertThat(testForCase3.getPerson().getFirstName(), is("James")); + + CaseDataDto testForCase4 = getCaseFacade().getCaseDataByUuid(caze4.getUuid()); + assertThat(testForCase4.isPseudonymized(), is(false)); + assertThat(testForCase4.getPerson().getFirstName(), is("James")); + } + @Test public void testPseudonymizeGetByUuids() { diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbTest.java index f2ac3b6c7f2..45aab194bed 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbTest.java @@ -821,7 +821,7 @@ public void testGetIndexListByEventFreeText() { @Test public void testGetIndexListByARestrictedAccessToAssignedEntities() { loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); String lastName = "Person"; PersonDto cazePerson = creator.createPerson("Case", lastName); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbPseudonymizationTest.java index d32e306f745..9c2a06c9e23 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbPseudonymizationTest.java @@ -18,6 +18,7 @@ package de.symeda.sormas.backend.contact; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.not; @@ -127,6 +128,65 @@ public void testGetContactOutsideJurisdiction() { assertPseudonymized(getContactFacade().getByUuid(contact.getUuid())); } + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + + // contact & case within limited user's jurisdiction + CaseDataDto caze1 = createCase(user1, rdcf1); + ContactDto contact1 = createContact(user1, caze1, rdcf1); + + // contact & case outside limited user's jurisdiction + CaseDataDto caze2 = createCase(user2, rdcf2); + ContactDto contact2 = createContact(user2, caze2, rdcf2); + + loginWith(nationalAdmin); + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + ContactDto testContact1 = getContactFacade().getByUuid(contact1.getUuid()); + assertThat(testContact1.isPseudonymized(), is(true)); + assertThat(testContact1.getPerson().getFirstName(), is(emptyString())); + + ContactDto testContact2 = getContactFacade().getByUuid(contact2.getUuid()); + assertThat(testContact2.isPseudonymized(), is(true)); + assertThat(testContact2.getPerson().getFirstName(), is(emptyString())); + + //contact created by limited user in the same jurisdiction + ContactDto contact3 = createContact(surveillanceOfficerWithRestrictedAccessToAssignedEntities, null, rdcf1); + //contact created by limited user outside limited user's jurisdiction + ContactDto contact4 = createContact(surveillanceOfficerWithRestrictedAccessToAssignedEntities, null, rdcf2); + + loginWith(nationalAdmin); + contact1.setContactOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getContactFacade().save(contact1); + contact2.setContactOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getContactFacade().save(contact2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + ContactDto testForContact1 = getContactFacade().getByUuid(contact1.getUuid()); + assertThat(testForContact1.isPseudonymized(), is(false)); + assertThat(testForContact1.getPerson().getFirstName(), is("James")); + CaseDataDto testForCase1 = getCaseFacade().getCaseDataByUuid(caze1.getUuid()); + assertThat(testForCase1.isPseudonymized(), is(true)); + assertThat(testForCase1.getPerson().getFirstName(), is(emptyString())); + + ContactDto testForContact2 = getContactFacade().getByUuid(contact2.getUuid()); + assertThat(testForContact2.isPseudonymized(), is(false)); + assertThat(testForContact2.getPerson().getFirstName(), is("James")); + CaseDataDto testForCase2 = getCaseFacade().getCaseDataByUuid(caze2.getUuid()); + assertThat(testForCase2.isPseudonymized(), is(true)); + assertThat(testForCase2.getPerson().getFirstName(), is(emptyString())); + + ContactDto testForContact3 = getContactFacade().getByUuid(contact3.getUuid()); + assertThat(testForContact3.isPseudonymized(), is(false)); + assertThat(testForContact3.getPerson().getFirstName(), is("James")); + + ContactDto testForContact4 = getContactFacade().getByUuid(contact4.getUuid()); + assertThat(testForContact4.isPseudonymized(), is(false)); + assertThat(testForContact4.getPerson().getFirstName(), is("James")); + } + @Test public void testPseudonymizeGetByUuids() { CaseDataDto caze = createCase(user1, rdcf1); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbTest.java index afdfcc9b9b9..377fb3e765c 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbTest.java @@ -1019,7 +1019,7 @@ public void testGetIndexListByARestrictedAccessToAssignedEntities() { UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); final List indexList = getContactFacade().getIndexList(null, 0, 100, null); assertEquals(0, indexList.size()); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbPseudonymizationTest.java new file mode 100644 index 00000000000..1a4e187121e --- /dev/null +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbPseudonymizationTest.java @@ -0,0 +1,102 @@ +package de.symeda.sormas.backend.environment; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.is; + +import org.junit.jupiter.api.Test; + +import de.symeda.sormas.api.environment.EnvironmentDto; +import de.symeda.sormas.api.environment.EnvironmentMedia; +import de.symeda.sormas.api.user.UserDto; +import de.symeda.sormas.backend.AbstractBeanTest; +import de.symeda.sormas.backend.TestDataCreator; + +public class EnvironmentFacadeEjbPseudonymizationTest extends AbstractBeanTest { + + private TestDataCreator.RDCF rdcf1; + private TestDataCreator.RDCF rdcf2; + private UserDto surveillanceOfficer1; + private UserDto nationalUser; + private UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities; + + @Override + public void init() { + + super.init(); + rdcf1 = creator.createRDCF("Region 1", "District 1", "Community 1", "Facility 1", "Point of entry 1"); + rdcf2 = creator.createRDCF("Region 2", "District 2", "Community 2", "Facility 2", "Point of entry 2"); + surveillanceOfficer1 = creator.createSurveillanceOfficer(rdcf1); + nationalUser = creator.createNationalUser(); + surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + } + + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + + //environment with same jurisdiction as limitedUser's + EnvironmentDto environment1 = creator.createEnvironment( + "Test Environment", + EnvironmentMedia.WATER, + surveillanceOfficer1.toReference(), + rdcf1, + (e) -> e.getLocation().setStreet("Main street")); + + //environment with different jurisdiction from limited User's + EnvironmentDto environment2 = creator.createEnvironment( + "Test Environment", + EnvironmentMedia.WATER, + nationalUser.toReference(), + rdcf2, + (e) -> e.getLocation().setStreet("Main street second")); + + //environment created by limited user in the same jurisdiction + EnvironmentDto environment3 = creator.createEnvironment( + "Test Environment", + EnvironmentMedia.WATER, + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf1, + (e) -> e.getLocation().setStreet("Main street third")); + + //environment created by limited user outside limited user's jurisdiction + EnvironmentDto environment4 = creator.createEnvironment( + "Test Environment", + EnvironmentMedia.WATER, + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf2, + (e) -> e.getLocation().setStreet("Main street fourth")); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + EnvironmentDto testEnvironment1 = getEnvironmentFacade().getByUuid(environment1.getUuid()); + assertThat(testEnvironment1.isPseudonymized(), is(true)); + assertThat(testEnvironment1.getLocation().getStreet(), is(emptyString())); + + EnvironmentDto testEnvironment2 = getEnvironmentFacade().getByUuid(environment2.getUuid()); + assertThat(testEnvironment2.isPseudonymized(), is(true)); + assertThat(testEnvironment2.getLocation().getStreet(), is(emptyString())); + + loginWith(nationalUser); + environment1.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEnvironmentFacade().save(environment1); + environment2.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEnvironmentFacade().save(environment2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + EnvironmentDto testForEnvironment1 = getEnvironmentFacade().getByUuid(environment1.getUuid()); + assertThat(testForEnvironment1.isPseudonymized(), is(false)); + assertThat(testForEnvironment1.getLocation().getStreet(), is("Main street")); + + EnvironmentDto testForEnvironment2 = getEnvironmentFacade().getByUuid(environment2.getUuid()); + assertThat(testForEnvironment2.isPseudonymized(), is(false)); + assertThat(testForEnvironment2.getLocation().getStreet(), is("Main street second")); + + EnvironmentDto testForEnvironment3 = getEnvironmentFacade().getByUuid(environment3.getUuid()); + assertThat(testForEnvironment3.isPseudonymized(), is(false)); + assertThat(testForEnvironment3.getLocation().getStreet(), is("Main street third")); + + EnvironmentDto testForEnvironment4 = getEnvironmentFacade().getByUuid(environment4.getUuid()); + assertThat(testForEnvironment4.isPseudonymized(), is(false)); + assertThat(testForEnvironment4.getLocation().getStreet(), is("Main street fourth")); + } + +} diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbTest.java index 71d7acd86af..d85b20d5479 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbTest.java @@ -128,7 +128,7 @@ public void testGetIndexListByARestrictedAccessToAssignedEntities() { UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); assertEquals(0, getEnvironmentFacade().getIndexList(new EnvironmentCriteria(), 0, 100, null).size()); loginWith(user); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbPseudonymizationTest.java new file mode 100644 index 00000000000..a9ae8b16f2f --- /dev/null +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbPseudonymizationTest.java @@ -0,0 +1,170 @@ +package de.symeda.sormas.backend.environment.environmentsample; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.is; + +import org.junit.jupiter.api.Test; + +import de.symeda.sormas.api.environment.EnvironmentDto; +import de.symeda.sormas.api.environment.EnvironmentMedia; +import de.symeda.sormas.api.environment.environmentsample.EnvironmentSampleDto; +import de.symeda.sormas.api.environment.environmentsample.EnvironmentSampleMaterial; +import de.symeda.sormas.api.infrastructure.facility.FacilityDto; +import de.symeda.sormas.api.infrastructure.facility.FacilityType; +import de.symeda.sormas.api.user.DefaultUserRole; +import de.symeda.sormas.api.user.UserDto; +import de.symeda.sormas.backend.AbstractBeanTest; +import de.symeda.sormas.backend.TestDataCreator; + +public class EnvironmentSampleFacadeEjbPseudonymizationTest extends AbstractBeanTest { + + private TestDataCreator.RDCF rdcf1; + private FacilityDto lab1; + private FacilityDto lab2; + private UserDto reportingUser; + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities; + private EnvironmentDto environment1; + private EnvironmentDto environment2; + private EnvironmentDto environment3; + private EnvironmentDto environment4; + + private TestDataCreator.RDCF rdcf2; + private UserDto userInDifferentJurisdiction; + + @Override + public void init() { + super.init(); + + rdcf1 = creator.createRDCF(); + rdcf2 = creator.createRDCF(); + lab1 = creator.createFacility("Lab", rdcf1.region, rdcf1.district, rdcf1.community, FacilityType.LABORATORY); + lab2 = creator.createFacility("Lab2", rdcf2.region, rdcf2.district, rdcf2.community, FacilityType.LABORATORY); + + reportingUser = creator.createUser(rdcf1, creator.getUserRoleReference(DefaultUserRole.ENVIRONMENTAL_SURVEILLANCE_USER)); + userInDifferentJurisdiction = + creator.createUser(rdcf2, "Env", "Surv2", creator.getUserRoleReference(DefaultUserRole.ENVIRONMENTAL_SURVEILLANCE_USER)); + surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + environment1 = creator.createEnvironment("Test env", EnvironmentMedia.WATER, reportingUser.toReference(), rdcf1); + environment2 = creator.createEnvironment("Test environment 2", EnvironmentMedia.AIR, userInDifferentJurisdiction.toReference(), rdcf2); + environment3 = creator.createEnvironment( + "Test environment 3", + EnvironmentMedia.AIR, + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf2); + environment4 = creator.createEnvironment( + "Test environment 4", + EnvironmentMedia.AIR, + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf2); + } + + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + + // environment within limited user's jurisdiction + EnvironmentSampleDto sample1 = + creator.createEnvironmentSample(environment1.toReference(), reportingUser.toReference(), rdcf1, lab1.toReference(), s -> { + s.setSampleMaterial(EnvironmentSampleMaterial.OTHER); + s.setOtherSampleMaterial("Test material"); + s.setFieldSampleId("Test id"); + s.setLaboratoryDetails("Test lab details"); + s.setOtherRequestedPathogenTests("Test pathogen tests"); + s.setDispatched(true); + s.setDispatchDetails("Test dispatch details"); + s.setLabSampleId("Test lab sample id"); + s.setGeneralComment("Test comment"); + s.getLocation().setCity("Test city"); + }); + + // environment outside limited user's jurisdiction + EnvironmentSampleDto sample2 = + creator.createEnvironmentSample(environment2.toReference(), userInDifferentJurisdiction.toReference(), rdcf2, lab2.toReference(), s -> { + s.setSampleMaterial(EnvironmentSampleMaterial.OTHER); + s.setOtherSampleMaterial("Test material second"); + s.setFieldSampleId("Test id second"); + s.setLaboratoryDetails("Test lab details second"); + s.setOtherRequestedPathogenTests("Test pathogen tests second"); + s.setDispatched(true); + s.setDispatchDetails("Test dispatch details second"); + s.setLabSampleId("Test lab sample id second"); + s.setGeneralComment("Test comment second"); + s.getLocation().setCity("Test city second"); + }); + +// loginWith(nationalAdmin); +// UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = +// creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + EnvironmentSampleDto testSample1 = getEnvironmentSampleFacade().getByUuid(sample1.getUuid()); + assertThat(testSample1.isPseudonymized(), is(true)); + assertThat(testSample1.getOtherSampleMaterial(), is(emptyString())); + EnvironmentSampleDto testSample2 = getEnvironmentSampleFacade().getByUuid(sample2.getUuid()); + assertThat(testSample2.isPseudonymized(), is(true)); + assertThat(testSample2.getOtherSampleMaterial(), is(emptyString())); + + // environment within limited user's jurisdiction + loginWith(nationalAdmin); + EnvironmentSampleDto sample3 = creator.createEnvironmentSample( + environment3.toReference(), + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf1, + lab1.toReference(), + s -> { + s.setSampleMaterial(EnvironmentSampleMaterial.OTHER); + s.setOtherSampleMaterial("Test material third"); + s.setFieldSampleId("Test id third"); + s.setLaboratoryDetails("Test lab details third"); + s.setOtherRequestedPathogenTests("Test pathogen tests third"); + s.setDispatched(true); + s.setDispatchDetails("Test dispatch details third"); + s.setLabSampleId("Test lab sample id third"); + s.setGeneralComment("Test comment third"); + s.getLocation().setCity("Test city third"); + }); + + // environment outside limited user's jurisdiction + EnvironmentSampleDto sample4 = creator.createEnvironmentSample( + environment4.toReference(), + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf2, + lab2.toReference(), + s -> { + s.setSampleMaterial(EnvironmentSampleMaterial.OTHER); + s.setOtherSampleMaterial("Test material fourth"); + s.setFieldSampleId("Test id fourth"); + s.setLaboratoryDetails("Test lab details fourth"); + s.setOtherRequestedPathogenTests("Test pathogen tests fourth"); + s.setDispatched(true); + s.setDispatchDetails("Test dispatch details fourth"); + s.setLabSampleId("Test lab sample id fourth"); + s.setGeneralComment("Test comment fourth"); + s.getLocation().setCity("Test city fourth"); + }); + +// loginWith(nationalAdmin); + environment1.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEnvironmentFacade().save(environment1); + environment2.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEnvironmentFacade().save(environment2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + EnvironmentSampleDto returnTestSample1 = getEnvironmentSampleFacade().getByUuid(sample1.getUuid()); + assertThat(returnTestSample1.isPseudonymized(), is(false)); + assertThat(returnTestSample1.getOtherSampleMaterial(), is("Test material")); + + EnvironmentSampleDto returnTestSample2 = getEnvironmentSampleFacade().getByUuid(sample2.getUuid()); + assertThat(returnTestSample2.isPseudonymized(), is(false)); + assertThat(returnTestSample2.getOtherSampleMaterial(), is("Test material second")); + + EnvironmentSampleDto returnTestSample3 = getEnvironmentSampleFacade().getByUuid(sample3.getUuid()); + assertThat(returnTestSample3.isPseudonymized(), is(false)); + assertThat(returnTestSample3.getOtherSampleMaterial(), is("Test material third")); + + EnvironmentSampleDto returnTestSample4 = getEnvironmentSampleFacade().getByUuid(sample4.getUuid()); + assertThat(returnTestSample4.isPseudonymized(), is(false)); + assertThat(returnTestSample4.getOtherSampleMaterial(), is("Test material fourth")); + } +} diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbTest.java index c2d3e71eb49..c993b2d4fe2 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbTest.java @@ -528,6 +528,7 @@ public void testGetIndexList() { @Test public void testGetIndexListWithRestrictedAccessToAssignedEntities() { + loginWith(nationalAdmin); EnvironmentSampleDto environmentSample = creator.createEnvironmentSample(environment.toReference(), reportingUser.toReference(), rdcf, lab.toReference(), s -> { s.setFieldSampleId("field_sample-1"); @@ -543,6 +544,9 @@ public void testGetIndexListWithRestrictedAccessToAssignedEntities() { s.setSampleMaterial(EnvironmentSampleMaterial.OTHER); s.setOtherSampleMaterial("Other sample material"); }); + environment.setResponsibleUser(reportingUser.toReference()); + getEnvironmentFacade().save(environment); + Pathogen positivePathogen = creator.createPathogen("TEST_PATHOGEN", "Test pathogen"); PathogenTestDto positiveTest = creator.createPathogenTest( environmentSample.toReference(), @@ -554,10 +558,12 @@ public void testGetIndexListWithRestrictedAccessToAssignedEntities() { null); assertThat(getEnvironmentSampleFacade().getIndexList(null, null, null, null), hasSize(1)); + loginWith(nationalAdmin); UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf); + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); assertThat(getEnvironmentSampleFacade().getIndexList(null, null, null, null), hasSize(0)); } diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbPseudonymizationTest.java index 9e498756eef..e099bb843e8 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbPseudonymizationTest.java @@ -16,6 +16,7 @@ package de.symeda.sormas.backend.event; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; @@ -93,6 +94,82 @@ public void testEventOutsideJurisdiction() { assertPseudonymized(getEventFacade().getEventByUuid(event.getUuid(), false)); } + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + + loginWith(nationalAdmin); + + // event within limited user's jurisdiction + EventDto event1 = creator + .createEvent(EventStatus.SIGNAL, EventInvestigationStatus.PENDING, "Test title", "Test Description", user1.toReference(), rdcf1, e -> { + e.setConnectionNumber("123"); + }); + + // event outside limited user's jurisdiction + EventDto event2 = creator + .createEvent(EventStatus.SIGNAL, EventInvestigationStatus.PENDING, "Test title", "Test Description", user2.toReference(), rdcf2, e -> { + e.setConnectionNumber("456"); + }); + + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + final EventDto testEvent1 = getEventFacade().getEventByUuid(event1.getUuid(), false); + assertThat(testEvent1.isPseudonymized(), is(true)); + assertThat(testEvent1.getConnectionNumber(), is(emptyString())); + final EventDto testEvent2 = getEventFacade().getEventByUuid(event2.getUuid(), false); + assertThat(testEvent2.isPseudonymized(), is(true)); + assertThat(testEvent2.getConnectionNumber(), is(emptyString())); + + //event created by limited user in the same jurisdiction + EventDto event3 = creator.createEvent( + EventStatus.SIGNAL, + EventInvestigationStatus.PENDING, + "Test title", + "Test Description", + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf1, + e -> { + e.setConnectionNumber("789"); + }); + + //event created by limited user outside limited user's jurisdiction + EventDto event4 = creator.createEvent( + EventStatus.SIGNAL, + EventInvestigationStatus.PENDING, + "Test title", + "Test Description", + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf2, + e -> { + e.setConnectionNumber("987"); + }); + + loginWith(nationalAdmin); + testEvent1.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEventFacade().save(testEvent1); + testEvent2.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEventFacade().save(testEvent2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + final EventDto testForEvent1 = getEventFacade().getEventByUuid(event1.getUuid(), false); + assertThat(testForEvent1.isPseudonymized(), is(false)); + assertThat(testForEvent1.getConnectionNumber(), is("123")); + + final EventDto testForEvent2 = getEventFacade().getEventByUuid(event2.getUuid(), false); + assertThat(testForEvent2.isPseudonymized(), is(false)); + assertThat(testForEvent2.getConnectionNumber(), is("456")); + + final EventDto testForEvent3 = getEventFacade().getEventByUuid(event3.getUuid(), false); + assertThat(testForEvent3.isPseudonymized(), is(false)); + assertThat(testForEvent3.getConnectionNumber(), is("789")); + + final EventDto testForEvent4 = getEventFacade().getEventByUuid(event4.getUuid(), false); + assertThat(testForEvent4.isPseudonymized(), is(false)); + assertThat(testForEvent4.getConnectionNumber(), is("987")); + } + @Test public void testUpdatePseudonymizedEvent() { EventDto event = createEvent(user2, rdcf2); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbTest.java index d21d495c443..59c4323610c 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbTest.java @@ -278,7 +278,7 @@ public void testGetIndexListByARestrictedAccessToAssignedEntities() { event.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); getEventFacade().save(event); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); List results3 = getEventFacade().getIndexList(eventCriteria, 0, 100, null); assertEquals(1, results3.size()); } diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjbPseudonymizationTest.java index bc31fc63b1e..d7bb4e5ca22 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjbPseudonymizationTest.java @@ -16,6 +16,7 @@ package de.symeda.sormas.backend.event; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.notNullValue; @@ -87,6 +88,88 @@ public void testEventParticipantOutsideJurisdiction() { assertPseudonymized(getEventParticipantFacade().getEventParticipantByUuid(eventParticipant.getUuid())); } + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + loginWith(nationalAdmin); + + // event within limited user's jurisdiction + EventParticipantDto eventParticipant1 = createEventParticipant(user1, rdcf1); + EventDto eventDto1 = getEventFacade().getEventByUuid(eventParticipant1.getEvent().getUuid(), false); + eventDto1.setConnectionNumber("123"); + getEventFacade().save(eventDto1); + + // event outside limited user's jurisdiction + EventParticipantDto eventParticipant2 = createEventParticipant(user2, rdcf2); + EventDto eventDto2 = getEventFacade().getEventByUuid(eventParticipant2.getEvent().getUuid(), false); + eventDto2.setConnectionNumber("456"); + getEventFacade().save(eventDto2); + + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + final EventDto testEvent1 = getEventFacade().getEventByUuid(eventDto1.getUuid(), false); + assertThat(testEvent1.isPseudonymized(), is(true)); + assertThat(testEvent1.getConnectionNumber(), is(emptyString())); + final EventParticipantDto testEventParticipant1 = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant1.getUuid()); + assertThat(testEventParticipant1.isPseudonymized(), is(true)); + assertThat(testEventParticipant1.getPerson().getFirstName(), is("Confidential")); + + final EventDto testEvent1Second = getEventFacade().getEventByUuid(eventDto2.getUuid(), false); + assertThat(testEvent1Second.isPseudonymized(), is(true)); + assertThat(testEvent1Second.getConnectionNumber(), is(emptyString())); + final EventParticipantDto testEventParticipant1Second = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant2.getUuid()); + assertThat(testEventParticipant1Second.isPseudonymized(), is(true)); + assertThat(testEventParticipant1Second.getPerson().getFirstName(), is("Confidential")); + + // event created by limited user in the same jurisdiction + EventParticipantDto eventParticipant3 = createEventParticipant(surveillanceOfficerWithRestrictedAccessToAssignedEntities, rdcf1); + EventDto eventDto3 = getEventFacade().getEventByUuid(eventParticipant3.getEvent().getUuid(), false); + eventDto3.setConnectionNumber("789"); + getEventFacade().save(eventDto3); + + // event created by limited user outside it's jurisdiction + EventParticipantDto eventParticipant4 = createEventParticipant(surveillanceOfficerWithRestrictedAccessToAssignedEntities, rdcf2); + EventDto eventDto4 = getEventFacade().getEventByUuid(eventParticipant4.getEvent().getUuid(), false); + eventDto4.setConnectionNumber("987"); + getEventFacade().save(eventDto4); + + loginWith(nationalAdmin); + testEvent1.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEventFacade().save(testEvent1); + testEvent1Second.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEventFacade().save(testEvent1Second); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + final EventDto testEvent3 = getEventFacade().getEventByUuid(eventDto1.getUuid(), false); + assertThat(testEvent3.isPseudonymized(), is(false)); + assertThat(testEvent3.getConnectionNumber(), is("123")); + final EventParticipantDto testEventParticipant3 = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant1.getUuid()); + assertThat(testEventParticipant3.isPseudonymized(), is(false)); + assertThat(testEventParticipant3.getPerson().getFirstName(), is("John")); + + final EventDto testEvent3Second = getEventFacade().getEventByUuid(eventDto2.getUuid(), false); + assertThat(testEvent3Second.isPseudonymized(), is(false)); + assertThat(testEvent3Second.getConnectionNumber(), is("456")); + final EventParticipantDto testEventParticipant3Second = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant2.getUuid()); + assertThat(testEventParticipant3Second.isPseudonymized(), is(false)); + assertThat(testEventParticipant3Second.getPerson().getFirstName(), is("John")); + + final EventDto testEvent3Third = getEventFacade().getEventByUuid(eventDto3.getUuid(), false); + assertThat(testEvent3Third.isPseudonymized(), is(false)); + assertThat(testEvent3Third.getConnectionNumber(), is("789")); + final EventParticipantDto testEventParticipant3Third = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant3.getUuid()); + assertThat(testEventParticipant3Third.isPseudonymized(), is(false)); + assertThat(testEventParticipant3Third.getPerson().getFirstName(), is("John")); + + final EventDto testEvent3Fourth = getEventFacade().getEventByUuid(eventDto4.getUuid(), false); + assertThat(testEvent3Fourth.isPseudonymized(), is(false)); + assertThat(testEvent3Fourth.getConnectionNumber(), is("987")); + final EventParticipantDto testEventParticipant3Fourth = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant4.getUuid()); + assertThat(testEventParticipant3Fourth.isPseudonymized(), is(false)); + assertThat(testEventParticipant3Fourth.getPerson().getFirstName(), is("John")); + } + @Test public void testPseudonymizeGetByUuids() { EventParticipantDto eventParticipant1 = createEventParticipant(user2, rdcf2); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/immunization/ImmunizationFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/immunization/ImmunizationFacadeEjbPseudonymizationTest.java new file mode 100644 index 00000000000..6b2b56b5374 --- /dev/null +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/immunization/ImmunizationFacadeEjbPseudonymizationTest.java @@ -0,0 +1,217 @@ +package de.symeda.sormas.backend.immunization; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.is; + +import java.util.HashMap; + +import javax.persistence.Query; + +import org.junit.jupiter.api.Test; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.caze.CaseDataDto; +import de.symeda.sormas.api.feature.FeatureConfigurationIndexDto; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.feature.FeatureTypeProperty; +import de.symeda.sormas.api.immunization.ImmunizationDto; +import de.symeda.sormas.api.immunization.ImmunizationManagementStatus; +import de.symeda.sormas.api.immunization.ImmunizationStatus; +import de.symeda.sormas.api.immunization.MeansOfImmunization; +import de.symeda.sormas.api.person.PersonDto; +import de.symeda.sormas.api.user.DefaultUserRole; +import de.symeda.sormas.api.user.UserDto; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.backend.AbstractBeanTest; +import de.symeda.sormas.backend.TestDataCreator; +import de.symeda.sormas.backend.feature.FeatureConfiguration; + +public class ImmunizationFacadeEjbPseudonymizationTest extends AbstractBeanTest { + + private TestDataCreator.RDCF rdcf1; + private TestDataCreator.RDCF rdcf2; + + private UserDto districtUser1; + private UserDto nationalUser; + + @Override + public void init() { + super.init(); + rdcf1 = creator.createRDCF("Region 1", "District 1", "Community 1", "Facility 1", "Point of entry 1"); + rdcf2 = creator.createRDCF("Region 2", "District 2", "Community 2", "Facility 2", "Point of entry 2"); + nationalUser = creator.createUser( + rdcf1.region.getUuid(), + rdcf1.district.getUuid(), + rdcf1.community.getUuid(), + rdcf1.facility.getUuid(), + "Nat", + "User", + creator.getUserRoleReference(DefaultUserRole.NATIONAL_USER)); + + districtUser1 = creator.createUser( + rdcf1.region.getUuid(), + rdcf1.district.getUuid(), + rdcf1.facility.getUuid(), + "Surv", + "Off1", + creator.getUserRoleReference(DefaultUserRole.SURVEILLANCE_OFFICER)); + } + + @Test + public void testPseudonymized() { + loginWith(nationalAdmin); + + // immunization within limited user's jurisdiction + PersonDto person1 = creator.createPerson("John", "Doe"); + final ImmunizationDto immunization1 = creator.createImmunization( + Disease.CORONAVIRUS, + person1.toReference(), + nationalUser.toReference(), + ImmunizationStatus.ACQUIRED, + MeansOfImmunization.VACCINATION, + ImmunizationManagementStatus.COMPLETED, + rdcf1); + immunization1.setAdditionalDetails("confidential details"); + getImmunizationFacade().save(immunization1); + + // immunization outside limited user's jurisdiction + PersonDto person2 = creator.createPerson("Max", "MUstermann"); + final ImmunizationDto immunization2 = creator.createImmunization( + Disease.CORONAVIRUS, + person2.toReference(), + nationalUser.toReference(), + ImmunizationStatus.ACQUIRED, + MeansOfImmunization.VACCINATION, + ImmunizationManagementStatus.COMPLETED, + rdcf2); + immunization2.setAdditionalDetails("confidential details second"); + getImmunizationFacade().save(immunization2); + + loginWith(districtUser1); + ImmunizationDto testImmunization3 = getImmunizationFacade().getByUuid(immunization1.getUuid()); + assertThat(testImmunization3.isPseudonymized(), is(false)); + assertThat(testImmunization3.getAdditionalDetails(), is("confidential details")); + ImmunizationDto testImmunization3Second = getImmunizationFacade().getByUuid(immunization2.getUuid()); + assertThat(testImmunization3Second.isPseudonymized(), is(true)); + assertThat(testImmunization3Second.getAdditionalDetails(), is(emptyString())); + } + + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + + // deactivate AUTOMATIC_RESPONSIBILITY_ASSIGNMENT in order to assign the limited user to a case from outside jurisdiction + FeatureConfigurationIndexDto featureConfiguration = + new FeatureConfigurationIndexDto(DataHelper.createUuid(), null, null, null, null, null, true, null); + getFeatureConfigurationFacade().saveFeatureConfiguration(featureConfiguration, FeatureType.CASE_SURVEILANCE); + + executeInTransaction(em -> { + Query query = em.createQuery("select f from featureconfiguration f"); + FeatureConfiguration singleResult = (FeatureConfiguration) query.getSingleResult(); + HashMap properties = new HashMap<>(); + properties.put(FeatureTypeProperty.AUTOMATIC_RESPONSIBILITY_ASSIGNMENT, false); + singleResult.setProperties(properties); + em.persist(singleResult); + }); + + loginWith(nationalAdmin); + + // immunization within limited user's jurisdiction + PersonDto person1 = creator.createPerson("John", "Doe"); + final ImmunizationDto immunization1 = creator.createImmunization( + Disease.CORONAVIRUS, + person1.toReference(), + nationalUser.toReference(), + ImmunizationStatus.ACQUIRED, + MeansOfImmunization.VACCINATION, + ImmunizationManagementStatus.COMPLETED, + rdcf1); + immunization1.setAdditionalDetails("confidential details"); + getImmunizationFacade().save(immunization1); + + // immunization outside limited user's jurisdiction + PersonDto person2 = creator.createPerson("Max", "MUstermann"); + final ImmunizationDto immunization2 = creator.createImmunization( + Disease.CORONAVIRUS, + person2.toReference(), + nationalUser.toReference(), + ImmunizationStatus.ACQUIRED, + MeansOfImmunization.VACCINATION, + ImmunizationManagementStatus.COMPLETED, + rdcf2); + immunization2.setAdditionalDetails("confidential details second"); + getImmunizationFacade().save(immunization2); + + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + // immunization created by limited user within limited user's jurisdiction + PersonDto person3 = creator.createPerson("John", "Doe"); + final ImmunizationDto immunization3 = creator.createImmunization( + Disease.CORONAVIRUS, + person3.toReference(), + nationalUser.toReference(), + ImmunizationStatus.ACQUIRED, + MeansOfImmunization.VACCINATION, + ImmunizationManagementStatus.COMPLETED, + rdcf1); + immunization3.setAdditionalDetails("confidential details"); + getImmunizationFacade().save(immunization3); + + // immunization created by limited user outside limited user's jurisdiction + PersonDto person4 = creator.createPerson("Max", "MUstermann"); + final ImmunizationDto immunization4 = creator.createImmunization( + Disease.CORONAVIRUS, + person4.toReference(), + nationalUser.toReference(), + ImmunizationStatus.ACQUIRED, + MeansOfImmunization.VACCINATION, + ImmunizationManagementStatus.COMPLETED, + rdcf2); + immunization4.setAdditionalDetails("confidential details second"); + getImmunizationFacade().save(immunization4); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + ImmunizationDto testImmunization = getImmunizationFacade().getByUuid(immunization1.getUuid()); + assertThat(testImmunization.isPseudonymized(), is(true)); + assertThat(testImmunization.getAdditionalDetails(), is(emptyString())); + ImmunizationDto testImmunizationSecond = getImmunizationFacade().getByUuid(immunization2.getUuid()); + assertThat(testImmunizationSecond.isPseudonymized(), is(true)); + assertThat(testImmunizationSecond.getAdditionalDetails(), is(emptyString())); + + loginWith(nationalAdmin); + final CaseDataDto caseDataDto = creator.createCase(nationalUser.toReference(), person1.toReference(), rdcf1); + final CaseDataDto caseDataDtoSecond = creator.createCase(nationalUser.toReference(), person2.toReference(), rdcf2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + ImmunizationDto testImmunization2 = getImmunizationFacade().getByUuid(immunization1.getUuid()); + assertThat(testImmunization2.isPseudonymized(), is(true)); + assertThat(testImmunization2.getAdditionalDetails(), is(emptyString())); + ImmunizationDto testImmunization2Second = getImmunizationFacade().getByUuid(immunization2.getUuid()); + assertThat(testImmunization2Second.isPseudonymized(), is(true)); + assertThat(testImmunization2Second.getAdditionalDetails(), is(emptyString())); + + loginWith(nationalAdmin); + caseDataDto.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(caseDataDto); + caseDataDtoSecond.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(caseDataDtoSecond); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + ImmunizationDto testImmunization3 = getImmunizationFacade().getByUuid(immunization1.getUuid()); + assertThat(testImmunization3.isPseudonymized(), is(false)); + assertThat(testImmunization3.getAdditionalDetails(), is("confidential details")); + + ImmunizationDto testImmunization3Second = getImmunizationFacade().getByUuid(immunization2.getUuid()); + assertThat(testImmunization3Second.isPseudonymized(), is(true)); + assertThat(testImmunization3Second.getAdditionalDetails(), is(emptyString())); + + ImmunizationDto testImmunization3Third = getImmunizationFacade().getByUuid(immunization3.getUuid()); + assertThat(testImmunization3Third.isPseudonymized(), is(true)); + assertThat(testImmunization3Third.getAdditionalDetails(), is(emptyString())); + + ImmunizationDto testImmunization3Fourth = getImmunizationFacade().getByUuid(immunization4.getUuid()); + assertThat(testImmunization3Fourth.isPseudonymized(), is(true)); + assertThat(testImmunization3Fourth.getAdditionalDetails(), is(emptyString())); + } +} diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbPseudonymizationTest.java index 4300f9d6ce7..6124e0098a8 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbPseudonymizationTest.java @@ -19,23 +19,31 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Calendar; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Optional; +import javax.persistence.Query; + import org.junit.jupiter.api.Test; import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.caze.CaseDataDto; import de.symeda.sormas.api.contact.ContactDto; +import de.symeda.sormas.api.feature.FeatureConfigurationIndexDto; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.infrastructure.facility.FacilityReferenceDto; import de.symeda.sormas.api.sample.PathogenTestResultType; import de.symeda.sormas.api.sample.PathogenTestType; @@ -49,6 +57,7 @@ import de.symeda.sormas.api.utils.DataHelper; import de.symeda.sormas.backend.AbstractBeanTest; import de.symeda.sormas.backend.TestDataCreator; +import de.symeda.sormas.backend.feature.FeatureConfiguration; import de.symeda.sormas.backend.infrastructure.facility.Facility; public class SampleFacadeEjbPseudonymizationTest extends AbstractBeanTest { @@ -107,6 +116,84 @@ public void testGetSampleWithCaseOutsideJurisdiction() { assertPseudonymized(getSampleFacade().getSampleByUuid(sample.getUuid()), "Lab"); } + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() throws InterruptedException { + + // deactivate AUTOMATIC_RESPONSIBILITY_ASSIGNMENT in order to assign the limited user to a case from outside jurisdiction + FeatureConfigurationIndexDto featureConfiguration = + new FeatureConfigurationIndexDto(DataHelper.createUuid(), null, null, null, null, null, true, null); + getFeatureConfigurationFacade().saveFeatureConfiguration(featureConfiguration, FeatureType.CASE_SURVEILANCE); + + executeInTransaction(em -> { + Query query = em.createQuery("select f from featureconfiguration f"); + FeatureConfiguration singleResult = (FeatureConfiguration) query.getSingleResult(); + HashMap properties = new HashMap<>(); + properties.put(FeatureTypeProperty.AUTOMATIC_RESPONSIBILITY_ASSIGNMENT, false); + singleResult.setProperties(properties); + em.persist(singleResult); + }); + + // case and sample within limited user's jurisdiction + CaseDataDto caze1 = creator.createCase(user1.toReference(), creator.createPerson("John", "Smith").toReference(), rdcf1); + SampleDto sample1 = createCaseSample(caze1, user1); + + // case and sample outside limited user's jurisdiction + CaseDataDto caze2 = creator.createCase(user2.toReference(), creator.createPerson("Max", "Mustermann").toReference(), rdcf2); + SampleDto sample2 = createCaseSample(caze2, user2); + + loginWith(nationalAdmin); + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + //case and sample created by limited user within limited user's jurisdiction + CaseDataDto caze3 = creator.createCase( + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + creator.createPerson("Max", "Mustermann").toReference(), + rdcf2); + SampleDto sample3 = createCaseSample(caze3, surveillanceOfficerWithRestrictedAccessToAssignedEntities); + + //case and sample created by limited user outside limited user's jurisdiction + CaseDataDto caze4 = creator.createCase( + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + creator.createPerson("Max", "Mustermann").toReference(), + rdcf2); + SampleDto sample4 = createCaseSample(caze4, surveillanceOfficerWithRestrictedAccessToAssignedEntities); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); + final SampleDto testSample1 = getSampleFacade().getSampleByUuid(sample1.getUuid()); + final SampleDto testSample2 = getSampleFacade().getSampleByUuid(sample2.getUuid()); + assertThat(testSample1.isPseudonymized(), is(true)); + assertThat(testSample1.getComment(), is(emptyString())); + assertThat(testSample2.isPseudonymized(), is(true)); + assertThat(testSample2.getComment(), is(emptyString())); + + loginWith(nationalAdmin); + final CaseDataDto testCase1 = getCaseFacade().getCaseDataByUuid(caze1.getUuid()); + testCase1.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(testCase1); + final CaseDataDto testCase2 = getCaseFacade().getCaseDataByUuid(caze2.getUuid()); + testCase2.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(testCase2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + final SampleDto returnedTestSample1 = getSampleFacade().getSampleByUuid(sample1.getUuid()); + assertThat(returnedTestSample1.isPseudonymized(), is(false)); + assertThat(returnedTestSample1.getComment(), is("Test comment")); + + final SampleDto returnedTestSample2 = getSampleFacade().getSampleByUuid(sample2.getUuid()); + assertThat(returnedTestSample2.isPseudonymized(), is(false)); + assertThat(returnedTestSample2.getComment(), is("Test comment")); + + final SampleDto returnedTestSample3 = getSampleFacade().getSampleByUuid(sample3.getUuid()); + assertThat(returnedTestSample3.isPseudonymized(), is(false)); + assertThat(returnedTestSample3.getComment(), is("Test comment")); + + final SampleDto returnedTestSample4 = getSampleFacade().getSampleByUuid(sample4.getUuid()); + assertThat(returnedTestSample4.isPseudonymized(), is(false)); + assertThat(returnedTestSample4.getComment(), is("Test comment")); + } + @Test public void testGetSampleWithLabUserOfSampleLab() { loginWith(user1); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbTest.java index 8811ec8aa87..b9331faceb9 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbTest.java @@ -308,7 +308,7 @@ public void testGetIndexListBySampleAssociationTypeAndRestrictedAccessToAssigned UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); assertEquals(0, getSampleFacade().getIndexList(new SampleCriteria(), 0, 100, null).size()); loginWith(user); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/task/TaskFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/task/TaskFacadeEjbTest.java index 3336cdd7bde..8735077f9dd 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/task/TaskFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/task/TaskFacadeEjbTest.java @@ -188,7 +188,7 @@ public void testGetIndexListByARestrictedAccessToAssignedEntitiesUser() { UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); assertEquals(0, getTaskFacade().getIndexList(null, 0, 100, null).size()); loginWith(user); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/travelentry/TravelEntryFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/travelentry/TravelEntryFacadeEjbPseudonymizationTest.java new file mode 100644 index 00000000000..97eff06b42f --- /dev/null +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/travelentry/TravelEntryFacadeEjbPseudonymizationTest.java @@ -0,0 +1,163 @@ +package de.symeda.sormas.backend.travelentry; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.is; + +import java.util.HashMap; + +import javax.persistence.Query; + +import org.junit.jupiter.api.Test; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.caze.CaseDataDto; +import de.symeda.sormas.api.feature.FeatureConfigurationIndexDto; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.feature.FeatureTypeProperty; +import de.symeda.sormas.api.person.PersonDto; +import de.symeda.sormas.api.travelentry.TravelEntryDto; +import de.symeda.sormas.api.user.DefaultUserRole; +import de.symeda.sormas.api.user.UserDto; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.backend.AbstractBeanTest; +import de.symeda.sormas.backend.TestDataCreator; +import de.symeda.sormas.backend.feature.FeatureConfiguration; + +public class TravelEntryFacadeEjbPseudonymizationTest extends AbstractBeanTest { + + private TestDataCreator.RDCF rdcf1; + private TestDataCreator.RDCF rdcf2; + + private UserDto nationalUser; + + @Override + public void init() { + super.init(); + rdcf1 = creator.createRDCF("Region 1", "District 1", "Community 1", "Facility 1", "Point of entry 1"); + rdcf2 = creator.createRDCF("Region 2", "District 2", "Community 2", "Facility 2", "Point of entry 2"); + nationalUser = creator.createUser( + rdcf1.region.getUuid(), + rdcf1.district.getUuid(), + rdcf1.community.getUuid(), + rdcf1.facility.getUuid(), + "Nat", + "User", + creator.getUserRoleReference(DefaultUserRole.NATIONAL_USER)); + } + + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + + // deactivate AUTOMATIC_RESPONSIBILITY_ASSIGNMENT in order to assign the limited user to a case from outside jurisdiction + FeatureConfigurationIndexDto featureConfiguration = + new FeatureConfigurationIndexDto(DataHelper.createUuid(), null, null, null, null, null, true, null); + getFeatureConfigurationFacade().saveFeatureConfiguration(featureConfiguration, FeatureType.CASE_SURVEILANCE); + + executeInTransaction(em -> { + Query query = em.createQuery("select f from featureconfiguration f"); + FeatureConfiguration singleResult = (FeatureConfiguration) query.getSingleResult(); + HashMap properties = new HashMap<>(); + properties.put(FeatureTypeProperty.AUTOMATIC_RESPONSIBILITY_ASSIGNMENT, false); + singleResult.setProperties(properties); + em.persist(singleResult); + }); + + loginWith(nationalUser); + + // travel entry within limited user's jurisdiction + PersonDto person1 = creator.createPerson("John", "Doe"); + TravelEntryDto travelEntry1 = creator.createTravelEntry( + person1.toReference(), + nationalUser.toReference(), + Disease.CORONAVIRUS, + rdcf1.region, + rdcf1.district, + rdcf1.pointOfEntry); + travelEntry1.setQuarantineHomePossibleComment("pacient can stay home"); + getTravelEntryFacade().save(travelEntry1); + + // travel entry outside limited user's jurisdiction + PersonDto person2 = creator.createPerson("John", "Doe"); + TravelEntryDto travelEntry2 = creator.createTravelEntry( + person2.toReference(), + nationalUser.toReference(), + Disease.CORONAVIRUS, + rdcf2.region, + rdcf2.district, + rdcf2.pointOfEntry); + travelEntry2.setQuarantineHomePossibleComment("pacient can stay home second"); + getTravelEntryFacade().save(travelEntry2); + + loginWith(nationalAdmin); + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + // travel entry created by limited user within limited user's jurisdiction + PersonDto person3 = creator.createPerson("John", "Doe"); + TravelEntryDto travelEntry3 = creator.createTravelEntry( + person3.toReference(), + nationalUser.toReference(), + Disease.CORONAVIRUS, + rdcf1.region, + rdcf1.district, + rdcf1.pointOfEntry); + travelEntry3.setQuarantineHomePossibleComment("pacient can stay home"); + getTravelEntryFacade().save(travelEntry3); + + // travel entry created by limited user outside limited user's jurisdiction + PersonDto person4 = creator.createPerson("John", "Doe"); + TravelEntryDto travelEntry4 = creator.createTravelEntry( + person4.toReference(), + nationalUser.toReference(), + Disease.CORONAVIRUS, + rdcf2.region, + rdcf2.district, + rdcf2.pointOfEntry); + travelEntry4.setQuarantineHomePossibleComment("pacient can stay home second"); + getTravelEntryFacade().save(travelEntry4); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + TravelEntryDto testTravelEntry = getTravelEntryFacade().getByUuid(travelEntry1.getUuid()); + assertThat(testTravelEntry.isPseudonymized(), is(true)); + assertThat(testTravelEntry.getQuarantineHomePossibleComment(), is(emptyString())); + TravelEntryDto testTravelEntrySecond = getTravelEntryFacade().getByUuid(travelEntry2.getUuid()); + assertThat(testTravelEntrySecond.isPseudonymized(), is(true)); + assertThat(testTravelEntrySecond.getQuarantineHomePossibleComment(), is(emptyString())); + + loginWith(nationalAdmin); + final CaseDataDto caseDataDto1 = creator.createCase(nationalUser.toReference(), person1.toReference(), rdcf1); + final CaseDataDto caseDataDto2 = creator.createCase(nationalUser.toReference(), person2.toReference(), rdcf2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + TravelEntryDto testTravelEntry2 = getTravelEntryFacade().getByUuid(travelEntry1.getUuid()); + assertThat(testTravelEntry2.isPseudonymized(), is(true)); + assertThat(testTravelEntry2.getQuarantineHomePossibleComment(), is(emptyString())); + TravelEntryDto testTravelEntry2Second = getTravelEntryFacade().getByUuid(travelEntry2.getUuid()); + assertThat(testTravelEntry2Second.isPseudonymized(), is(true)); + assertThat(testTravelEntry2Second.getQuarantineHomePossibleComment(), is(emptyString())); + + loginWith(nationalAdmin); + caseDataDto1.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(caseDataDto1); + caseDataDto2.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(caseDataDto2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + TravelEntryDto testTravelEntry3 = getTravelEntryFacade().getByUuid(travelEntry1.getUuid()); + assertThat(testTravelEntry3.isPseudonymized(), is(false)); + assertThat(testTravelEntry3.getQuarantineHomePossibleComment(), is("pacient can stay home")); + + TravelEntryDto testTravelEntry3Second = getTravelEntryFacade().getByUuid(travelEntry2.getUuid()); + assertThat(testTravelEntry3Second.isPseudonymized(), is(true)); + assertThat(testTravelEntry3Second.getQuarantineHomePossibleComment(), is(emptyString())); + + TravelEntryDto testTravelEntry3Third = getTravelEntryFacade().getByUuid(travelEntry3.getUuid()); + assertThat(testTravelEntry3Third.isPseudonymized(), is(true)); + assertThat(testTravelEntry3Third.getQuarantineHomePossibleComment(), is(emptyString())); + + TravelEntryDto testTravelEntry3Fourth = getTravelEntryFacade().getByUuid(travelEntry4.getUuid()); + assertThat(testTravelEntry3Fourth.isPseudonymized(), is(true)); + assertThat(testTravelEntry3Fourth.getQuarantineHomePossibleComment(), is(emptyString())); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java index 8e8996c8b62..94d08a2e2af 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java @@ -958,7 +958,7 @@ public CommitDiscardWrapperComponent getCaseDataEditComponent(fina } if (UserProvider.getCurrent().getUserRoles().stream().anyMatch(userRoleDto -> !userRoleDto.isRestrictAccessToAssignedEntities()) - || caze.getSurveillanceOfficer().equals(UserProvider.getCurrent().getUserReference())) { + || DataHelper.isSame(caze.getSurveillanceOfficer(), UserProvider.getCurrent().getUserReference())) { appendSpecialCommands(caze, editView); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CasePersonView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CasePersonView.java index d0c380e3202..67566201816 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CasePersonView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CasePersonView.java @@ -48,6 +48,7 @@ protected void initView(String params) { CaseDataDto caseData = FacadeProvider.getCaseFacade().getCaseDataByUuid(getCaseRef().getUuid()); person = FacadeProvider.getPersonFacade().getByUuid(caseData.getPerson().getUuid()); + boolean isEditAllowed = isEditAllowed(); CommitDiscardWrapperComponent editComponent = ControllerProvider.getPersonController() .getPersonEditComponent( PersonContext.CASE, @@ -56,11 +57,11 @@ protected void initView(String params) { caseData.getDiseaseDetails(), UserRight.CASE_EDIT, getViewMode(), - isEditAllowed()); + isEditAllowed); DetailSubComponentWrapper componentWrapper = addComponentWrapper(editComponent); CustomLayout layout = addPageLayout(componentWrapper, editComponent); setSubComponent(componentWrapper); - addSideComponents(layout, DeletableEntityType.CASE, caseData.getUuid(), person.toReference(), this::showUnsavedChangesPopup, isEditAllowed()); + addSideComponents(layout, DeletableEntityType.CASE, caseData.getUuid(), person.toReference(), this::showUnsavedChangesPopup, isEditAllowed); setEditPermission( editComponent, UserProvider.getCurrent().hasUserRight(UserRight.PERSON_EDIT), diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/filter/ImmunizationFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/filter/ImmunizationFilterForm.java index 3da1de7bc46..fd957f004d4 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/filter/ImmunizationFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/filter/ImmunizationFilterForm.java @@ -100,10 +100,10 @@ protected void addFields() { @Override public void addMoreFilters(CustomLayout moreFiltersContainer) { - if (currentUserDto().getRegion() == null) { +// if (currentUserDto().getRegion() == null) { ComboBox regionFilter = addField(moreFiltersContainer, FieldConfiguration.pixelSized(ImmunizationCriteria.REGION, 140)); regionFilter.addItems(FacadeProvider.getRegionFacade().getAllActiveByServerCountry()); - } +// } ComboBox districtFilter = addField(moreFiltersContainer, FieldConfiguration.pixelSized(ImmunizationCriteria.DISTRICT, 140)); districtFilter.setDescription(I18nProperties.getDescription(Descriptions.descDistrictFilter)); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleCreateForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleCreateForm.java index b4182aee86d..3a932216f7d 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleCreateForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleCreateForm.java @@ -47,8 +47,8 @@ public class UserRoleCreateForm extends AbstractEditForm { + fluidRowLocs(UserRoleDto.DESCRIPTION) + fluidRowLocs(UserRoleDto.HAS_OPTIONAL_HEALTH_FACILITY) + fluidRowLocs(UserRoleDto.HAS_ASSOCIATED_DISTRICT_USER) - + fluidRowLocs(UserRoleDto.PORT_HEALTH_USER); -// + fluidRowLocs(UserRoleDto.RESTRICT_ACCESS_TO_ASSIGNED_ENTITIES); + + fluidRowLocs(UserRoleDto.PORT_HEALTH_USER) + + fluidRowLocs(UserRoleDto.RESTRICT_ACCESS_TO_ASSIGNED_ENTITIES); protected UserRoleCreateForm() { super(UserRoleDto.class, UserRoleDto.I18N_PREFIX); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleEditForm.java index fb51d8cf9ff..f2c5af9cb46 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleEditForm.java @@ -59,7 +59,7 @@ public class UserRoleEditForm extends AbstractUserRoleForm { + fluidRowLocs(UserRoleDto.HAS_OPTIONAL_HEALTH_FACILITY) + fluidRowLocs(UserRoleDto.HAS_ASSOCIATED_DISTRICT_USER) + fluidRowLocs(UserRoleDto.PORT_HEALTH_USER) -// + fluidRowLocs(UserRoleDto.RESTRICT_ACCESS_TO_ASSIGNED_ENTITIES) + + fluidRowLocs(UserRoleDto.RESTRICT_ACCESS_TO_ASSIGNED_ENTITIES) + fluidRowLocs(USER_RIGHTS_LABEL_LOC) + fluidRowLocs(UserRoleDto.USER_RIGHTS); @@ -85,7 +85,7 @@ protected void addFields() { addField(UserRoleDto.HAS_OPTIONAL_HEALTH_FACILITY).addStyleName(CssStyles.VSPACE_TOP_3); addField(UserRoleDto.HAS_ASSOCIATED_DISTRICT_USER).addStyleName(CssStyles.VSPACE_TOP_3); - addField(UserRoleDto.PORT_HEALTH_USER).addStyleNames(CssStyles.VSPACE_TOP_3, CssStyles.VSPACE_3); + addField(UserRoleDto.PORT_HEALTH_USER).addStyleNames(CssStyles.VSPACE_TOP_3); addField(UserRoleDto.RESTRICT_ACCESS_TO_ASSIGNED_ENTITIES).addStyleNames(CssStyles.VSPACE_TOP_3, CssStyles.VSPACE_3); Label userRightsLabel = new Label(I18nProperties.getCaption(Captions.UserRole_userRights), ContentMode.HTML); From 89389fa79bc48e395be387331bd06ee352847e8d Mon Sep 17 00:00:00 2001 From: sergiupacurariu <62688603+sergiupacurariu@users.noreply.github.com> Date: Fri, 19 Jan 2024 20:12:11 +0200 Subject: [PATCH 2/6] #12697 - Assign case(s) to a User and allow them to see the data of only the assigned case(s) in the system - additional logic - android --- .../sormas/app/backend/caze/CaseDao.java | 11 ++ .../CaseJurisdictionBooleanValidator.java | 17 ++- .../app/backend/caze/CaseJurisdictionDto.java | 10 ++ .../app/backend/common/DatabaseHelper.java | 7 +- .../app/backend/contact/ContactDao.java | 11 ++ .../ContactJurisdictionBooleanValidator.java | 15 ++- .../contact/ContactJurisdictionDto.java | 11 ++ ...vironmentJurisdictionBooleanValidator.java | 12 ++- ...entSampleJurisdictionBooleanValidator.java | 11 +- .../EnvironmentSampleJurisdictionDto.java | 8 ++ .../sormas/app/backend/event/EventDao.java | 17 +++ .../EventJurisdictionBooleanValidator.java | 21 +++- .../backend/event/EventJurisdictionDto.java | 3 +- ...rticipantJurisdictionBooleanValidator.java | 11 +- .../EventParticipantJurisdictionDto.java | 9 ++ ...unizationJurisdictionBooleanValidator.java | 12 +++ .../ImmunizationJurisdictionDto.java | 18 ++++ .../PersonJurisdictionBooleanValidator.java | 101 ++++++++++++++++++ .../backend/person/PersonJurisdictionDto.java | 65 +++++++++++ .../SampleJurisdictionBooleanValidator.java | 10 ++ .../TaskJurisdictionBooleanValidator.java | 15 ++- .../app/backend/user/UserDtoHelper.java | 6 ++ .../sormas/app/backend/user/UserRole.java | 10 ++ .../app/backend/user/UserRoleDtoHelper.java | 2 + .../util/BooleanJurisdictionValidator.java | 4 +- .../sormas/app/util/JurisdictionHelper.java | 56 ++++++++++ 26 files changed, 454 insertions(+), 19 deletions(-) create mode 100644 sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java create mode 100644 sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionDto.java diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseDao.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseDao.java index dba95207911..e208e9a2c11 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseDao.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseDao.java @@ -701,6 +701,17 @@ public void deleteCaseAndAllDependingEntities(String caseUuid) throws SQLExcepti deleteCascade(caze); } + public List getByPerson(Person person) { + try { + QueryBuilder qb = queryBuilder(); + qb.where().eq(Case.PERSON, person); + return qb.query(); + } catch (SQLException e) { + Log.e(getTableName(), "Could not perform queryByCriteria on Contact"); + throw new RuntimeException(e); + } + } + public List getSimilarCases(CaseSimilarityCriteria criteria) { try { QueryBuilder queryBuilder = queryBuilder(); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionBooleanValidator.java index 2eda6522496..a5df9821794 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionBooleanValidator.java @@ -43,10 +43,19 @@ public Boolean isRootInJurisdiction() { return isInJurisdictionByJurisdictionLevel(userJurisdiction.getJurisdictionLevel()); } - @Override - public Boolean isRootInJurisdictionOrOwned() { - return userJurisdiction.getUuid().equals(caseJurisdiction.getReportingUserUuid()) || inJurisdiction(); - } + @Override + public Boolean isRootInJurisdictionOrOwned() { + return getReportedByCurrentUser() || inJurisdiction(); + } + + private boolean getReportedByCurrentUser() { + return userJurisdiction.getUuid().equals(caseJurisdiction.getReportingUserUuid()); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return getReportedByCurrentUser() || userJurisdiction.getUuid().equals(caseJurisdiction.getSurveillanceOfficerUuid()); + } @Override protected Disease getDisease() { diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionDto.java index c05cff34c43..6c1b75dd0de 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionDto.java @@ -34,6 +34,7 @@ public class CaseJurisdictionDto implements Serializable { private String healthFacilityUuid; private String pointOfEntryUuid; private List sampleLabUuids; + private String surveillanceOfficerUuid; public CaseJurisdictionDto() { } @@ -118,4 +119,13 @@ public List getSampleLabUuids() { public void setSampleLabUuids(List sampleLabUuids) { this.sampleLabUuids = sampleLabUuids; } + + public String getSurveillanceOfficerUuid() { + return surveillanceOfficerUuid; + } + + public CaseJurisdictionDto setSurveillanceOfficerUuid(String surveillanceOfficerUuid) { + this.surveillanceOfficerUuid = surveillanceOfficerUuid; + return this; + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/common/DatabaseHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/common/DatabaseHelper.java index edd309bb28e..1d87f17f965 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/common/DatabaseHelper.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/common/DatabaseHelper.java @@ -190,7 +190,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public static final String DATABASE_NAME = "sormas.db"; // any time you make changes to your database objects, you may have to increase the database version - public static final int DATABASE_VERSION = 358; + public static final int DATABASE_VERSION = 359; private static DatabaseHelper instance = null; @@ -3174,6 +3174,11 @@ public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int currentVersion = 357; getDao(CustomizableEnumValue.class).executeRaw("ALTER TABLE customizableEnumValue ADD COLUMN active boolean default true;"); + case 358: + currentVersion = 358; + getDao(UserRole.class) + .executeRaw("ALTER TABLE userroles ADD COLUMN restrictAccessToAssignedEntities boolean NOT NULL DEFAULT false;"); + // ATTENTION: break should only be done after last version break; diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactDao.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactDao.java index 15211b359fe..67c548a0da0 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactDao.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactDao.java @@ -196,6 +196,17 @@ public List queryByCriteria(ContactCriteria criteria, long offset, long } } + public List getByPerson(Person person) { + try { + QueryBuilder qb = queryBuilder(); + qb.where().eq(Contact.PERSON, person); + return qb.query(); + } catch (SQLException e) { + Log.e(getTableName(), "Could not perform queryByCriteria on Contact"); + throw new RuntimeException(e); + } + } + private QueryBuilder buildQueryBuilder(ContactCriteria contactCriteria) throws SQLException { QueryBuilder queryBuilder = queryBuilder(); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionBooleanValidator.java index b85b5c546bd..0b2015fa5b4 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionBooleanValidator.java @@ -46,11 +46,20 @@ public Boolean isRootInJurisdiction() { return isInJurisdictionByJurisdictionLevel(userJurisdiction.getJurisdictionLevel()); } - @Override - public Boolean isRootInJurisdictionOrOwned() { - return userJurisdiction.getUuid().equals(contactJurisdictionDto.getReportingUserUuid()) || inJurisdiction(); + @Override + public Boolean isRootInJurisdictionOrOwned() { + return getReportedByCurrentUser() || inJurisdiction(); + } + + private boolean getReportedByCurrentUser(){ + return userJurisdiction.getUuid().equals(contactJurisdictionDto.getReportingUserUuid()); } + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return getReportedByCurrentUser() || userJurisdiction.getUuid().equals(contactJurisdictionDto.getContactOfficerUuid()); + } + @Override protected Disease getDisease() { return null; diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionDto.java index 0ffd8d9839a..5a87edade7b 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionDto.java @@ -45,6 +45,8 @@ public class ContactJurisdictionDto implements Serializable { private CaseJurisdictionDto caseJurisdiction; + private String contactOfficerUuid; + public ContactJurisdictionDto() { } @@ -110,4 +112,13 @@ public List getSampleLabUuids() { public void setSampleLabUuids(List sampleLabUuids) { this.sampleLabUuids = sampleLabUuids; } + + public String getContactOfficerUuid() { + return contactOfficerUuid; + } + + public ContactJurisdictionDto setContactOfficerUuid(String contactOfficerUuid) { + this.contactOfficerUuid = contactOfficerUuid; + return this; + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java index cef4d1c6dd9..568900ac618 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java @@ -32,9 +32,17 @@ public Boolean isRootInJurisdiction() { @Override public Boolean isRootInJurisdictionOrOwned() { + return getReportedAndResponsibleByCurrentUser() || inJurisdiction(); + } + + private boolean getReportedAndResponsibleByCurrentUser() { return userJurisdiction.getUuid().equals(environmentJurisdiction.getReportingUserUuid()) - || userJurisdiction.getUuid().equals(environmentJurisdiction.getResponsibleUserUuid()) - || inJurisdiction(); + || userJurisdiction.getUuid().equals(environmentJurisdiction.getResponsibleUserUuid()); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return getReportedAndResponsibleByCurrentUser(); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionBooleanValidator.java index a2fac30eba9..403d4f39b9d 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionBooleanValidator.java @@ -51,7 +51,16 @@ public Boolean isRootInJurisdiction() { @Override public Boolean isRootInJurisdictionOrOwned() { - return userJurisdiction.getUuid().equals(environmentSampleJurisdiction.getReportingUserUuid()) || inJurisdiction(); + return getReportedByCurrentUser() || inJurisdiction(); + } + + private boolean getReportedByCurrentUser() { + return userJurisdiction.getUuid().equals(environmentSampleJurisdiction.getReportingUserUuid()); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return getReportedByCurrentUser() || userJurisdiction.getUuid().equals(environmentSampleJurisdiction.getEnvironmentResponsibleUser()); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionDto.java index 06cb2d78021..ed01eeabfff 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionDto.java @@ -23,6 +23,7 @@ public class EnvironmentSampleJurisdictionDto implements Serializable { private String regionUuid; private String districtUuid; private String communityUuid; + private String environmentResponsibleUser; public EnvironmentSampleJurisdictionDto() { } @@ -67,4 +68,11 @@ public void setCommunityUuid(String communityUuid) { this.communityUuid = communityUuid; } + public String getEnvironmentResponsibleUser() { + return environmentResponsibleUser; + } + + public void setEnvironmentResponsibleUser(String environmentResponsibleUser) { + this.environmentResponsibleUser = environmentResponsibleUser; + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventDao.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventDao.java index 9b44f2d9fd8..422f616f6fe 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventDao.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventDao.java @@ -39,7 +39,9 @@ import de.symeda.sormas.app.backend.common.DaoException; import de.symeda.sormas.app.backend.common.DatabaseHelper; import de.symeda.sormas.app.backend.config.ConfigProvider; +import de.symeda.sormas.app.backend.contact.Contact; import de.symeda.sormas.app.backend.location.Location; +import de.symeda.sormas.app.backend.person.Person; import de.symeda.sormas.app.backend.task.Task; import de.symeda.sormas.app.util.DiseaseConfigurationCache; import de.symeda.sormas.app.util.LocationService; @@ -260,4 +262,19 @@ private QueryBuilder buildQueryBuilder(EventCriteria criteria) thro return queryBuilder; } + public List getByEventParticipantPerson(Person person){ + try { + QueryBuilder queryBuilder = queryBuilder(); + QueryBuilder eventParticipantBuilder = DatabaseHelper.getEventParticipantDao().queryBuilder(); + queryBuilder.leftJoin(eventParticipantBuilder); + Where where = eventParticipantBuilder.where(); + + where.eq(EventParticipant.PERSON + "_id", person.getId()); + + return queryBuilder.query(); + } catch (SQLException e) { + Log.e(getTableName(), "Could not perform queryByCriteria on Event"); + throw new RuntimeException(e); + } + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionBooleanValidator.java index 196b60c13e4..fdcf81f4aa6 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionBooleanValidator.java @@ -43,10 +43,23 @@ public Boolean isRootInJurisdiction() { return isInJurisdictionByJurisdictionLevel(userJurisdiction.getJurisdictionLevel()); } - @Override - public Boolean isRootInJurisdictionOrOwned() { - return userJurisdiction.getUuid().equals(eventJurisdictionDto.getReportingUserUuid()) || userJurisdiction.getUuid().equals(eventJurisdictionDto.getResponsibleUserUuid()) || inJurisdiction(); - } + @Override + public Boolean isRootInJurisdictionOrOwned() { + return getReportedByCurrentUser() || getCurrentUserResponsible() || inJurisdiction(); + } + + private boolean getReportedByCurrentUser() { + return userJurisdiction.getUuid().equals(eventJurisdictionDto.getReportingUserUuid()); + } + + public boolean getCurrentUserResponsible() { + return userJurisdiction.getUuid().equals(eventJurisdictionDto.getResponsibleUserUuid()); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return getReportedByCurrentUser() || getCurrentUserResponsible(); + } @Override protected Disease getDisease() { diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionDto.java index aa44b8437cb..4ed06b2256a 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionDto.java @@ -56,8 +56,9 @@ public String getResponsibleUserUuid() { return responsibleUserUuid; } - public void setResponsibleUserUuid(String responsibleUserUuid) { + public EventJurisdictionDto setResponsibleUserUuid(String responsibleUserUuid) { this.responsibleUserUuid = responsibleUserUuid; + return this; } public String getRegionUuid() { diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionBooleanValidator.java index cf36d72997e..704dbc8c653 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionBooleanValidator.java @@ -48,7 +48,16 @@ public Boolean isRootInJurisdiction() { @Override public Boolean isRootInJurisdictionOrOwned() { - return userJurisdiction.getUuid().equals(eventParticipantJurisdictionDto.getReportingUserUuid()) || inJurisdiction(); + return getReportedByCurrentUser() || inJurisdiction(); + } + + private boolean getReportedByCurrentUser() { + return userJurisdiction.getUuid().equals(eventParticipantJurisdictionDto.getReportingUserUuid()); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return getReportedByCurrentUser() || userJurisdiction.getUuid().equals(eventParticipantJurisdictionDto.getEventResponsibleUserUuid()); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionDto.java index c5880f62388..094343a4ee5 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionDto.java @@ -28,6 +28,7 @@ public class EventParticipantJurisdictionDto implements Serializable { private String districtUuid; private String eventUuid; private EventJurisdictionDto eventJurisdictionDto; + private String eventResponsibleUserUuid; public EventParticipantJurisdictionDto() { } @@ -96,4 +97,12 @@ public EventJurisdictionDto getEventJurisdictionDto() { public void setEventJurisdictionDto(EventJurisdictionDto eventJurisdictionDto) { this.eventJurisdictionDto = eventJurisdictionDto; } + + public String getEventResponsibleUserUuid() { + return eventResponsibleUserUuid; + } + + public void setEventResponsibleUserUuid(String eventResponsibleUserUuid) { + this.eventResponsibleUserUuid = eventResponsibleUserUuid; + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionBooleanValidator.java index 7de10c4d76a..4bdb9c35d9c 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionBooleanValidator.java @@ -15,9 +15,14 @@ package de.symeda.sormas.app.backend.immunization; +import java.util.ArrayList; +import java.util.List; + import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.app.backend.caze.CaseJurisdictionDto; import de.symeda.sormas.app.backend.caze.ResponsibleJurisdictionDto; +import de.symeda.sormas.app.backend.person.PersonJurisdictionBooleanValidator; import de.symeda.sormas.app.util.BooleanJurisdictionValidator; import de.symeda.sormas.app.util.UserJurisdiction; @@ -48,6 +53,13 @@ public Boolean isRootInJurisdictionOrOwned() { return userJurisdiction.getUuid().equals(immunizationJurisdiction.getReportingUserUuid()) || inJurisdiction(); } + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + PersonJurisdictionBooleanValidator personJurisdictionBooleanValidator = new PersonJurisdictionBooleanValidator(userJurisdiction, immunizationJurisdiction.getPersonJurisdiction()); + + return isRootInJurisdictionOrOwned() && personJurisdictionBooleanValidator.isRootInJurisdictionForRestrictedAccess(); + } + @Override protected Disease getDisease() { return null; diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionDto.java index 0efa6fa1175..089418222c0 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionDto.java @@ -21,12 +21,15 @@ import java.io.Serializable; import de.symeda.sormas.app.backend.caze.ResponsibleJurisdictionDto; +import de.symeda.sormas.app.backend.person.PersonJurisdictionDto; public class ImmunizationJurisdictionDto implements Serializable { private String reportingUserUuid; private ResponsibleJurisdictionDto responsibleJurisdiction; + private String personUuid; + private PersonJurisdictionDto personJurisdiction; public ImmunizationJurisdictionDto() { } @@ -52,4 +55,19 @@ public ResponsibleJurisdictionDto getResponsibleJurisdiction() { public void setResponsibleJurisdiction(ResponsibleJurisdictionDto responsibleJurisdiction) { this.responsibleJurisdiction = responsibleJurisdiction; } + public String getPersonUuid() { + return personUuid; + } + + public void setPersonUuid(String personUuid) { + this.personUuid = personUuid; + } + + public PersonJurisdictionDto getPersonJurisdiction() { + return personJurisdiction; + } + + public void setPersonJurisdiction(PersonJurisdictionDto personJurisdiction) { + this.personJurisdiction = personJurisdiction; + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java new file mode 100644 index 00000000000..16d4c9ae45f --- /dev/null +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java @@ -0,0 +1,101 @@ +package de.symeda.sormas.app.backend.person; + +import java.util.stream.Collectors; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.app.backend.caze.CaseJurisdictionDto; +import de.symeda.sormas.app.backend.contact.ContactJurisdictionDto; +import de.symeda.sormas.app.backend.event.EventJurisdictionDto; +import de.symeda.sormas.app.util.BooleanJurisdictionValidator; +import de.symeda.sormas.app.util.UserJurisdiction; + +public class PersonJurisdictionBooleanValidator extends BooleanJurisdictionValidator { + + private final PersonJurisdictionDto personJurisdiction; + private final UserJurisdiction userJurisdiction; + + public PersonJurisdictionBooleanValidator(UserJurisdiction userJurisdiction, PersonJurisdictionDto personJurisdiction) { + super(null, userJurisdiction); + this.personJurisdiction = personJurisdiction; + this.userJurisdiction = userJurisdiction; + } + + @Override + protected Disease getDisease() { + return null; + } + + @Override + public Boolean isRootInJurisdiction() { + return false; + } + + @Override + public Boolean isRootInJurisdictionOrOwned() { + return this.isRootInJurisdiction(); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + + boolean currentUserIsSurveillanceOfficer = personJurisdiction.getCaseJurisdiction() + .stream() + .map(CaseJurisdictionDto::getSurveillanceOfficerUuid) + .collect(Collectors.toList()) + .contains(userJurisdiction.getUuid()); + + boolean currentUserIsContactOfficer = personJurisdiction.getContactJurisdiction() + .stream() + .map(ContactJurisdictionDto::getContactOfficerUuid) + .collect(Collectors.toList()) + .contains(userJurisdiction.getUuid()); + + boolean currentUserIsResponsibleUser = personJurisdiction.getEventJurisdiction() + .stream() + .map(EventJurisdictionDto::getResponsibleUserUuid) + .collect(Collectors.toList()) + .contains(userJurisdiction.getUuid()); + + return currentUserIsSurveillanceOfficer || currentUserIsContactOfficer || currentUserIsResponsibleUser; + } + + @Override + protected Boolean whenNotAllowed() { + return false; + } + + @Override + protected Boolean whenNationalLevel() { + return false; + } + + @Override + protected Boolean whenRegionalLevel() { + return false; + } + + @Override + protected Boolean whenDistrictLevel() { + return false; + } + + @Override + protected Boolean whenCommunityLevel() { + return false; + } + + @Override + protected Boolean whenFacilityLevel() { + return false; + } + + @Override + protected Boolean whenPointOfEntryLevel() { + return false; + } + + @Override + protected Boolean whenLaboratoryLevel() { + return false; + } +} diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionDto.java new file mode 100644 index 00000000000..a439cac90b6 --- /dev/null +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionDto.java @@ -0,0 +1,65 @@ +package de.symeda.sormas.app.backend.person; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import de.symeda.sormas.app.backend.caze.CaseJurisdictionDto; +import de.symeda.sormas.app.backend.contact.ContactJurisdictionDto; +import de.symeda.sormas.app.backend.event.EventJurisdictionDto; +import de.symeda.sormas.app.backend.immunization.ImmunizationJurisdictionDto; + +public class PersonJurisdictionDto implements Serializable { + + private List caseJurisdiction = new ArrayList<>(); + private List contactJurisdiction = new ArrayList<>(); + private List eventJurisdiction = new ArrayList<>(); + private List immunizationJurisdiction = new ArrayList<>(); + + public PersonJurisdictionDto() { + + } + + public PersonJurisdictionDto( + List caseJurisdiction, + List contactJurisdiction, + List eventJurisdiction, + List immunizationJurisdiction) { + this.caseJurisdiction = caseJurisdiction; + this.contactJurisdiction = contactJurisdiction; + this.eventJurisdiction = eventJurisdiction; + this.immunizationJurisdiction = immunizationJurisdiction; + } + + public List getCaseJurisdiction() { + return caseJurisdiction; + } + + public void setCaseJurisdiction(List caseJurisdiction) { + this.caseJurisdiction = caseJurisdiction; + } + + public List getContactJurisdiction() { + return contactJurisdiction; + } + + public void setContactJurisdiction(List contactJurisdiction) { + this.contactJurisdiction = contactJurisdiction; + } + + public List getEventJurisdiction() { + return eventJurisdiction; + } + + public void setEventJurisdiction(List eventJurisdiction) { + this.eventJurisdiction = eventJurisdiction; + } + + public List getImmunizationJurisdiction() { + return immunizationJurisdiction; + } + + public void setImmunizationJurisdiction(List immunizationJurisdiction) { + this.immunizationJurisdiction = immunizationJurisdiction; + } +} diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/sample/SampleJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/sample/SampleJurisdictionBooleanValidator.java index 5a9364f0915..adf8711e39b 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/sample/SampleJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/sample/SampleJurisdictionBooleanValidator.java @@ -74,6 +74,16 @@ public Boolean isRootInJurisdictionOrOwned() { return userJurisdiction.getUuid().equals(sampleJurisdictionDto.getReportingUserUuid()) || inJurisdiction(); } + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + + boolean currentUserIsSurveilanceOfficer = userJurisdiction.getUuid().equals(sampleJurisdictionDto.getCaseJurisdiction().getSurveillanceOfficerUuid()); + boolean currentUserIsContactOfficer = userJurisdiction.getUuid().equals(sampleJurisdictionDto.getContactJurisdiction().getContactOfficerUuid()); + boolean currentUserIsResponsibleOfficer = userJurisdiction.getUuid().equals(sampleJurisdictionDto.getEventParticipantJurisdiction().getEventResponsibleUserUuid()); + + return currentUserIsSurveilanceOfficer || currentUserIsContactOfficer || currentUserIsResponsibleOfficer; + } + @Override protected Disease getDisease() { return null; diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/task/TaskJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/task/TaskJurisdictionBooleanValidator.java index 788613b2b84..f44def5a56f 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/task/TaskJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/task/TaskJurisdictionBooleanValidator.java @@ -69,7 +69,20 @@ public Boolean isRootInJurisdiction() { @Override public Boolean isRootInJurisdictionOrOwned() { - return userJurisdiction.getUuid().equals(taskJurisdictionDto.getCreatorUserUuid()) || userJurisdiction.getUuid().equals(taskJurisdictionDto.getAssigneeUserUuid()) || inJurisdiction(); + return getCreatedByCurrentUser() || getAssignedToCurrentUser() || inJurisdiction(); + } + + private boolean getAssignedToCurrentUser() { + return userJurisdiction.getUuid().equals(taskJurisdictionDto.getAssigneeUserUuid()); + } + + private boolean getCreatedByCurrentUser() { + return userJurisdiction. getUuid().equals(taskJurisdictionDto.getCreatorUserUuid()); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return isRootInJurisdictionOrOwned(); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserDtoHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserDtoHelper.java index 647aa000902..eeb1ee3e4ba 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserDtoHelper.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserDtoHelper.java @@ -132,4 +132,10 @@ public static UserReferenceDto toReferenceDto(User ado) { UserReferenceDto dto = new UserReferenceDto(ado.getUuid()); return dto; } + public static boolean isRestrictedToAssignEntities(User user) { + if (user != null && !user.getUserRoles().isEmpty()) { + return user.getUserRoles().stream().allMatch(UserRole::isRestrictAccessToAssignedEntities); + } + return false; + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRole.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRole.java index f4520cd7da9..715a009d80a 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRole.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRole.java @@ -69,6 +69,8 @@ public class UserRole extends AbstractDomainObject { private JurisdictionLevel jurisdictionLevel; @Enumerated(EnumType.STRING) private DefaultUserRole linkedDefaultUserRole; + @Column + private boolean restrictAccessToAssignedEntities; public String getUserRightsJson() { return userRightsJson; @@ -147,6 +149,14 @@ public void setPortHealthUser(boolean portHealthUser) { this.portHealthUser = portHealthUser; } + public boolean isRestrictAccessToAssignedEntities() { + return restrictAccessToAssignedEntities; + } + + public void setRestrictAccessToAssignedEntities(boolean restrictAccessToAssignedEntities) { + this.restrictAccessToAssignedEntities = restrictAccessToAssignedEntities; + } + public JurisdictionLevel getJurisdictionLevel() { return jurisdictionLevel; } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRoleDtoHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRoleDtoHelper.java index 951f76d4489..e4f1133b0f1 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRoleDtoHelper.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRoleDtoHelper.java @@ -63,6 +63,7 @@ public void fillInnerFromDto(UserRole target, UserRoleDto source) { target.setHasOptionalHealthFacility(source.getHasOptionalHealthFacility()); target.setJurisdictionLevel(source.getJurisdictionLevel()); target.setLinkedDefaultUserRole(source.getLinkedDefaultUserRole()); + target.setRestrictAccessToAssignedEntities(source.isRestrictAccessToAssignedEntities()); } @Override @@ -76,6 +77,7 @@ public void fillInnerFromAdo(UserRoleDto target, UserRole source) { target.setHasOptionalHealthFacility(source.hasOptionalHealthFacility()); target.setJurisdictionLevel(source.getJurisdictionLevel()); target.setLinkedDefaultUserRole(source.getLinkedDefaultUserRole()); + target.setRestrictAccessToAssignedEntities(source.isRestrictAccessToAssignedEntities()); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/util/BooleanJurisdictionValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/util/BooleanJurisdictionValidator.java index 5bdbee6f159..2a47be84acf 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/util/BooleanJurisdictionValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/util/BooleanJurisdictionValidator.java @@ -21,13 +21,15 @@ import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.utils.jurisdiction.JurisdictionValidator; +import de.symeda.sormas.app.backend.config.ConfigProvider; +import de.symeda.sormas.app.backend.user.UserDtoHelper; public abstract class BooleanJurisdictionValidator extends JurisdictionValidator { private final UserJurisdiction userJurisdiction; public BooleanJurisdictionValidator(List associatedJurisdictionValidators, UserJurisdiction userJurisdiction) { - super(associatedJurisdictionValidators); + super(associatedJurisdictionValidators, UserDtoHelper.isRestrictedToAssignEntities(ConfigProvider.getUser())); this.userJurisdiction = userJurisdiction; } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/util/JurisdictionHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/util/JurisdictionHelper.java index 51bf97b6bc5..37d32323ef2 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/util/JurisdictionHelper.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/util/JurisdictionHelper.java @@ -21,6 +21,8 @@ import de.symeda.sormas.app.backend.immunization.Immunization; import de.symeda.sormas.app.backend.immunization.ImmunizationJurisdictionDto; import de.symeda.sormas.app.backend.location.Location; +import de.symeda.sormas.app.backend.person.Person; +import de.symeda.sormas.app.backend.person.PersonJurisdictionDto; import de.symeda.sormas.app.backend.region.Community; import de.symeda.sormas.app.backend.region.District; import de.symeda.sormas.app.backend.region.Region; @@ -93,6 +95,9 @@ public static CaseJurisdictionDto createCaseJurisdictionDto(Case caze) { dto.setSampleLabUuids( samples.stream().filter(sample -> sample.getLab() != null).map(sample -> sample.getLab().getUuid()).collect(Collectors.toList())); } + if (caze.getSurveillanceOfficer() != null) { + dto.setSurveillanceOfficerUuid(caze.getSurveillanceOfficer().getUuid()); + } return dto; } @@ -118,6 +123,9 @@ public static ContactJurisdictionDto createContactJurisdictionDto(Contact contac dto.setCaseJurisdiction(JurisdictionHelper.createCaseJurisdictionDto(caseOfContact)); } + if (contact.getContactOfficer() != null) { + dto.setContactOfficerUuid(contact.getContactOfficer().getUuid()); + } return dto; } @@ -139,9 +147,49 @@ public static ImmunizationJurisdictionDto createImmunizationJurisdictionDto(Immu immunization.getHealthFacility()); immunizationJurisdictionDto.setResponsibleJurisdiction(responsibleJurisdiction); + Person immunizationPerson = immunization.getPerson(); + immunizationJurisdictionDto.setPersonJurisdiction(createPersonJurisdictionDto(immunizationPerson)); + return immunizationJurisdictionDto; } + public static PersonJurisdictionDto createPersonJurisdictionDto(Person person) { + if (person == null) { + return null; + } + + PersonJurisdictionDto personJurisdiction = new PersonJurisdictionDto(); + + DatabaseHelper.getCaseDao() + .getByPerson(person) + .stream() + .map(Case::getSurveillanceOfficer) + .collect(Collectors.toList()) + .forEach(caseSurveillanceOfficer -> { + personJurisdiction.getCaseJurisdiction().add(new CaseJurisdictionDto().setSurveillanceOfficerUuid(caseSurveillanceOfficer.getUuid())); + }); + + DatabaseHelper.getContactDao() + .getByPerson(person) + .stream() + .map(Contact::getContactOfficer) + .collect(Collectors.toList()) + .forEach(contactOfficer -> { + personJurisdiction.getContactJurisdiction().add(new ContactJurisdictionDto().setContactOfficerUuid(contactOfficer.getUuid())); + }); + + DatabaseHelper.getEventDao() + .getByEventParticipantPerson(person) + .stream() + .map(Event::getResponsibleUser) + .collect(Collectors.toList()) + .forEach(responsibleUser -> { + personJurisdiction.getEventJurisdiction().add(new EventJurisdictionDto().setResponsibleUserUuid(responsibleUser.getUuid())); + }); + + return personJurisdiction; + } + public static EventJurisdictionDto createEventJurisdictionDto(Event event) { if (event == null) { return null; @@ -199,6 +247,10 @@ public static EventParticipantJurisdictionDto createEventParticipantJurisdiction jurisdiction.setEventJurisdictionDto(JurisdictionHelper.createEventJurisdictionDto(event)); } + if (event.getResponsibleUser() != null) { + jurisdiction.setEventResponsibleUserUuid(event.getResponsibleUser().getUuid()); + } + return jurisdiction; } @@ -261,6 +313,10 @@ public static EnvironmentSampleJurisdictionDto createEnvironmentSampleJurisdicti } } + if (sample.getEnvironment().getResponsibleUser() != null) { + environmentSampleJurisdiction.setEnvironmentResponsibleUser(sample.getEnvironment().getResponsibleUser().getUuid()); + } + return environmentSampleJurisdiction; } From 5b51560ddf6c69370538d6db84ccd84551c8f14f Mon Sep 17 00:00:00 2001 From: sergiupacurariu <62688603+sergiupacurariu@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:25:55 +0200 Subject: [PATCH 3/6] #12697 - Assign case(s) to a User and allow them to see the data of only the assigned case(s) in the system - additional logic - changes after review --- ...ticipantFacadeEjbPseudonymizationTest.java | 42 ++++++----- ...nizationFacadeEjbPseudonymizationTest.java | 72 +++++++++---------- ...velEntryFacadeEjbPseudonymizationTest.java | 56 +++++++-------- .../filter/ImmunizationFilterForm.java | 2 - 4 files changed, 80 insertions(+), 92 deletions(-) diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjbPseudonymizationTest.java index d7bb4e5ca22..573b1334772 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjbPseudonymizationTest.java @@ -24,6 +24,7 @@ import java.util.Arrays; import java.util.List; +import java.util.function.Consumer; import org.junit.jupiter.api.Test; @@ -93,29 +94,23 @@ public void testPseudonymizedGetByUuidWithLimitedUser() { loginWith(nationalAdmin); // event within limited user's jurisdiction - EventParticipantDto eventParticipant1 = createEventParticipant(user1, rdcf1); - EventDto eventDto1 = getEventFacade().getEventByUuid(eventParticipant1.getEvent().getUuid(), false); - eventDto1.setConnectionNumber("123"); - getEventFacade().save(eventDto1); + EventParticipantDto eventParticipant1 = createEventParticipant(user1, rdcf1, e -> e.setConnectionNumber("123")); // event outside limited user's jurisdiction - EventParticipantDto eventParticipant2 = createEventParticipant(user2, rdcf2); - EventDto eventDto2 = getEventFacade().getEventByUuid(eventParticipant2.getEvent().getUuid(), false); - eventDto2.setConnectionNumber("456"); - getEventFacade().save(eventDto2); + EventParticipantDto eventParticipant2 = createEventParticipant(user2, rdcf2, e -> e.setConnectionNumber("456")); UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - final EventDto testEvent1 = getEventFacade().getEventByUuid(eventDto1.getUuid(), false); + final EventDto testEvent1 = getEventFacade().getEventByUuid(eventParticipant1.getEvent().getUuid(), false); assertThat(testEvent1.isPseudonymized(), is(true)); assertThat(testEvent1.getConnectionNumber(), is(emptyString())); final EventParticipantDto testEventParticipant1 = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant1.getUuid()); assertThat(testEventParticipant1.isPseudonymized(), is(true)); assertThat(testEventParticipant1.getPerson().getFirstName(), is("Confidential")); - final EventDto testEvent1Second = getEventFacade().getEventByUuid(eventDto2.getUuid(), false); + final EventDto testEvent1Second = getEventFacade().getEventByUuid(eventParticipant2.getEvent().getUuid(), false); assertThat(testEvent1Second.isPseudonymized(), is(true)); assertThat(testEvent1Second.getConnectionNumber(), is(emptyString())); final EventParticipantDto testEventParticipant1Second = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant2.getUuid()); @@ -123,16 +118,12 @@ public void testPseudonymizedGetByUuidWithLimitedUser() { assertThat(testEventParticipant1Second.getPerson().getFirstName(), is("Confidential")); // event created by limited user in the same jurisdiction - EventParticipantDto eventParticipant3 = createEventParticipant(surveillanceOfficerWithRestrictedAccessToAssignedEntities, rdcf1); - EventDto eventDto3 = getEventFacade().getEventByUuid(eventParticipant3.getEvent().getUuid(), false); - eventDto3.setConnectionNumber("789"); - getEventFacade().save(eventDto3); + EventParticipantDto eventParticipant3 = + createEventParticipant(surveillanceOfficerWithRestrictedAccessToAssignedEntities, rdcf1, e -> e.setConnectionNumber("789")); // event created by limited user outside it's jurisdiction - EventParticipantDto eventParticipant4 = createEventParticipant(surveillanceOfficerWithRestrictedAccessToAssignedEntities, rdcf2); - EventDto eventDto4 = getEventFacade().getEventByUuid(eventParticipant4.getEvent().getUuid(), false); - eventDto4.setConnectionNumber("987"); - getEventFacade().save(eventDto4); + EventParticipantDto eventParticipant4 = + createEventParticipant(surveillanceOfficerWithRestrictedAccessToAssignedEntities, rdcf2, e -> e.setConnectionNumber("987")); loginWith(nationalAdmin); testEvent1.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); @@ -141,28 +132,28 @@ public void testPseudonymizedGetByUuidWithLimitedUser() { getEventFacade().save(testEvent1Second); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - final EventDto testEvent3 = getEventFacade().getEventByUuid(eventDto1.getUuid(), false); + final EventDto testEvent3 = getEventFacade().getEventByUuid(eventParticipant1.getEvent().getUuid(), false); assertThat(testEvent3.isPseudonymized(), is(false)); assertThat(testEvent3.getConnectionNumber(), is("123")); final EventParticipantDto testEventParticipant3 = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant1.getUuid()); assertThat(testEventParticipant3.isPseudonymized(), is(false)); assertThat(testEventParticipant3.getPerson().getFirstName(), is("John")); - final EventDto testEvent3Second = getEventFacade().getEventByUuid(eventDto2.getUuid(), false); + final EventDto testEvent3Second = getEventFacade().getEventByUuid(eventParticipant2.getEvent().getUuid(), false); assertThat(testEvent3Second.isPseudonymized(), is(false)); assertThat(testEvent3Second.getConnectionNumber(), is("456")); final EventParticipantDto testEventParticipant3Second = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant2.getUuid()); assertThat(testEventParticipant3Second.isPseudonymized(), is(false)); assertThat(testEventParticipant3Second.getPerson().getFirstName(), is("John")); - final EventDto testEvent3Third = getEventFacade().getEventByUuid(eventDto3.getUuid(), false); + final EventDto testEvent3Third = getEventFacade().getEventByUuid(eventParticipant3.getEvent().getUuid(), false); assertThat(testEvent3Third.isPseudonymized(), is(false)); assertThat(testEvent3Third.getConnectionNumber(), is("789")); final EventParticipantDto testEventParticipant3Third = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant3.getUuid()); assertThat(testEventParticipant3Third.isPseudonymized(), is(false)); assertThat(testEventParticipant3Third.getPerson().getFirstName(), is("John")); - final EventDto testEvent3Fourth = getEventFacade().getEventByUuid(eventDto4.getUuid(), false); + final EventDto testEvent3Fourth = getEventFacade().getEventByUuid(eventParticipant4.getEvent().getUuid(), false); assertThat(testEvent3Fourth.isPseudonymized(), is(false)); assertThat(testEvent3Fourth.getConnectionNumber(), is("987")); final EventParticipantDto testEventParticipant3Fourth = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant4.getUuid()); @@ -246,10 +237,17 @@ public void testUpdateWithPseudonymizedDto() { } private EventParticipantDto createEventParticipant(UserDto user, TestDataCreator.RDCF rdcf) { + return createEventParticipant(user, rdcf, null); + } + + private EventParticipantDto createEventParticipant(UserDto user, TestDataCreator.RDCF rdcf, Consumer eventCustomSettings) { EventDto event = creator.createEvent(EventStatus.SIGNAL, EventInvestigationStatus.PENDING, "", "", user.toReference(), null, e -> { e.getEventLocation().setRegion(rdcf.region); e.getEventLocation().setDistrict(rdcf.district); e.getEventLocation().setCommunity(rdcf.community); + if (eventCustomSettings != null) { + eventCustomSettings.accept(e); + } }); PersonDto person = creator.createPerson("John", "Smith", Sex.MALE, 1980, 10, 23, p -> { diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/immunization/ImmunizationFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/immunization/ImmunizationFacadeEjbPseudonymizationTest.java index 6b2b56b5374..6b4f61d54b9 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/immunization/ImmunizationFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/immunization/ImmunizationFacadeEjbPseudonymizationTest.java @@ -119,28 +119,28 @@ public void testPseudonymizedGetByUuidWithLimitedUser() { // immunization within limited user's jurisdiction PersonDto person1 = creator.createPerson("John", "Doe"); final ImmunizationDto immunization1 = creator.createImmunization( - Disease.CORONAVIRUS, - person1.toReference(), - nationalUser.toReference(), - ImmunizationStatus.ACQUIRED, - MeansOfImmunization.VACCINATION, - ImmunizationManagementStatus.COMPLETED, - rdcf1); - immunization1.setAdditionalDetails("confidential details"); - getImmunizationFacade().save(immunization1); + Disease.CORONAVIRUS, + person1.toReference(), + nationalUser.toReference(), rdcf1, v->{ + v.setImmunizationStatus(ImmunizationStatus.ACQUIRED); + v.setMeansOfImmunization(MeansOfImmunization.VACCINATION); + v.setImmunizationManagementStatus(ImmunizationManagementStatus.COMPLETED); + v.setAdditionalDetails("confidential details"); + } + ); // immunization outside limited user's jurisdiction PersonDto person2 = creator.createPerson("Max", "MUstermann"); final ImmunizationDto immunization2 = creator.createImmunization( - Disease.CORONAVIRUS, - person2.toReference(), - nationalUser.toReference(), - ImmunizationStatus.ACQUIRED, - MeansOfImmunization.VACCINATION, - ImmunizationManagementStatus.COMPLETED, - rdcf2); - immunization2.setAdditionalDetails("confidential details second"); - getImmunizationFacade().save(immunization2); + Disease.CORONAVIRUS, + person2.toReference(), + nationalUser.toReference(), rdcf2, v-> { + v.setImmunizationStatus(ImmunizationStatus.ACQUIRED); + v.setMeansOfImmunization(MeansOfImmunization.VACCINATION); + v.setImmunizationManagementStatus(ImmunizationManagementStatus.COMPLETED); + v.setAdditionalDetails("confidential details second"); + } + ); UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); @@ -148,28 +148,28 @@ public void testPseudonymizedGetByUuidWithLimitedUser() { // immunization created by limited user within limited user's jurisdiction PersonDto person3 = creator.createPerson("John", "Doe"); final ImmunizationDto immunization3 = creator.createImmunization( - Disease.CORONAVIRUS, - person3.toReference(), - nationalUser.toReference(), - ImmunizationStatus.ACQUIRED, - MeansOfImmunization.VACCINATION, - ImmunizationManagementStatus.COMPLETED, - rdcf1); - immunization3.setAdditionalDetails("confidential details"); - getImmunizationFacade().save(immunization3); + Disease.CORONAVIRUS, + person3.toReference(), + nationalUser.toReference(), rdcf1, v-> { + v.setImmunizationStatus(ImmunizationStatus.ACQUIRED); + v.setMeansOfImmunization(MeansOfImmunization.VACCINATION); + v.setImmunizationManagementStatus(ImmunizationManagementStatus.COMPLETED); + v.setAdditionalDetails("confidential details"); + } + ); // immunization created by limited user outside limited user's jurisdiction PersonDto person4 = creator.createPerson("Max", "MUstermann"); final ImmunizationDto immunization4 = creator.createImmunization( - Disease.CORONAVIRUS, - person4.toReference(), - nationalUser.toReference(), - ImmunizationStatus.ACQUIRED, - MeansOfImmunization.VACCINATION, - ImmunizationManagementStatus.COMPLETED, - rdcf2); - immunization4.setAdditionalDetails("confidential details second"); - getImmunizationFacade().save(immunization4); + Disease.CORONAVIRUS, + person4.toReference(), + nationalUser.toReference(), rdcf2, v-> { + v.setImmunizationStatus(ImmunizationStatus.ACQUIRED); + v.setMeansOfImmunization(MeansOfImmunization.VACCINATION); + v.setImmunizationManagementStatus(ImmunizationManagementStatus.COMPLETED); + v.setAdditionalDetails("confidential details second"); + } + ); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); ImmunizationDto testImmunization = getImmunizationFacade().getByUuid(immunization1.getUuid()); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/travelentry/TravelEntryFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/travelentry/TravelEntryFacadeEjbPseudonymizationTest.java index 97eff06b42f..edb7f67d38a 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/travelentry/TravelEntryFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/travelentry/TravelEntryFacadeEjbPseudonymizationTest.java @@ -68,26 +68,22 @@ public void testPseudonymizedGetByUuidWithLimitedUser() { // travel entry within limited user's jurisdiction PersonDto person1 = creator.createPerson("John", "Doe"); TravelEntryDto travelEntry1 = creator.createTravelEntry( - person1.toReference(), - nationalUser.toReference(), - Disease.CORONAVIRUS, - rdcf1.region, - rdcf1.district, - rdcf1.pointOfEntry); - travelEntry1.setQuarantineHomePossibleComment("pacient can stay home"); - getTravelEntryFacade().save(travelEntry1); + person1.toReference(), + nationalUser.toReference(), rdcf1, v ->{ + v.setDisease(Disease.CORONAVIRUS); + v.setQuarantineHomePossibleComment("pacient can stay home"); + } + ); // travel entry outside limited user's jurisdiction PersonDto person2 = creator.createPerson("John", "Doe"); TravelEntryDto travelEntry2 = creator.createTravelEntry( - person2.toReference(), - nationalUser.toReference(), - Disease.CORONAVIRUS, - rdcf2.region, - rdcf2.district, - rdcf2.pointOfEntry); - travelEntry2.setQuarantineHomePossibleComment("pacient can stay home second"); - getTravelEntryFacade().save(travelEntry2); + person2.toReference(), + nationalUser.toReference(),rdcf2, v -> { + v.setDisease(Disease.CORONAVIRUS); + v.setQuarantineHomePossibleComment("pacient can stay home second"); + } + ); loginWith(nationalAdmin); UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = @@ -96,26 +92,22 @@ public void testPseudonymizedGetByUuidWithLimitedUser() { // travel entry created by limited user within limited user's jurisdiction PersonDto person3 = creator.createPerson("John", "Doe"); TravelEntryDto travelEntry3 = creator.createTravelEntry( - person3.toReference(), - nationalUser.toReference(), - Disease.CORONAVIRUS, - rdcf1.region, - rdcf1.district, - rdcf1.pointOfEntry); - travelEntry3.setQuarantineHomePossibleComment("pacient can stay home"); - getTravelEntryFacade().save(travelEntry3); + person3.toReference(), + nationalUser.toReference(), rdcf1, v -> { + v.setDisease(Disease.CORONAVIRUS); + v.setQuarantineHomePossibleComment("pacient can stay home"); + } + ); // travel entry created by limited user outside limited user's jurisdiction PersonDto person4 = creator.createPerson("John", "Doe"); TravelEntryDto travelEntry4 = creator.createTravelEntry( - person4.toReference(), - nationalUser.toReference(), - Disease.CORONAVIRUS, - rdcf2.region, - rdcf2.district, - rdcf2.pointOfEntry); - travelEntry4.setQuarantineHomePossibleComment("pacient can stay home second"); - getTravelEntryFacade().save(travelEntry4); + person4.toReference(), + nationalUser.toReference(), rdcf2, v-> { + v.setDisease(Disease.CORONAVIRUS); + v.setQuarantineHomePossibleComment("pacient can stay home second"); + } + ); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); TravelEntryDto testTravelEntry = getTravelEntryFacade().getByUuid(travelEntry1.getUuid()); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/filter/ImmunizationFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/filter/ImmunizationFilterForm.java index fd957f004d4..3dde895c3fc 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/filter/ImmunizationFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/filter/ImmunizationFilterForm.java @@ -100,10 +100,8 @@ protected void addFields() { @Override public void addMoreFilters(CustomLayout moreFiltersContainer) { -// if (currentUserDto().getRegion() == null) { ComboBox regionFilter = addField(moreFiltersContainer, FieldConfiguration.pixelSized(ImmunizationCriteria.REGION, 140)); regionFilter.addItems(FacadeProvider.getRegionFacade().getAllActiveByServerCountry()); -// } ComboBox districtFilter = addField(moreFiltersContainer, FieldConfiguration.pixelSized(ImmunizationCriteria.DISTRICT, 140)); districtFilter.setDescription(I18nProperties.getDescription(Descriptions.descDistrictFilter)); From 06a8db28949f6533989739ae4ff34426159fb7a8 Mon Sep 17 00:00:00 2001 From: sergiupacurariu <62688603+sergiupacurariu@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:28:36 +0200 Subject: [PATCH 4/6] #12697 - Assign case(s) to a User and allow them to see the data of only the assigned case(s) in the system - additional logic - changes after review - android --- .../contact/ContactJurisdictionBooleanValidator.java | 6 +++--- .../EnvironmentJurisdictionBooleanValidator.java | 6 +++--- .../backend/event/EventJurisdictionBooleanValidator.java | 6 +++--- .../immunization/ImmunizationJurisdictionDto.java | 9 --------- .../person/PersonJurisdictionBooleanValidator.java | 2 +- 5 files changed, 10 insertions(+), 19 deletions(-) diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionBooleanValidator.java index 0b2015fa5b4..f403de6e02a 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionBooleanValidator.java @@ -48,16 +48,16 @@ public Boolean isRootInJurisdiction() { @Override public Boolean isRootInJurisdictionOrOwned() { - return getReportedByCurrentUser() || inJurisdiction(); + return isReportedByCurrentUser() || inJurisdiction(); } - private boolean getReportedByCurrentUser(){ + private boolean isReportedByCurrentUser(){ return userJurisdiction.getUuid().equals(contactJurisdictionDto.getReportingUserUuid()); } @Override public Boolean isRootInJurisdictionForRestrictedAccess() { - return getReportedByCurrentUser() || userJurisdiction.getUuid().equals(contactJurisdictionDto.getContactOfficerUuid()); + return isReportedByCurrentUser() || userJurisdiction.getUuid().equals(contactJurisdictionDto.getContactOfficerUuid()); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java index 568900ac618..62072116bbf 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java @@ -32,17 +32,17 @@ public Boolean isRootInJurisdiction() { @Override public Boolean isRootInJurisdictionOrOwned() { - return getReportedAndResponsibleByCurrentUser() || inJurisdiction(); + return isReportedAndResponsibleByCurrentUser() || inJurisdiction(); } - private boolean getReportedAndResponsibleByCurrentUser() { + private boolean isReportedAndResponsibleByCurrentUser() { return userJurisdiction.getUuid().equals(environmentJurisdiction.getReportingUserUuid()) || userJurisdiction.getUuid().equals(environmentJurisdiction.getResponsibleUserUuid()); } @Override public Boolean isRootInJurisdictionForRestrictedAccess() { - return getReportedAndResponsibleByCurrentUser(); + return isReportedAndResponsibleByCurrentUser(); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionBooleanValidator.java index fdcf81f4aa6..0e36bdcd101 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionBooleanValidator.java @@ -45,20 +45,20 @@ public Boolean isRootInJurisdiction() { @Override public Boolean isRootInJurisdictionOrOwned() { - return getReportedByCurrentUser() || getCurrentUserResponsible() || inJurisdiction(); + return getReportedByCurrentUser() || isCurrentUserResponsible() || inJurisdiction(); } private boolean getReportedByCurrentUser() { return userJurisdiction.getUuid().equals(eventJurisdictionDto.getReportingUserUuid()); } - public boolean getCurrentUserResponsible() { + public boolean isCurrentUserResponsible() { return userJurisdiction.getUuid().equals(eventJurisdictionDto.getResponsibleUserUuid()); } @Override public Boolean isRootInJurisdictionForRestrictedAccess() { - return getReportedByCurrentUser() || getCurrentUserResponsible(); + return getReportedByCurrentUser() || isCurrentUserResponsible(); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionDto.java index 089418222c0..1299991e94b 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionDto.java @@ -27,8 +27,6 @@ public class ImmunizationJurisdictionDto implements Serializable { private String reportingUserUuid; private ResponsibleJurisdictionDto responsibleJurisdiction; - - private String personUuid; private PersonJurisdictionDto personJurisdiction; public ImmunizationJurisdictionDto() { } @@ -55,13 +53,6 @@ public ResponsibleJurisdictionDto getResponsibleJurisdiction() { public void setResponsibleJurisdiction(ResponsibleJurisdictionDto responsibleJurisdiction) { this.responsibleJurisdiction = responsibleJurisdiction; } - public String getPersonUuid() { - return personUuid; - } - - public void setPersonUuid(String personUuid) { - this.personUuid = personUuid; - } public PersonJurisdictionDto getPersonJurisdiction() { return personJurisdiction; diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java index 16d4c9ae45f..a5bbd043351 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java @@ -12,7 +12,7 @@ public class PersonJurisdictionBooleanValidator extends BooleanJurisdictionValidator { private final PersonJurisdictionDto personJurisdiction; - private final UserJurisdiction userJurisdiction; + protected final UserJurisdiction userJurisdiction; public PersonJurisdictionBooleanValidator(UserJurisdiction userJurisdiction, PersonJurisdictionDto personJurisdiction) { super(null, userJurisdiction); From 79dcfa125ff205426f6b25c84499e8248207a8f8 Mon Sep 17 00:00:00 2001 From: sergiupacurariu <62688603+sergiupacurariu@users.noreply.github.com> Date: Tue, 23 Jan 2024 14:24:28 +0200 Subject: [PATCH 5/6] #12697 - Assign case(s) to a User and allow them to see the data of only the assigned case(s) in the system - additional logic - changes after review --- .../PersonJurisdictionBooleanValidator.java | 48 ++++++++-------- .../backend/person/PersonJurisdictionDto.java | 56 +++++++++---------- .../sormas/app/util/JurisdictionHelper.java | 46 +++++++-------- .../sormas/backend/caze/CaseService.java | 5 +- .../backend/contact/ContactService.java | 5 +- .../EnvironmentSampleService.java | 7 +-- ...izationJurisdictionPredicateValidator.java | 28 +++++++++- .../DirectoryImmunizationService.java | 18 ------ .../immunization/ImmunizationService.java | 22 +------- .../sormas/backend/person/PersonService.java | 17 ------ .../SampleJurisdictionPredicateValidator.java | 1 - .../sormas/backend/sample/SampleService.java | 6 +- .../TaskJurisdictionPredicateValidator.java | 3 - .../sormas/backend/task/TaskService.java | 25 +++------ ...ntSampleFacadeEjbPseudonymizationTest.java | 4 -- 15 files changed, 117 insertions(+), 174 deletions(-) diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java index a5bbd043351..54bec46e25e 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java @@ -1,11 +1,10 @@ package de.symeda.sormas.app.backend.person; -import java.util.stream.Collectors; - import de.symeda.sormas.api.Disease; import de.symeda.sormas.app.backend.caze.CaseJurisdictionDto; import de.symeda.sormas.app.backend.contact.ContactJurisdictionDto; import de.symeda.sormas.app.backend.event.EventJurisdictionDto; +import de.symeda.sormas.app.core.NotImplementedException; import de.symeda.sormas.app.util.BooleanJurisdictionValidator; import de.symeda.sormas.app.util.UserJurisdiction; @@ -27,75 +26,78 @@ protected Disease getDisease() { @Override public Boolean isRootInJurisdiction() { - return false; + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); } @Override public Boolean isRootInJurisdictionOrOwned() { - return this.isRootInJurisdiction(); + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); } @Override public Boolean isRootInJurisdictionForRestrictedAccess() { - boolean currentUserIsSurveillanceOfficer = personJurisdiction.getCaseJurisdiction() + boolean currentUserIsSurveillanceOfficer = personJurisdiction.getCaseJurisdictions() .stream() .map(CaseJurisdictionDto::getSurveillanceOfficerUuid) - .collect(Collectors.toList()) - .contains(userJurisdiction.getUuid()); + .anyMatch(surveillanceOfficer -> surveillanceOfficer.equals(userJurisdiction.getUuid())); + + if (currentUserIsSurveillanceOfficer) { + return true; + } - boolean currentUserIsContactOfficer = personJurisdiction.getContactJurisdiction() + boolean currentUserIsContactOfficer = personJurisdiction.getContactJurisdictions() .stream() .map(ContactJurisdictionDto::getContactOfficerUuid) - .collect(Collectors.toList()) - .contains(userJurisdiction.getUuid()); + .anyMatch(contactOfficer -> contactOfficer.equals(userJurisdiction.getUuid())); - boolean currentUserIsResponsibleUser = personJurisdiction.getEventJurisdiction() + if (currentUserIsContactOfficer) { + return true; + } + + return personJurisdiction.getEventJurisdictions() .stream() .map(EventJurisdictionDto::getResponsibleUserUuid) - .collect(Collectors.toList()) - .contains(userJurisdiction.getUuid()); - - return currentUserIsSurveillanceOfficer || currentUserIsContactOfficer || currentUserIsResponsibleUser; + .anyMatch(responsibleUser -> responsibleUser.equals(userJurisdiction.getUuid())); } @Override protected Boolean whenNotAllowed() { - return false; + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); } @Override protected Boolean whenNationalLevel() { - return false; + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); } @Override protected Boolean whenRegionalLevel() { - return false; + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); } @Override protected Boolean whenDistrictLevel() { - return false; + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); } @Override protected Boolean whenCommunityLevel() { - return false; + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); } @Override protected Boolean whenFacilityLevel() { - return false; + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); } @Override protected Boolean whenPointOfEntryLevel() { - return false; + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); } @Override protected Boolean whenLaboratoryLevel() { - return false; + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionDto.java index a439cac90b6..f57a6db55bc 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionDto.java @@ -11,55 +11,55 @@ public class PersonJurisdictionDto implements Serializable { - private List caseJurisdiction = new ArrayList<>(); - private List contactJurisdiction = new ArrayList<>(); - private List eventJurisdiction = new ArrayList<>(); - private List immunizationJurisdiction = new ArrayList<>(); + private List caseJurisdictions = new ArrayList<>(); + private List contactJurisdictions = new ArrayList<>(); + private List eventJurisdictions = new ArrayList<>(); + private List immunizationJurisdictions = new ArrayList<>(); public PersonJurisdictionDto() { } public PersonJurisdictionDto( - List caseJurisdiction, - List contactJurisdiction, - List eventJurisdiction, - List immunizationJurisdiction) { - this.caseJurisdiction = caseJurisdiction; - this.contactJurisdiction = contactJurisdiction; - this.eventJurisdiction = eventJurisdiction; - this.immunizationJurisdiction = immunizationJurisdiction; + List caseJurisdictions, + List contactJurisdictions, + List eventJurisdictions, + List immunizationJurisdictions) { + this.caseJurisdictions = caseJurisdictions; + this.contactJurisdictions = contactJurisdictions; + this.eventJurisdictions = eventJurisdictions; + this.immunizationJurisdictions = immunizationJurisdictions; } - public List getCaseJurisdiction() { - return caseJurisdiction; + public List getCaseJurisdictions() { + return caseJurisdictions; } - public void setCaseJurisdiction(List caseJurisdiction) { - this.caseJurisdiction = caseJurisdiction; + public void setCaseJurisdictions(List caseJurisdictions) { + this.caseJurisdictions = caseJurisdictions; } - public List getContactJurisdiction() { - return contactJurisdiction; + public List getContactJurisdictions() { + return contactJurisdictions; } - public void setContactJurisdiction(List contactJurisdiction) { - this.contactJurisdiction = contactJurisdiction; + public void setContactJurisdictions(List contactJurisdictions) { + this.contactJurisdictions = contactJurisdictions; } - public List getEventJurisdiction() { - return eventJurisdiction; + public List getEventJurisdictions() { + return eventJurisdictions; } - public void setEventJurisdiction(List eventJurisdiction) { - this.eventJurisdiction = eventJurisdiction; + public void setEventJurisdictions(List eventJurisdictions) { + this.eventJurisdictions = eventJurisdictions; } - public List getImmunizationJurisdiction() { - return immunizationJurisdiction; + public List getImmunizationJurisdictions() { + return immunizationJurisdictions; } - public void setImmunizationJurisdiction(List immunizationJurisdiction) { - this.immunizationJurisdiction = immunizationJurisdiction; + public void setImmunizationJurisdictions(List immunizationJurisdictions) { + this.immunizationJurisdictions = immunizationJurisdictions; } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/util/JurisdictionHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/util/JurisdictionHelper.java index 37d32323ef2..df50cbc7573 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/util/JurisdictionHelper.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/util/JurisdictionHelper.java @@ -160,32 +160,26 @@ public static PersonJurisdictionDto createPersonJurisdictionDto(Person person) { PersonJurisdictionDto personJurisdiction = new PersonJurisdictionDto(); - DatabaseHelper.getCaseDao() - .getByPerson(person) - .stream() - .map(Case::getSurveillanceOfficer) - .collect(Collectors.toList()) - .forEach(caseSurveillanceOfficer -> { - personJurisdiction.getCaseJurisdiction().add(new CaseJurisdictionDto().setSurveillanceOfficerUuid(caseSurveillanceOfficer.getUuid())); - }); - - DatabaseHelper.getContactDao() - .getByPerson(person) - .stream() - .map(Contact::getContactOfficer) - .collect(Collectors.toList()) - .forEach(contactOfficer -> { - personJurisdiction.getContactJurisdiction().add(new ContactJurisdictionDto().setContactOfficerUuid(contactOfficer.getUuid())); - }); - - DatabaseHelper.getEventDao() - .getByEventParticipantPerson(person) - .stream() - .map(Event::getResponsibleUser) - .collect(Collectors.toList()) - .forEach(responsibleUser -> { - personJurisdiction.getEventJurisdiction().add(new EventJurisdictionDto().setResponsibleUserUuid(responsibleUser.getUuid())); - }); + personJurisdiction.setCaseJurisdictions( + DatabaseHelper.getCaseDao() + .getByPerson(person) + .stream() + .map(surveillanceOfficer -> new CaseJurisdictionDto().setSurveillanceOfficerUuid(surveillanceOfficer.getUuid())) + .collect(Collectors.toList())); + + personJurisdiction.setContactJurisdictions( + DatabaseHelper.getContactDao() + .getByPerson(person) + .stream() + .map(contactOfficer -> new ContactJurisdictionDto().setContactOfficerUuid(contactOfficer.getUuid())) + .collect(Collectors.toList())); + + personJurisdiction.setEventJurisdictions( + DatabaseHelper.getEventDao() + .getByEventParticipantPerson(person) + .stream() + .map(responsibleUser -> new EventJurisdictionDto().setResponsibleUserUuid(responsibleUser.getUuid())) + .collect(Collectors.toList())); return personJurisdiction; } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseService.java index 8003d85444a..880f88fb0d3 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseService.java @@ -1395,7 +1395,8 @@ public Predicate createUserFilter(CaseQueryContext caseQueryContext, CaseUserFil final JurisdictionLevel jurisdictionLevel = currentUser.getJurisdictionLevel(); - if (isRestrictedToAssignedEntities()) { + final boolean restrictedToAssignedEntities = isRestrictedToAssignedEntities(); + if (restrictedToAssignedEntities) { filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(casePath.get(Case.SURVEILLANCE_OFFICER).get(User.ID), currentUser.getId())); } @@ -1410,7 +1411,7 @@ public Predicate createUserFilter(CaseQueryContext caseQueryContext, CaseUserFil filterResponsible = cb.disjunction(); } - if (!isRestrictedToAssignedEntities()) { + if (!restrictedToAssignedEntities) { switch (jurisdictionLevel) { case REGION: final Region region = currentUser.getRegion(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java index f90d0c83a6f..c869b4e5c28 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java @@ -1082,7 +1082,8 @@ public Predicate createUserFilterWithoutCase(ContactQueryContext qc, ContactCrit Predicate filter = null; - if (isRestrictedToAssignedEntities()) { + final boolean restrictedToAssignedEntities = isRestrictedToAssignedEntities(); + if (restrictedToAssignedEntities) { filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(contactRoot.get(Contact.CONTACT_OFFICER).get(User.ID), getCurrentUser().getId())); } @@ -1098,7 +1099,7 @@ public Predicate createUserFilterWithoutCase(ContactQueryContext qc, ContactCrit filter = cb.or(filter, cb.equal(contactRoot.get(Contact.CONTACT_OFFICER), currentUser)); } - if (!isRestrictedToAssignedEntities()) { + if (!restrictedToAssignedEntities) { switch (jurisdictionLevel) { case REGION: final Region region = currentUser.getRegion(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleService.java index d961e7dbb30..35ac3d17963 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleService.java @@ -197,14 +197,9 @@ public Predicate buildCriteriaFilter(EnvironmentSampleCriteria criteria, Environ } private Predicate inJurisdictionOrOwned(CriteriaBuilder cb, CriteriaQuery cq, From from) { - if (isRestrictedToAssignedEntities()) { - return EnvironmentSampleJurisdictionValidator - .of(new EnvironmentSampleQueryContext(cb, cq, from, new EnvironmentSampleJoins(from)), userService.getCurrentUser()) - .isRootInJurisdictionForRestrictedAccess(); - } return EnvironmentSampleJurisdictionValidator .of(new EnvironmentSampleQueryContext(cb, cq, from, new EnvironmentSampleJoins(from)), userService.getCurrentUser()) - .isRootInJurisdictionOrOwned(); + .inJurisdictionOrOwned(); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationJurisdictionPredicateValidator.java index 0f9d5450b60..12f5d79fcdc 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationJurisdictionPredicateValidator.java @@ -1,16 +1,24 @@ package de.symeda.sormas.backend.immunization; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import javax.persistence.criteria.Subquery; +import de.symeda.sormas.api.person.PersonAssociation; +import de.symeda.sormas.backend.common.AbstractDomainObject; import de.symeda.sormas.backend.immunization.entity.Immunization; import de.symeda.sormas.backend.infrastructure.community.Community; import de.symeda.sormas.backend.infrastructure.district.District; import de.symeda.sormas.backend.infrastructure.facility.Facility; import de.symeda.sormas.backend.infrastructure.region.Region; +import de.symeda.sormas.backend.person.PersonJurisdictionPredicateValidator; import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.util.PredicateJurisdictionValidator; @@ -54,7 +62,25 @@ private Predicate getReportedByCurrentUser() { @Override public Predicate isRootInJurisdictionForRestrictedAccess() { //for restricted access the immunization is only accessible when the associated person is accessible - return cb.disjunction(); + Predicate isRootInJurisdiction = isRootInJurisdictionOrOwned(); + + final CriteriaQuery cq = queryContext.getQuery(); + + Subquery personSubquery = cq.subquery(Boolean.class); + final Root from = personSubquery.from(Immunization.class); + ImmunizationJoins immunizationJoins = new ImmunizationJoins(from); + final Predicate isPersonInJurisdiction = PersonJurisdictionPredicateValidator + .of( + cq, + cb, + immunizationJoins.getPersonJoins(), + user, + new HashSet<>(Arrays.asList(PersonAssociation.CASE, PersonAssociation.CONTACT, PersonAssociation.EVENT_PARTICIPANT))) + .isRootInJurisdictionForRestrictedAccess(); + personSubquery.select(from.get(AbstractDomainObject.ID)); + personSubquery.where(isPersonInJurisdiction, cb.equal(from.get(AbstractDomainObject.ID), joins.getRoot().get(AbstractDomainObject.ID))); + + return and(isRootInJurisdiction, cb.exists(personSubquery)); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationService.java index fe7e74052d1..bf7f19d79ab 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationService.java @@ -403,25 +403,7 @@ private Predicate createUserFilter(DirectoryImmunizationQueryContext qc) { final CriteriaBuilder cb = qc.getCriteriaBuilder(); Predicate filter = null; - if (isRestrictedToAssignedEntities()) { - final PersonQueryContext personQueryContext = new PersonQueryContext(cb, qc.getQuery(), qc.getJoins().getPersonJoins()); - - final PersonCriteria personCaseCriteria = new PersonCriteria(); - personCaseCriteria.setPersonAssociation(PersonAssociation.CASE); - final Predicate personCaseUserFilter = personService.createUserFilter(personQueryContext, personCaseCriteria); - - final PersonCriteria personContactCriteria = new PersonCriteria(); - personContactCriteria.setPersonAssociation(PersonAssociation.CONTACT); - final Predicate personContactUserFilter = personService.createUserFilter(personQueryContext, personContactCriteria); - - final PersonCriteria personEventParticipantCriteria = new PersonCriteria(); - personEventParticipantCriteria.setPersonAssociation(PersonAssociation.EVENT_PARTICIPANT); - final Predicate personEventParticipantUserFilter = personService.createUserFilter(personQueryContext, personEventParticipantCriteria); - - filter = CriteriaBuilderHelper.and(cb, filter, cb.or(personCaseUserFilter, personContactUserFilter, personEventParticipantUserFilter)); - } else { filter = isInJurisdictionOrOwned(qc); - } filter = CriteriaBuilderHelper .and(cb, filter, CriteriaBuilderHelper.limitedDiseasePredicate(cb, currentUser, qc.getRoot().get(Immunization.DISEASE))); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationService.java index aaff5434809..1ef94f30efa 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationService.java @@ -558,27 +558,7 @@ public Predicate createUserFilter(ImmunizationQueryContext qc) { } final CriteriaBuilder cb = qc.getCriteriaBuilder(); - Predicate filter = null; - if (isRestrictedToAssignedEntities()) { - final PersonQueryContext personQueryContext = new PersonQueryContext(cb, qc.getQuery(), qc.getJoins().getPersonJoins()); - - final PersonCriteria personCaseCriteria = new PersonCriteria(); - personCaseCriteria.setPersonAssociation(PersonAssociation.CASE); - final Predicate personCaseUserFilter = personService.createUserFilter(personQueryContext, personCaseCriteria); - - final PersonCriteria personContactCriteria = new PersonCriteria(); - personContactCriteria.setPersonAssociation(PersonAssociation.CONTACT); - final Predicate personContactUserFilter = personService.createUserFilter(personQueryContext, personContactCriteria); - - final PersonCriteria personEventParticipantCriteria = new PersonCriteria(); - personEventParticipantCriteria.setPersonAssociation(PersonAssociation.EVENT_PARTICIPANT); - final Predicate personEventParticipantUserFilter = personService.createUserFilter(personQueryContext, personEventParticipantCriteria); - - filter = CriteriaBuilderHelper.and(cb, filter, cb.or(personCaseUserFilter, personContactUserFilter, personEventParticipantUserFilter)); - - } else { - filter = inJurisdictionOrOwned(qc); - } + Predicate filter = inJurisdictionOrOwned(qc); filter = CriteriaBuilderHelper .and(cb, filter, CriteriaBuilderHelper.limitedDiseasePredicate(cb, currentUser, qc.getRoot().get(Immunization.DISEASE))); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonService.java index 49e5b749550..b681af27ae7 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonService.java @@ -295,17 +295,8 @@ public Predicate createUserFilter(PersonQueryContext queryContext, PersonCriteri createAssociationPredicate(queryContext, PersonAssociation.TRAVEL_ENTRY)); break; case CASE: - userFilter = - CriteriaBuilderHelper.or(queryContext.getCriteriaBuilder(), createAssociationPredicate(queryContext, PersonAssociation.CASE)); - break; case CONTACT: - userFilter = - CriteriaBuilderHelper.or(queryContext.getCriteriaBuilder(), createAssociationPredicate(queryContext, PersonAssociation.CONTACT)); - break; case EVENT_PARTICIPANT: - userFilter = CriteriaBuilderHelper - .or(queryContext.getCriteriaBuilder(), createAssociationPredicate(queryContext, PersonAssociation.EVENT_PARTICIPANT)); - break; case IMMUNIZATION: case TRAVEL_ENTRY: userFilter = createAssociationPredicate(queryContext, personAssociation); @@ -362,24 +353,16 @@ private Predicate createAssociationPredicate(@NotNull PersonQueryContext queryCo eventParticipantService.createDefaultFilter(cb, joins.getEventParticipant())); break; case IMMUNIZATION: - if (!isRestrictedToAssignedEntities()) { associationPredicate = CriteriaBuilderHelper.and( cb, immunizationService.createUserFilter(new ImmunizationQueryContext(cb, cq, joins.getImmunizationJoins())), immunizationService.createDefaultFilter(cb, joins.getImmunization())); - } else { - associationPredicate = CriteriaBuilderHelper.and(cb, cb.disjunction()); - } break; case TRAVEL_ENTRY: - if (!isRestrictedToAssignedEntities()) { associationPredicate = CriteriaBuilderHelper.and( cb, travelEntryService.createUserFilter(new TravelEntryQueryContext(cb, cq, joins.getTravelEntryJoins())), travelEntryService.createDefaultFilter(cb, joins.getTravelEntry())); - } else { - associationPredicate = CriteriaBuilderHelper.and(cb, cb.disjunction()); - } break; case ALL: default: diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleJurisdictionPredicateValidator.java index 1a0b98cb8f6..c7435a91c9a 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleJurisdictionPredicateValidator.java @@ -92,7 +92,6 @@ public Predicate isRootInJurisdictionOrOwned() { @Override public Predicate inJurisdictionOrOwned() { -// Predicate rootInJurisdictionOrOwned = isRootInJurisdictionOrOwned(); Predicate rootInJurisdictionOrOwned = isRootAccessible(); Predicate rootHasLimitedDisease = hasUserLimitedDisease(); if (associatedJurisdictionValidators != null && !associatedJurisdictionValidators.isEmpty()) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleService.java index 1c02c6e4ed2..db56f74dd51 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleService.java @@ -723,18 +723,16 @@ public Subquery exists(CriteriaBuilder cb, CriteriaQuery cq, Join @Override public SampleJurisdictionFlagsDto getJurisdictionFlags(Sample entity) { - final SampleJurisdictionFlagsDto sampleJurisdictionFlagsDto = getJurisdictionsFlags(Collections.singletonList(entity)).get(entity.getId()); - return sampleJurisdictionFlagsDto; + return getJurisdictionsFlags(Collections.singletonList(entity)).get(entity.getId()); } @Override public Map getJurisdictionsFlags(List entities) { - final Map selectionAttributes = getSelectionAttributes( + return getSelectionAttributes( entities, (cb, cq, from) -> getJurisdictionSelections(new SampleQueryContext(cb, cq, from)), e -> new SampleJurisdictionFlagsDto(e)); - return selectionAttributes; } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskJurisdictionPredicateValidator.java index a1389874152..e1afc6bda9d 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskJurisdictionPredicateValidator.java @@ -91,10 +91,7 @@ public Predicate isRootInJurisdictionForRestrictedAccess() { List associationPredicates = new ArrayList<>(associatedJurisdictionValidators.size()); for (JurisdictionValidator associatedJurisdictionValidator : associatedJurisdictionValidators) { - if (!TravelEntryJurisdictionPredicateValidator.class.isAssignableFrom(associatedJurisdictionValidator.getClass()) - && !ImmunizationJurisdictionPredicateValidator.class.isAssignableFrom(associatedJurisdictionValidator.getClass())) { associationPredicates.add(associatedJurisdictionValidator.isRootInJurisdictionForRestrictedAccess()); - } } return cb.or(createdByCurrentUser, assignedToCurrentUser, or(associationPredicates)); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskService.java index 27bc27c9653..cdc883d3c5d 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskService.java @@ -41,7 +41,6 @@ import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.persistence.criteria.Selection; -import javax.persistence.criteria.Subquery; import de.symeda.sormas.backend.util.JurisdictionHelper; import org.apache.commons.lang3.ArrayUtils; @@ -220,11 +219,12 @@ public Predicate createUserFilter(TaskQueryContext taskQueryContext, TaskCriteri TaskJoins joins = taskQueryContext.getJoins(); - Predicate assigneeFilter; + Predicate assigneeJurisdictionFilter; if (isRestrictedToAssignedEntities()) { - assigneeFilter = cb.disjunction(); + //filters out tasks assigned to other users in the same jurisdiction (which are not linked to a core entity assigned to the limited user) + assigneeJurisdictionFilter = cb.disjunction(); } else { - assigneeFilter = createAssigneeFilter(cb, joins.getAssignee()); + assigneeJurisdictionFilter = createAssigneeJurisdictionFilter(cb, joins.getAssignee()); } Predicate relatedEntityNotDeletedFilter = cb.or( @@ -237,7 +237,7 @@ public Predicate createUserFilter(TaskQueryContext taskQueryContext, TaskCriteri final JurisdictionLevel jurisdictionLevel = currentUser.getJurisdictionLevel(); if (jurisdictionLevel == JurisdictionLevel.NATION && currentUser.getUserRoles().stream().noneMatch(UserRole::isPortHealthUser)) { - return cb.and(assigneeFilter, relatedEntityNotDeletedFilter); + return cb.and(assigneeJurisdictionFilter, relatedEntityNotDeletedFilter); } Predicate filter = cb.equal(taskPath.get(Task.CREATOR_USER), currentUser); @@ -281,7 +281,7 @@ public Predicate createUserFilter(TaskQueryContext taskQueryContext, TaskCriteri filter = cb.or(filter, environmantFilter); } - filter = cb.or(filter, assigneeFilter); + filter = cb.or(filter, assigneeJurisdictionFilter); if (RequestContextHolder.isMobileSync()) { Predicate limitedChangeDatePredicate = CriteriaBuilderHelper.and(cb, createLimitedChangeDateFilter(cb, taskQueryContext.getRoot())); @@ -331,7 +331,7 @@ protected Predicate getUserFilterForObsoleteUuids(CriteriaBuilder cb, CriteriaQu return createUserFilter(new TaskQueryContext(cb, cq, from), new TaskCriteria().excludeLimitedSyncRestrictions(true)); } - public Predicate createAssigneeFilter(CriteriaBuilder cb, Join assigneeUserJoin) { + public Predicate createAssigneeJurisdictionFilter(CriteriaBuilder cb, Join assigneeUserJoin) { return CriteriaBuilderHelper .or(cb, cb.isNull(assigneeUserJoin.get(User.UUID)), userService.createCurrentUserJurisdictionFilter(cb, assigneeUserJoin)); } @@ -864,17 +864,6 @@ public List> getJurisdictionSelections(TaskQueryContext qc) { environmentService.inJurisdictionOrOwned(new EnvironmentQueryContext(cb, qc.getQuery(), joins.getEnvironmentJoins()))))); } - private Predicate getObjectSubquery(TaskQueryContext qc, CriteriaBuilder cb, Function jurisdictionPredicate) { - Subquery inJurisditionSubquery = qc.getQuery().subquery(Object.class); - final Root from = inJurisditionSubquery.from(Task.class); - TaskJoins taskJoins = new TaskJoins(from); - inJurisditionSubquery.select(from.get(AbstractDomainObject.ID)); - inJurisditionSubquery - .where(jurisdictionPredicate.apply(taskJoins), cb.equal(from.get(AbstractDomainObject.ID), qc.getRoot().get(AbstractDomainObject.ID))); - - return cb.exists(inJurisditionSubquery); - } - @Override public Predicate inJurisdictionOrOwned(TaskQueryContext qc) { final User currentUser = userService.getCurrentUser(); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbPseudonymizationTest.java index a9ae8b16f2f..a050abfa006 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbPseudonymizationTest.java @@ -93,10 +93,6 @@ public void testPseudonymizedGetByUuidWithLimitedUser() { s.getLocation().setCity("Test city second"); }); -// loginWith(nationalAdmin); -// UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = -// creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); - loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); EnvironmentSampleDto testSample1 = getEnvironmentSampleFacade().getByUuid(sample1.getUuid()); assertThat(testSample1.isPseudonymized(), is(true)); From abe0dbd8a27d4c3a887b5e08ee8bdc17cbe94c70 Mon Sep 17 00:00:00 2001 From: sergiupacurariu <62688603+sergiupacurariu@users.noreply.github.com> Date: Tue, 23 Jan 2024 17:37:51 +0200 Subject: [PATCH 6/6] #12697 - Assign case(s) to a User and allow them to see the data of only the assigned case(s) in the system - additional logic - changes after review --- ...EnvironmentJurisdictionBooleanValidator.java | 13 ++++++++----- ...nmentSampleJurisdictionBooleanValidator.java | 6 +++--- .../services/BaseTravelEntryService.java | 17 ----------------- .../sormas/backend/user/UserFacadeEjb.java | 2 -- .../symeda/sormas/backend/user/UserService.java | 3 +-- 5 files changed, 12 insertions(+), 29 deletions(-) diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java index 62072116bbf..7ac7dea3d40 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java @@ -32,17 +32,20 @@ public Boolean isRootInJurisdiction() { @Override public Boolean isRootInJurisdictionOrOwned() { - return isReportedAndResponsibleByCurrentUser() || inJurisdiction(); + return isReportedByCurrentUser() || isResponsibleByCurrentUser() || inJurisdiction(); } - private boolean isReportedAndResponsibleByCurrentUser() { - return userJurisdiction.getUuid().equals(environmentJurisdiction.getReportingUserUuid()) - || userJurisdiction.getUuid().equals(environmentJurisdiction.getResponsibleUserUuid()); + private boolean isReportedByCurrentUser() { + return userJurisdiction.getUuid().equals(environmentJurisdiction.getReportingUserUuid()); + } + + private boolean isResponsibleByCurrentUser() { + return userJurisdiction.getUuid().equals(environmentJurisdiction.getResponsibleUserUuid()); } @Override public Boolean isRootInJurisdictionForRestrictedAccess() { - return isReportedAndResponsibleByCurrentUser(); + return isReportedByCurrentUser() || isResponsibleByCurrentUser(); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionBooleanValidator.java index 403d4f39b9d..5711aef48bb 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionBooleanValidator.java @@ -51,16 +51,16 @@ public Boolean isRootInJurisdiction() { @Override public Boolean isRootInJurisdictionOrOwned() { - return getReportedByCurrentUser() || inJurisdiction(); + return isReportedByCurrentUser() || inJurisdiction(); } - private boolean getReportedByCurrentUser() { + private boolean isReportedByCurrentUser() { return userJurisdiction.getUuid().equals(environmentSampleJurisdiction.getReportingUserUuid()); } @Override public Boolean isRootInJurisdictionForRestrictedAccess() { - return getReportedByCurrentUser() || userJurisdiction.getUuid().equals(environmentSampleJurisdiction.getEnvironmentResponsibleUser()); + return isReportedByCurrentUser() || userJurisdiction.getUuid().equals(environmentSampleJurisdiction.getEnvironmentResponsibleUser()); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/BaseTravelEntryService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/BaseTravelEntryService.java index 4db129708d9..58c11cc85fb 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/BaseTravelEntryService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/BaseTravelEntryService.java @@ -72,23 +72,6 @@ public Predicate createUserFilter(TravelEntryQueryContext qc, boolean checkJuris filter = CriteriaBuilderHelper .and(cb, filter, CriteriaBuilderHelper.limitedDiseasePredicate(cb, currentUser, qc.getRoot().get(TravelEntry.DISEASE))); } - if (isRestrictedToAssignedEntities()) { - final PersonQueryContext personQueryContext = new PersonQueryContext(cb, qc.getQuery(), qc.getJoins().getPersonJoins()); - - final PersonCriteria personCaseCriteria = new PersonCriteria(); - personCaseCriteria.setPersonAssociation(PersonAssociation.CASE); - final Predicate personCaseUserFilter = personService.createUserFilter(personQueryContext, personCaseCriteria); - - final PersonCriteria personContactCriteria = new PersonCriteria(); - personContactCriteria.setPersonAssociation(PersonAssociation.CONTACT); - final Predicate personContactUserFilter = personService.createUserFilter(personQueryContext, personContactCriteria); - - final PersonCriteria personEventParticipantCriteria = new PersonCriteria(); - personEventParticipantCriteria.setPersonAssociation(PersonAssociation.EVENT_PARTICIPANT); - final Predicate personEventParticipantUserFilter = personService.createUserFilter(personQueryContext, personEventParticipantCriteria); - - filter = CriteriaBuilderHelper.and(cb, filter, cb.or(personCaseUserFilter, personContactUserFilter, personEventParticipantUserFilter)); - } return filter; } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserFacadeEjb.java index 7f5ba09b4bc..fb8df2ca8d9 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserFacadeEjb.java @@ -956,8 +956,6 @@ private List getUsersFromCasesByDistricts(List districtsUuidsAmong Arrays.asList(UserRight.CASE_RESPONSIBLE)) .stream() .map(userReference -> userService.getByUuid(userReference.getUuid())) - .collect(Collectors.toList()) - .stream() .filter(user -> !UserHelper.isRestrictedToAssignEntities(user)) .collect(Collectors.toList()); return possibleUserForReplacement; diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserService.java index 237211d19ea..fd58a140468 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserService.java @@ -507,8 +507,7 @@ public List getUserReferencesByJurisdictions( cq.distinct(true); cq.orderBy(cb.asc(root.get(AbstractDomainObject.ID))); - final List resultList = em.createQuery(cq).setHint(ModelConstants.READ_ONLY, true).getResultList(); - return resultList; + return em.createQuery(cq).setHint(ModelConstants.READ_ONLY, true).getResultList(); } public List getUserReferencesByIds(Collection userIds) {