BI-2258 - Endpoint filtering for Experimental Collaborator role#385
BI-2258 - Endpoint filtering for Experimental Collaborator role#385
Conversation
| Optional<ProgramUser> experimentalCollaborator = programUserService.getIfExperimentalCollaborator(programId, securityService.getUser().getId()); | ||
| // If the program user is an experimental collaborator, filter results. | ||
| if (experimentalCollaborator.isPresent()) { | ||
| Optional<Program> program = programService.getById(programId); | ||
| if (program.isEmpty()) { | ||
| return HttpResponse.notFound(); | ||
| } | ||
|
|
||
| List<UUID> experimentIds = experimentalCollaboratorService.getAuthorizedExperimentIds(experimentalCollaborator.get().getId()); | ||
| studies = studyService.getStudiesByExperimentIds(program.get(), experimentIds) | ||
| .stream() | ||
| .peek(this::setDbIds) | ||
| .collect(Collectors.toList()); | ||
| } else { | ||
| studies = studyService.getStudies(programId) | ||
| .stream() | ||
| .peek(this::setDbIds) | ||
| .collect(Collectors.toList()); | ||
| } |
There was a problem hiding this comment.
Optional methods could be used to refactor the fetching logic.
| Optional<ProgramUser> experimentalCollaborator = programUserService.getIfExperimentalCollaborator(programId, securityService.getUser().getId()); | |
| // If the program user is an experimental collaborator, filter results. | |
| if (experimentalCollaborator.isPresent()) { | |
| Optional<Program> program = programService.getById(programId); | |
| if (program.isEmpty()) { | |
| return HttpResponse.notFound(); | |
| } | |
| List<UUID> experimentIds = experimentalCollaboratorService.getAuthorizedExperimentIds(experimentalCollaborator.get().getId()); | |
| studies = studyService.getStudiesByExperimentIds(program.get(), experimentIds) | |
| .stream() | |
| .peek(this::setDbIds) | |
| .collect(Collectors.toList()); | |
| } else { | |
| studies = studyService.getStudies(programId) | |
| .stream() | |
| .peek(this::setDbIds) | |
| .collect(Collectors.toList()); | |
| } | |
| Optional<HttpResponse> httpResponse = programUserService.getIfExperimentalCollaborator(programId, securityService.getUser().getId()) | |
| .flatMap(experimentalCollaborator -> { //If the program user is an experimental collaborator, filter results. | |
| Optional<Program> program = programService.getById(programId); | |
| return program.map(p -> { | |
| List<UUID> experimentIds = experimentalCollaboratorService.getAuthorizedExperimentIds(experimentalCollaborator.getId()); | |
| List<Study> studies = studyService.getStudiesByExperimentIds(p, experimentIds) | |
| .stream() | |
| .peek(this::setDbIds) | |
| .collect(Collectors.toList()); | |
| return HttpResponse.ok(studies); | |
| }); | |
| }) | |
| .orElseGet(() -> { //Otherwise, fallback to fetching studies without considering collaborator status | |
| List<Study> studies = studyService.getStudies(programId) | |
| .stream() | |
| .peek(this::setDbIds) | |
| .collect(Collectors.toList()); | |
| return HttpResponse.ok(studies); | |
| }); | |
| return httpResponse.orElse(HttpResponse.notFound()); |
There was a problem hiding this comment.
I tried to test this and the BrAPITrialsController suggestions locally, they both resulted in build errors. Are there problems in my code as written that you would like me to address?
| Optional<ProgramUser> experimentalCollaborator = programUserService.getIfExperimentalCollaborator(programId, securityService.getUser().getId()); | ||
| // If the program user is an experimental collaborator, filter results. | ||
| if (experimentalCollaborator.isPresent()) { | ||
| Optional<Program> program = programService.getById(programId); | ||
| if (program.isEmpty()) { | ||
| return HttpResponse.notFound(); | ||
| } | ||
| List<UUID> experimentIds = experimentalCollaboratorService.getAuthorizedExperimentIds(experimentalCollaborator.get().getId()); | ||
| experiments = experimentService.getTrialsByExperimentIds(program.get(), experimentIds).stream().peek(this::setDbIds).collect(Collectors.toList()); | ||
| } else { | ||
| experiments = experimentService.getExperiments(programId).stream().peek(this::setDbIds).collect(Collectors.toList()); | ||
| } | ||
|
|
There was a problem hiding this comment.
| Optional<ProgramUser> experimentalCollaborator = programUserService.getIfExperimentalCollaborator(programId, securityService.getUser().getId()); | |
| // If the program user is an experimental collaborator, filter results. | |
| if (experimentalCollaborator.isPresent()) { | |
| Optional<Program> program = programService.getById(programId); | |
| if (program.isEmpty()) { | |
| return HttpResponse.notFound(); | |
| } | |
| List<UUID> experimentIds = experimentalCollaboratorService.getAuthorizedExperimentIds(experimentalCollaborator.get().getId()); | |
| experiments = experimentService.getTrialsByExperimentIds(program.get(), experimentIds).stream().peek(this::setDbIds).collect(Collectors.toList()); | |
| } else { | |
| experiments = experimentService.getExperiments(programId).stream().peek(this::setDbIds).collect(Collectors.toList()); | |
| } | |
| Optional<HttpResponse> httpResponse = programUserService.getIfExperimentalCollaborator(programId, securityService.getUser().getId()) | |
| .flatMap(experimentalCollaborator -> | |
| programService.getById(programId) | |
| .map(program -> | |
| experimentalCollaboratorService.getAuthorizedExperimentIds(experimentalCollaborator.getId()) | |
| .stream() | |
| .flatMap(experimentId -> experimentService.getTrialsByExperimentIds(program, List.of(experimentId)).stream()) | |
| .peek(this::setDbIds) | |
| .collect(Collectors.toList()))) | |
| .or(() -> | |
| Optional.of(experimentService.getExperiments(programId) | |
| .stream() | |
| .peek(this::setDbIds) | |
| .collect(Collectors.toList())) | |
| .filter(experiments -> !experiments.isEmpty()) | |
| .map(HttpResponse::ok) | |
| .orElse(HttpResponse.notFound()); | |
| return httpResponse.orElse(HttpResponse.notFound()); | |
There was a problem hiding this comment.
See my comment on the BrAPIStudiesController.java suggestion.
| public Optional<ProgramUser> getIfExperimentalCollaborator(UUID programId, UUID userId) throws DoesNotExistException { | ||
| Optional<ProgramUser> programUser = getProgramUserbyId(programId, userId); | ||
| if (programUser.isEmpty()) { | ||
| throw new DoesNotExistException("Program User does not exist"); | ||
| } | ||
| boolean isExperimentalCollaborator = programUser.get().getRoles().stream().anyMatch(x -> ProgramSecuredRole.getEnum(x.getDomain()).equals(ProgramSecuredRole.EXPERIMENTAL_COLLABORATOR)); | ||
| if (isExperimentalCollaborator) { | ||
| return programUser; | ||
| } | ||
| return Optional.empty(); | ||
| } |
There was a problem hiding this comment.
Could refactor here using Optional methods
| public Optional<ProgramUser> getIfExperimentalCollaborator(UUID programId, UUID userId) throws DoesNotExistException { | |
| Optional<ProgramUser> programUser = getProgramUserbyId(programId, userId); | |
| if (programUser.isEmpty()) { | |
| throw new DoesNotExistException("Program User does not exist"); | |
| } | |
| boolean isExperimentalCollaborator = programUser.get().getRoles().stream().anyMatch(x -> ProgramSecuredRole.getEnum(x.getDomain()).equals(ProgramSecuredRole.EXPERIMENTAL_COLLABORATOR)); | |
| if (isExperimentalCollaborator) { | |
| return programUser; | |
| } | |
| return Optional.empty(); | |
| } | |
| public Optional<ProgramUser> getIfExperimentalCollaborator(UUID programId, UUID userId) throws DoesNotExistException { | |
| return getProgramUserbyId(programId, userId) | |
| .filter(programUser -> programUser.getRoles().stream() | |
| .anyMatch(x -> ProgramSecuredRole.getEnum(x.getDomain()).equals(ProgramSecuredRole.EXPERIMENTAL_COLLABORATOR))) | |
| .or(() -> { | |
| throw new RuntimeException(new DoesNotExistException("Program User does not exist")); | |
| }); | |
| } |
There was a problem hiding this comment.
Thank you for the suggestion. I tested it locally and it caused tests to fail because returning Optional.empty() is an important case which conceptually indicates that the program user exists, but is not in the "Experimental Collaborator" role.
Description
Story: https://breedinginsight.atlassian.net/browse/BI-2258
BrAPIStudiesController::getStudiesBrAPITrialsController::getExperimentsBrAPIV2Controller::getCatchall. The idea here is that Experimental Collaborators are allowed to access this endpoint, but not every GET endpoint that was handled by the catchall method.Testing
See acceptance criteria on Jira.
The testing steps on for BI-2283, in PR #393 test this story as well.
Checklist: