Skip to content

Commit

Permalink
task: Extract common validations to helper class [TECH-1677]
Browse files Browse the repository at this point in the history
  • Loading branch information
muilpp committed Dec 21, 2023
1 parent 8415ecd commit 9d95f86
Show file tree
Hide file tree
Showing 10 changed files with 490 additions and 799 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,38 @@
import static org.hisp.dhis.common.OrganisationUnitSelectionMode.CAPTURE;
import static org.hisp.dhis.security.Authorities.F_TRACKED_ENTITY_INSTANCE_SEARCH_IN_ALL_ORGUNITS;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.util.HashSet;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.hisp.dhis.common.OrganisationUnitSelectionMode;
import org.hisp.dhis.feedback.BadRequestException;
import org.hisp.dhis.feedback.ForbiddenException;
import org.hisp.dhis.organisationunit.OrganisationUnit;
import org.hisp.dhis.organisationunit.OrganisationUnitService;
import org.hisp.dhis.program.Program;
import org.hisp.dhis.program.ProgramService;
import org.hisp.dhis.security.acl.AclService;
import org.hisp.dhis.trackedentity.TrackedEntity;
import org.hisp.dhis.trackedentity.TrackedEntityService;
import org.hisp.dhis.trackedentity.TrackedEntityType;
import org.hisp.dhis.trackedentity.TrackedEntityTypeService;
import org.hisp.dhis.user.User;
import org.springframework.stereotype.Component;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Component
@RequiredArgsConstructor
public class OperationsParamsValidator {

private final ProgramService programService;

private final AclService aclService;

private final TrackedEntityService trackedEntityService;

private final TrackedEntityTypeService trackedEntityTypeService;

private final OrganisationUnitService organisationUnitService;

/**
* Validates the user is authorized and/or has the necessary configuration set up in case the org
* unit mode is ALL, ACCESSIBLE or CAPTURE. If the mode used is none of these three, no validation
Expand Down Expand Up @@ -94,4 +116,122 @@ private static void validateCaptureScope(User user) throws BadRequestException {
throw new BadRequestException("User needs to be assigned data capture org units");
}
}

/**
* Validates the specified program uid exists and is accessible by the supplied user
*
* @return the program if found and accessible
* @throws BadRequestException if the program uid does not exist
* @throws ForbiddenException if the user has no data read access to the program or its tracked
* entity type
*/
public Program validateProgram(String programUid, User user)
throws BadRequestException, ForbiddenException {
if (programUid == null) {
return null;
}

Program program = programService.getProgram(programUid);
if (program == null) {
throw new BadRequestException("Program is specified but does not exist: " + programUid);
}

if (!aclService.canDataRead(user, program)) {
throw new ForbiddenException("User has no access to program: " + program.getUid());
}

if (program.getTrackedEntityType() != null
&& !aclService.canDataRead(user, program.getTrackedEntityType())) {
throw new ForbiddenException(
"Current user is not authorized to read data from selected program's tracked entity type: "
+ program.getTrackedEntityType().getUid());
}

return program;
}

/**
* Validates the specified tracked entity uid exists and is accessible by the supplied user
*
* @return the tracked entity if found and accessible
* @throws BadRequestException if the tracked entity uid does not exist
* @throws ForbiddenException if the user has no data read access to type of the tracked entity
*/
public TrackedEntity validateTrackedEntity(String trackedEntityUid, User user)
throws BadRequestException, ForbiddenException {
if (trackedEntityUid == null) {
return null;
}

TrackedEntity trackedEntity = trackedEntityService.getTrackedEntity(trackedEntityUid);
if (trackedEntity == null) {
throw new BadRequestException(
"Tracked entity is specified but does not exist: " + trackedEntityUid);
}

if (trackedEntity.getTrackedEntityType() != null
&& !aclService.canDataRead(user, trackedEntity.getTrackedEntityType())) {
throw new ForbiddenException(
"Current user is not authorized to read data from type of selected tracked entity: "
+ trackedEntity.getTrackedEntityType().getUid());
}

return trackedEntity;
}

/**
* Validates the specified tracked entity type uid exists and is accessible by the supplied user
*
* @return the tracked entity type uid if found and accessible
* @throws BadRequestException if the tracked entity type uid does not exist
* @throws ForbiddenException if the user has no data read access to the tracked entity type
*/
public TrackedEntityType validateTrackedEntityType(String uid, User user)
throws BadRequestException, ForbiddenException {
if (uid == null) {
return null;
}

TrackedEntityType trackedEntityType = trackedEntityTypeService.getTrackedEntityType(uid);
if (trackedEntityType == null) {
throw new BadRequestException("Tracked entity type is specified but does not exist: " + uid);
}

if (!aclService.canDataRead(user, trackedEntityType)) {
throw new ForbiddenException(
"Current user is not authorized to read data from selected tracked entity type: "
+ trackedEntityType.getUid());
}

return trackedEntityType;
}

/**
* Validates the specified org unit uid exists and is part of the user scope
*
* @return the org unit if found and accessible
* @throws BadRequestException if the org unit uid does not exist
* @throws ForbiddenException if the org unit is not part of the user scope
*/
public Set<OrganisationUnit> validateOrgUnits(Set<String> orgUnitIds, User user)
throws BadRequestException, ForbiddenException {
Set<OrganisationUnit> orgUnits = new HashSet<>();
for (String orgUnitUid : orgUnitIds) {
OrganisationUnit orgUnit = organisationUnitService.getOrganisationUnit(orgUnitUid);
if (orgUnit == null) {
throw new BadRequestException("Organisation unit does not exist: " + orgUnitUid);
}

if (!user.isSuper()
&& !organisationUnitService.isInUserHierarchy(
orgUnit.getUid(), user.getTeiSearchOrganisationUnitsWithFallback())) {
throw new ForbiddenException(
"Organisation unit is not part of the search scope: " + orgUnit.getUid());
}

orgUnits.add(orgUnit);
}

return orgUnits;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ public Enrollment getEnrollment(String uid, EnrollmentParams params, boolean inc

@Override
public Enrollment getEnrollment(
@Nonnull Enrollment enrollment, EnrollmentParams params, boolean includeDeleted, User user)
throws ForbiddenException {
@Nonnull Enrollment enrollment, EnrollmentParams params, boolean includeDeleted, User user) {

Enrollment result = new Enrollment();
result.setId(enrollment.getId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,10 @@
import org.hisp.dhis.feedback.BadRequestException;
import org.hisp.dhis.feedback.ForbiddenException;
import org.hisp.dhis.organisationunit.OrganisationUnit;
import org.hisp.dhis.organisationunit.OrganisationUnitService;
import org.hisp.dhis.program.Program;
import org.hisp.dhis.program.ProgramService;
import org.hisp.dhis.security.acl.AclService;
import org.hisp.dhis.trackedentity.TrackedEntity;
import org.hisp.dhis.trackedentity.TrackedEntityService;
import org.hisp.dhis.trackedentity.TrackedEntityType;
import org.hisp.dhis.trackedentity.TrackedEntityTypeService;
import org.hisp.dhis.tracker.export.OperationsParamsValidator;
import org.hisp.dhis.user.CurrentUserService;
import org.hisp.dhis.user.User;
import org.springframework.stereotype.Component;
Expand All @@ -60,28 +56,21 @@
class EnrollmentOperationParamsMapper {
private final CurrentUserService currentUserService;

private final OrganisationUnitService organisationUnitService;

private final ProgramService programService;

private final TrackedEntityTypeService trackedEntityTypeService;

private final TrackedEntityService trackedEntityService;

private final AclService aclService;
private final OperationsParamsValidator paramsValidator;

@Transactional(readOnly = true)
public EnrollmentQueryParams map(EnrollmentOperationParams operationParams)
throws BadRequestException, ForbiddenException {
User user = currentUserService.getCurrentUser();

Program program = validateProgram(operationParams.getProgramUid(), user);
Program program = paramsValidator.validateProgram(operationParams.getProgramUid(), user);
TrackedEntityType trackedEntityType =
validateTrackedEntityType(operationParams.getTrackedEntityTypeUid(), user);
paramsValidator.validateTrackedEntityType(operationParams.getTrackedEntityTypeUid(), user);
TrackedEntity trackedEntity =
validateTrackedEntity(operationParams.getTrackedEntityUid(), user);
paramsValidator.validateTrackedEntity(operationParams.getTrackedEntityUid(), user);

Set<OrganisationUnit> orgUnits = validateOrgUnits(operationParams.getOrgUnitUids(), user);
Set<OrganisationUnit> orgUnits =
paramsValidator.validateOrgUnits(operationParams.getOrgUnitUids(), user);
validateOrgUnitMode(operationParams.getOrgUnitMode(), user, program);

EnrollmentQueryParams params = new EnrollmentQueryParams();
Expand Down Expand Up @@ -121,98 +110,4 @@ private void mergeOrgUnitModes(
queryParams.setOrganisationUnitMode(DESCENDANTS);
}
}

private Program validateProgram(String uid, User user)
throws BadRequestException, ForbiddenException {
if (uid == null) {
return null;
}

Program program = programService.getProgram(uid);
if (program == null) {
throw new BadRequestException("Program is specified but does not exist: " + uid);
}

if (!aclService.canDataRead(user, program)) {
throw new ForbiddenException(
"Current user is not authorized to read data from selected program: "
+ program.getUid());
}

if (program.getTrackedEntityType() != null
&& !aclService.canDataRead(user, program.getTrackedEntityType())) {
throw new ForbiddenException(
"Current user is not authorized to read data from selected program's tracked entity type: "
+ program.getTrackedEntityType().getUid());
}

return program;
}

private TrackedEntityType validateTrackedEntityType(String uid, User user)
throws BadRequestException, ForbiddenException {
if (uid == null) {
return null;
}

TrackedEntityType trackedEntityType = trackedEntityTypeService.getTrackedEntityType(uid);
if (trackedEntityType == null) {
throw new BadRequestException("Tracked entity type is specified but does not exist: " + uid);
}

if (!aclService.canDataRead(user, trackedEntityType)) {
throw new ForbiddenException(
"Current user is not authorized to read data from selected tracked entity type: "
+ trackedEntityType.getUid());
}

return trackedEntityType;
}

private TrackedEntity validateTrackedEntity(String uid, User user)
throws BadRequestException, ForbiddenException {
if (uid == null) {
return null;
}

TrackedEntity trackedEntity = trackedEntityService.getTrackedEntity(uid);
if (trackedEntity == null) {
throw new BadRequestException("Tracked entity is specified but does not exist: " + uid);
}

if (trackedEntity.getTrackedEntityType() != null
&& !aclService.canDataRead(user, trackedEntity.getTrackedEntityType())) {
throw new ForbiddenException(
"Current user is not authorized to read data from type of selected tracked entity: "
+ trackedEntity.getTrackedEntityType().getUid());
}

return trackedEntity;
}

private Set<OrganisationUnit> validateOrgUnits(Set<String> orgUnitUids, User user)
throws BadRequestException, ForbiddenException {

Set<OrganisationUnit> orgUnits = new HashSet<>();
if (orgUnitUids != null) {
for (String orgUnitUid : orgUnitUids) {
OrganisationUnit orgUnit = organisationUnitService.getOrganisationUnit(orgUnitUid);

if (orgUnit == null) {
throw new BadRequestException("Organisation unit does not exist: " + orgUnitUid);
}

if (user != null
&& !user.isSuper()
&& !organisationUnitService.isInUserHierarchy(
orgUnitUid, user.getTeiSearchOrganisationUnitsWithFallback())) {
throw new ForbiddenException(
"Organisation unit is not part of the search scope: " + orgUnitUid);
}
orgUnits.add(orgUnit);
}
}

return orgUnits;
}
}
Loading

0 comments on commit 9d95f86

Please sign in to comment.