diff --git a/src/main/java/org/breedinginsight/api/auth/AuthenticatedUser.java b/src/main/java/org/breedinginsight/api/auth/AuthenticatedUser.java index 389f7f4ac..b2fa128b7 100644 --- a/src/main/java/org/breedinginsight/api/auth/AuthenticatedUser.java +++ b/src/main/java/org/breedinginsight/api/auth/AuthenticatedUser.java @@ -21,6 +21,7 @@ import lombok.Getter; import lombok.Setter; import org.breedinginsight.model.ProgramUser; +import org.breedinginsight.services.exceptions.DoesNotExistException; import java.util.Collection; import java.util.List; @@ -38,4 +39,11 @@ public AuthenticatedUser(String username, Collection roles, UUID id, Lis this.id = id; this.programRoles = programRoles; } + + public ProgramUser extractProgramUser(UUID programId) throws DoesNotExistException { + return this.programRoles.stream() + .filter(pu -> programId.equals( pu.getProgramId() ) ) + .findFirst() + .orElseThrow( () -> new DoesNotExistException( String.format("No program user found for program %s", this.id) ) ); + } } diff --git a/src/main/java/org/breedinginsight/api/auth/ExperimentCollaboratorSecured.java b/src/main/java/org/breedinginsight/api/auth/ExperimentCollaboratorSecured.java new file mode 100644 index 000000000..f14dc5fce --- /dev/null +++ b/src/main/java/org/breedinginsight/api/auth/ExperimentCollaboratorSecured.java @@ -0,0 +1,29 @@ +/* + * See the NOTICE file distributed with this work for additional information + * regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.breedinginsight.api.auth; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ExperimentCollaboratorSecured { + //The only role is EXPERIMENTAL_COLLABORATOR +} diff --git a/src/main/java/org/breedinginsight/api/auth/ProgramSecuredRoleGroup.java b/src/main/java/org/breedinginsight/api/auth/ProgramSecuredRoleGroup.java index 37e657a32..61a329927 100644 --- a/src/main/java/org/breedinginsight/api/auth/ProgramSecuredRoleGroup.java +++ b/src/main/java/org/breedinginsight/api/auth/ProgramSecuredRoleGroup.java @@ -17,13 +17,10 @@ package org.breedinginsight.api.auth; -import org.apache.commons.collections4.ListUtils; - import java.util.List; public enum ProgramSecuredRoleGroup { - ALL_PROGRAM_ROLES(List.of(ProgramSecuredRole.READ_ONLY, ProgramSecuredRole.PROGRAM_ADMIN)), - ALL(ListUtils.union(ALL_PROGRAM_ROLES.getProgramRoles(), List.of(ProgramSecuredRole.SYSTEM_ADMIN))); + PROGRAM_SCOPED_ROLES(List.of(ProgramSecuredRole.SYSTEM_ADMIN, ProgramSecuredRole.READ_ONLY, ProgramSecuredRole.PROGRAM_ADMIN)); private List programRoles; diff --git a/src/main/java/org/breedinginsight/api/auth/rules/ExperimentCollaboratorSecuredAnnotationRule.java b/src/main/java/org/breedinginsight/api/auth/rules/ExperimentCollaboratorSecuredAnnotationRule.java new file mode 100644 index 000000000..31217eac6 --- /dev/null +++ b/src/main/java/org/breedinginsight/api/auth/rules/ExperimentCollaboratorSecuredAnnotationRule.java @@ -0,0 +1,156 @@ +/* + * See the NOTICE file distributed with this work for additional information + * regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.breedinginsight.api.auth.rules; + +import io.micronaut.http.HttpRequest; +import io.micronaut.http.HttpStatus; +import io.micronaut.http.exceptions.HttpStatusException; +import io.micronaut.http.server.exceptions.HttpServerException; +import io.micronaut.security.rules.SecuredAnnotationRule; +import io.micronaut.security.rules.SecurityRuleResult; +import io.micronaut.security.token.RolesFinder; +import io.micronaut.web.router.MethodBasedRouteMatch; +import io.micronaut.web.router.RouteMatch; +import org.brapi.client.v2.model.exceptions.ApiException; +import org.brapi.v2.model.core.BrAPITrial; +import org.breedinginsight.api.auth.*; +import org.breedinginsight.brapi.v2.dao.BrAPITrialDAO; +import org.breedinginsight.daos.ExperimentalCollaboratorDAO; +import org.breedinginsight.daos.ProgramDAO; +import org.breedinginsight.model.ProgramUser; +import org.breedinginsight.model.Role; +import org.breedinginsight.services.exceptions.DoesNotExistException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.*; + +@Singleton +public class ExperimentCollaboratorSecuredAnnotationRule extends SecuredAnnotationRule { + + // Executes before the ProgramSecuredAnnotationRule, and if the annotation exists, will return before the ProgramSecuredAnnotationRule can execute + public static final Integer ORDER = ProgramSecuredAnnotationRule.ORDER -2; + + public ExperimentCollaboratorSecuredAnnotationRule(RolesFinder rolesFinder) { + super(rolesFinder); + } + + @Inject + private SecurityService securityService; + @Inject + private ProgramDAO programDAO; + @Inject + private BrAPITrialDAO brAPITrialDAO; + @Inject + private ExperimentalCollaboratorDAO experimentalCollaboratorDAO; + + @Override + public SecurityRuleResult check(HttpRequest request, @Nullable RouteMatch routeMatch, @Nullable Map claims) { + // Does not approve request so that checks after it can check. Only rejects on fail. + + if (routeMatch instanceof MethodBasedRouteMatch) { + MethodBasedRouteMatch methodRoute = ((MethodBasedRouteMatch) routeMatch); + + if (methodRoute.hasAnnotation(ExperimentCollaboratorSecured.class)) { + String programId = (String) routeMatch.getVariableValues() + .get("programId"); + String experimentId = extractExperimentId(routeMatch); + if (programId == null) { + throw new HttpServerException("Endpoint does not have program id to check roles against"); + } + if (experimentId == null) { + throw new HttpServerException("Endpoint does not have experiment id to check roles against"); + } + + if (!programDAO.existsById(UUID.fromString(programId))) { + throw new HttpStatusException(HttpStatus.NOT_FOUND, "Program does not exist"); + } + Optional trial; + try { + trial = brAPITrialDAO.getTrialById(UUID.fromString(programId), UUID.fromString(experimentId)); + } catch (ApiException e) { + throw new RuntimeException(e); + } catch (DoesNotExistException e) { + throw new HttpStatusException(HttpStatus.NOT_FOUND, "Experiment does not exist"); + } + if( trial.isEmpty()) { + throw new HttpStatusException(HttpStatus.NOT_FOUND, "Experiment does not exist"); + } + + if (claims != null){ + AuthenticatedUser user = securityService.getUser(); + + return checkAuthorization(user, experimentId, programId); + } + + // Rejects if no claims + return SecurityRuleResult.REJECTED; + } + } + + return SecurityRuleResult.UNKNOWN; + } + + private static String extractExperimentId(@NotNull RouteMatch routeMatch) { + //The endpoints can use either the "experimentId" or "trialId" parameter to pass the experiment ID + String experimentId = (String) routeMatch.getVariableValues() + .get("experimentId"); + if( experimentId==null) { + experimentId = (String) routeMatch.getVariableValues() + .get("trialId"); + } + return experimentId; + } + + private SecurityRuleResult checkAuthorization(AuthenticatedUser authenticatedUser, String experimentId, String programId) { + ProgramUser programUserRole; + try { + programUserRole = authenticatedUser.extractProgramUser(UUID.fromString(programId)); + } catch (DoesNotExistException e) { + return SecurityRuleResult.UNKNOWN; + } + if(this.isExperimentCoordinator(programUserRole)){ + List collaborativeExperimentIds = experimentalCollaboratorDAO.getExperimentIds(programUserRole.getId(), true); + if(collaborativeExperimentIds.contains( UUID.fromString(experimentId)) ){ + return SecurityRuleResult.ALLOWED; + } + } + else { + //Allow the next Secured Annotation to be run + return SecurityRuleResult.UNKNOWN; + } + return SecurityRuleResult.REJECTED; + } + + private boolean isExperimentCoordinator(ProgramUser programUser){ + List roles = programUser.getRoles(); + if( roles.size()!=1 ){ return false; } + String primaryRole = roles.get(0).getDomain(); + return (primaryRole != null && + primaryRole.equals( ProgramSecuredRole.EXPERIMENTAL_COLLABORATOR.toString() ) + ); + } + + @Override + public int getOrder() { + return ORDER; + } + +} \ No newline at end of file diff --git a/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java b/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java index e92e11fb2..f246e9bb8 100644 --- a/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java +++ b/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java @@ -85,7 +85,7 @@ public HttpResponse createProgramBreedingMethod(@PathVariable UUID programId, @Get("programs/{programId}/breeding-methods{?inUse}") @Produces(MediaType.APPLICATION_JSON) @AddMetadata - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>> getProgramBreedingMethods(@PathVariable UUID programId, @QueryValue(defaultValue = "false") Boolean inUse) { log.debug(String.format("fetching breeding methods for program: %s", programId)); diff --git a/src/main/java/org/breedinginsight/api/v1/controller/ExperimentController.java b/src/main/java/org/breedinginsight/api/v1/controller/ExperimentController.java index 77214c9cf..55b63e24e 100644 --- a/src/main/java/org/breedinginsight/api/v1/controller/ExperimentController.java +++ b/src/main/java/org/breedinginsight/api/v1/controller/ExperimentController.java @@ -10,8 +10,7 @@ import io.micronaut.security.rules.SecurityRule; import lombok.extern.slf4j.Slf4j; import org.brapi.client.v2.model.exceptions.ApiException; -import org.breedinginsight.api.auth.ProgramSecured; -import org.breedinginsight.api.auth.ProgramSecuredRoleGroup; +import org.breedinginsight.api.auth.*; import org.breedinginsight.api.model.v1.request.SubEntityDatasetRequest; import org.breedinginsight.api.model.v1.response.Response; import org.breedinginsight.brapi.v2.model.request.query.ExperimentExportQuery; @@ -22,7 +21,6 @@ import org.breedinginsight.model.Program; import org.breedinginsight.services.ProgramService; import org.breedinginsight.services.exceptions.DoesNotExistException; -import org.breedinginsight.services.exceptions.UnprocessableEntityException; import org.breedinginsight.utilities.response.mappers.ExperimentQueryMapper; import javax.inject.Inject; @@ -47,7 +45,8 @@ public ExperimentController(BrAPITrialService experimentService, ExperimentQuery } @Get("/${micronaut.bi.api.version}/programs/{programId}/experiments/{experimentId}/export{?queryParams*}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ExperimentCollaboratorSecured + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) @Produces(value={"text/csv", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/octet-stream"}) public HttpResponse datasetExport( @PathVariable("programId") UUID programId, @PathVariable("experimentId") UUID experimentId, @@ -75,7 +74,8 @@ public HttpResponse datasetExport( } @Get("/${micronaut.bi.api.version}/programs/{programId}/experiments/{experimentId}/dataset/{datasetId}{?stats}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ExperimentCollaboratorSecured + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) @Produces(MediaType.APPLICATION_JSON) public HttpResponse> getDatasetData( @PathVariable("programId") UUID programId, @@ -102,7 +102,7 @@ public HttpResponse> getDatasetData( * @return An HttpResponse with a Response object containing the newly created Dataset. */ @Post("/${micronaut.bi.api.version}/programs/{programId}/experiments/{experimentId}/dataset") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) @Produces(MediaType.APPLICATION_JSON) public HttpResponse> createSubEntityDataset( @PathVariable("programId") UUID programId, @@ -132,7 +132,8 @@ public HttpResponse> createSubEntityDataset( * @throws ApiException if an error occurs while retrieving the datasets. */ @Get("/${micronaut.bi.api.version}/programs/{programId}/experiments/{experimentId}/datasets") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ExperimentCollaboratorSecured + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) @Produces(MediaType.APPLICATION_JSON) public HttpResponse>> getDatasets( @PathVariable("programId") UUID programId, diff --git a/src/main/java/org/breedinginsight/api/v1/controller/JobController.java b/src/main/java/org/breedinginsight/api/v1/controller/JobController.java index 621493eb0..67b2e241d 100644 --- a/src/main/java/org/breedinginsight/api/v1/controller/JobController.java +++ b/src/main/java/org/breedinginsight/api/v1/controller/JobController.java @@ -59,7 +59,7 @@ public JobController(SecurityService securityService, JobService jobService) { @Get("programs/{programId}/jobs") @Produces(MediaType.APPLICATION_JSON) @AddMetadata - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>> getProgramJobs(@PathVariable UUID programId) { log.debug(String.format("fetching jobs for program: %s", programId)); try { diff --git a/src/main/java/org/breedinginsight/api/v1/controller/ProgramController.java b/src/main/java/org/breedinginsight/api/v1/controller/ProgramController.java index 5464fc315..79dd3d796 100644 --- a/src/main/java/org/breedinginsight/api/v1/controller/ProgramController.java +++ b/src/main/java/org/breedinginsight/api/v1/controller/ProgramController.java @@ -107,7 +107,8 @@ public HttpResponse>> postProgramsSearch( @Get("/programs/{programId}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roles = {ProgramSecuredRole.SYSTEM_ADMIN, ProgramSecuredRole.READ_ONLY, ProgramSecuredRole.PROGRAM_ADMIN + ,ProgramSecuredRole.EXPERIMENTAL_COLLABORATOR }) @AddMetadata public HttpResponse> getProgram(@PathVariable UUID programId) { @@ -178,7 +179,7 @@ public HttpResponse archiveProgram(@PathVariable UUID programId) { @Get("/programs/{programId}/users{?queryParams*}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>> getProgramUsers( @PathVariable UUID programId, @QueryValue @QueryValid(using = ProgramUserQueryMapper.class) @Valid QueryParams queryParams) { @@ -194,7 +195,7 @@ public HttpResponse>> getProgramUsers( @Post("/programs/{programId}/users/search{?queryParams*}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>> searchProgramUsers( @PathVariable UUID programId, @QueryValue @QueryValid(using = ProgramUserQueryMapper.class) @Valid QueryParams queryParams, @@ -211,7 +212,7 @@ public HttpResponse>> searchProgramUsers( @Get("/programs/{programId}/users/{userId}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) @AddMetadata public HttpResponse> getProgramUser(@PathVariable UUID programId, @PathVariable UUID userId) { @@ -292,7 +293,7 @@ public HttpResponse archiveProgramUser(@PathVariable UUID programId, @PathVariab @Get("/programs/{programId}/locations{?queryParams*}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>> getProgramLocations( @PathVariable UUID programId, @QueryValue @QueryValid(using= ProgramLocationQueryMapper.class) @Valid QueryParams queryParams) { @@ -311,7 +312,7 @@ public HttpResponse>> getProgramLocations @Post("/programs/{programId}/locations/search{?queryParams*}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>> postProgramLocationsSearch( @PathVariable UUID programId, @QueryValue @QueryValid(using= ProgramLocationQueryMapper.class) @Valid QueryParams queryParams, @@ -335,7 +336,7 @@ public HttpResponse>> postProgramLocation @Get("/programs/{programId}/locations/{locationId}") @Produces(MediaType.APPLICATION_JSON) @AddMetadata - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse> getProgramLocations(@PathVariable UUID programId, @PathVariable UUID locationId) { @@ -423,7 +424,7 @@ public HttpResponse archiveProgramLocation(@PathVariable UUID programId, @Get("/programs/{programId}/observation-levels") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>> getProgramObservationLevels(@PathVariable UUID programId) throws DoesNotExistException { List programObservationLevels = programObservationLevelService.getByProgramId(programId); diff --git a/src/main/java/org/breedinginsight/api/v1/controller/TraitController.java b/src/main/java/org/breedinginsight/api/v1/controller/TraitController.java index 775bcc859..8e8f1769b 100644 --- a/src/main/java/org/breedinginsight/api/v1/controller/TraitController.java +++ b/src/main/java/org/breedinginsight/api/v1/controller/TraitController.java @@ -77,7 +77,7 @@ public TraitController(TraitService traitService, SecurityService securityServic @Get("/programs/{programId}/traits{?traitsQuery*}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>> getTraits( @PathVariable UUID programId, @QueryValue @QueryValid(using = TraitQueryMapper.class) @Valid TraitsQuery traitsQuery) { @@ -93,7 +93,7 @@ public HttpResponse>> getTraits( @Get("/programs/{programId}/traits/export{?fileExtension,isActive}") @Produces(value = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse getTraitsExport( @PathVariable("programId") UUID programId, @QueryValue(defaultValue = "XLSX") String fileExtension, @QueryValue(defaultValue = "true") Boolean isActive) { String downloadErrorMessage = "An error occurred while generating the download file. Contact the development team at bidevteam@cornell.edu."; @@ -113,7 +113,7 @@ public HttpResponse getTraitsExport( @Post("/programs/{programId}/traits/search{?queryParams*}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>> postTraitsSearch( @PathVariable UUID programId, @QueryValue @QueryValid(using = TraitQueryMapper.class) @Valid QueryParams queryParams, @@ -130,7 +130,7 @@ public HttpResponse>> postTraitsSearch( @Get("/programs/{programId}/traits/{traitId}") @Produces(MediaType.APPLICATION_JSON) @AddMetadata - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse> getTrait(@PathVariable UUID programId, @PathVariable UUID traitId) { try { @@ -151,7 +151,7 @@ public HttpResponse> getTrait(@PathVariable UUID programId, @Pat @Get("/programs/{programId}/traits/{traitId}/editable") @Produces(MediaType.APPLICATION_JSON) @AddMetadata - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse> getTraitEditable(@PathVariable UUID programId, @PathVariable UUID traitId) { Editable editable = traitService.getEditable(programId, traitId); @@ -235,7 +235,7 @@ public HttpResponse> archiveTrait(@PathVariable UUID programId, @Get("/programs/{programId}/traits/tags") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>> getAllTraitTags( @PathVariable UUID programId) { diff --git a/src/main/java/org/breedinginsight/api/v1/controller/geno/SampleSubmissionController.java b/src/main/java/org/breedinginsight/api/v1/controller/geno/SampleSubmissionController.java index 43923c71a..e99bb5e70 100644 --- a/src/main/java/org/breedinginsight/api/v1/controller/geno/SampleSubmissionController.java +++ b/src/main/java/org/breedinginsight/api/v1/controller/geno/SampleSubmissionController.java @@ -74,7 +74,7 @@ public SampleSubmissionController(@Property(name = "brapi.vendor-submission-enab @Get("programs/{programId}/submissions") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = ProgramSecuredRoleGroup.ALL) + @ProgramSecured(roleGroups = ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES) public HttpResponse>> getProgramSampleSubmissions(@PathVariable UUID programId) { Optional program = programService.getById(programId); if(program.isEmpty()) { @@ -91,7 +91,7 @@ public HttpResponse>> getProgramSampleSu @Get("programs/{programId}/submissions/{submissionId}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = ProgramSecuredRoleGroup.ALL) + @ProgramSecured(roleGroups = ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES) public HttpResponse> getSubmissionById(@PathVariable UUID programId, @PathVariable UUID submissionId, @QueryValue(value = "details", defaultValue = "false") @Nullable Boolean fetchDetails) { Optional program = programService.getById(programId); if(program.isEmpty()) { @@ -157,7 +157,7 @@ public HttpResponse> updateSubmissionStatus(@PathVari @Get("/programs/{programId}/submissions/{submissionId}/dart") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) @Produces(value={"text/csv", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/octet-stream"}) public HttpResponse generateDArTFile(@PathVariable UUID programId, @PathVariable UUID submissionId) { try { @@ -184,7 +184,7 @@ public HttpResponse generateDArTFile(@PathVariable UUID programId, } @Get("/programs/{programId}/submissions/{submissionId}/lookup") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) @Produces(value={"text/csv", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/octet-stream"}) public HttpResponse generateLookupFile(@PathVariable UUID programId, @PathVariable UUID submissionId) { try { diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIGermplasmController.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIGermplasmController.java index edc89b5f0..be22abaf3 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIGermplasmController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIGermplasmController.java @@ -76,7 +76,7 @@ public BrAPIGermplasmController(BrAPIGermplasmService germplasmService, Germplas // TODO: expand to fully support BrAPI request body. @Post("/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/search/germplasm{?queryParams*}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>>> searchGermplasm( @PathVariable("programId") UUID programId, @QueryValue @QueryValid(using = GermplasmQueryMapper.class) @Valid BrapiQuery queryParams, @@ -95,7 +95,7 @@ public HttpResponse>>> searchGermplas @Get("/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/germplasm{?queryParams*}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>>> getGermplasm( @PathVariable("programId") UUID programId, @QueryValue @QueryValid(using = GermplasmQueryMapper.class) @Valid GermplasmQuery queryParams) { @@ -122,7 +122,7 @@ public HttpResponse>>> getGermplasm( @Get("/programs/{programId}/germplasm/lists/{listDbId}/records{?queryParams*}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>>> getGermplasmListRecords( @PathVariable("programId") UUID programId, @PathVariable("listDbId") String listDbId, @@ -139,7 +139,7 @@ public HttpResponse>>> getGermplasmLi @Get("/programs/{programId}/germplasm/lists/{listDbId}/export{?fileExtension}") @Produces(value = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse germplasmListExport( @PathVariable("programId") UUID programId, @PathVariable("listDbId") String listDbId, @QueryValue(defaultValue = "XLSX") String fileExtension) { String downloadErrorMessage = "An error occurred while generating the download file. Contact the development team at bidevteam@cornell.edu."; @@ -159,7 +159,7 @@ public HttpResponse germplasmListExport( @Get("/programs/{programId}/germplasm/export{?fileExtension}") @Produces(value = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse germplasmExport( @PathVariable("programId") UUID programId, @QueryValue(defaultValue = "XLSX") String fileExtension) { String downloadErrorMessage = "An error occurred while generating the download file. Contact the development team at bidevteam@cornell.edu."; @@ -178,7 +178,7 @@ public HttpResponse germplasmExport( @Get("/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/germplasm/{germplasmId}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse> getSingleGermplasm( @PathVariable("programId") UUID programId, @PathVariable("germplasmId") String germplasmId) { @@ -197,7 +197,7 @@ public HttpResponse> getSingleGermplasm( @Get("/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/germplasm/{germplasmId}/pedigree{?notation}{?includeSiblings}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse getGermplasmPedigreeInfo( @PathVariable("programId") UUID programId, @PathVariable("germplasmId") String germplasmId, @@ -282,7 +282,7 @@ public HttpResponse getGermplasmPedigreeInfo( @Get("/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/germplasm/{germplasmId}/progeny") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse getGermplasmProgenyInfo( @PathVariable("programId") UUID programId, @PathVariable("germplasmId") String germplasmId) { @@ -346,7 +346,7 @@ public HttpResponse getGermplasmProgenyInfo( @Get("/programs/{programId}/germplasm/{germplasmId}/genotype") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse> getGermplasmGenotype(@PathVariable("programId") UUID programId, @PathVariable("germplasmId") String germplasmId) { diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIImagesController.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIImagesController.java index f760af9f0..cf59df624 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIImagesController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIImagesController.java @@ -41,7 +41,7 @@ public class BrAPIImagesController { - PUT imagesImageDbIdPut */ @Get("/images") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse imagesGet(@PathVariable("programId") UUID programId, @QueryValue("imageDbId") String imageDbId, @QueryValue("imageName") String imageName, @@ -59,7 +59,7 @@ public HttpResponse imagesGet(@PathVariable("programId") UUID programId, } @Get("/images/{imageDbId}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse imagesImageDbIdGet(@PathVariable("programId") UUID programId, @PathVariable("imageDbId") String imageDbId) { return HttpResponse.notFound(); @@ -67,7 +67,7 @@ public HttpResponse imagesImageDbIdGet(@PathVariable("programId") UUID programId @Put("/images/{imageDbId}/imagecontent") @Consumes({"image/_*"}) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse imagesImageDbIdImagecontentPut(@PathVariable("programId") UUID programId, @PathVariable("imageDbId") String imageDbId, @Body Object body) { @@ -75,7 +75,7 @@ public HttpResponse imagesImageDbIdImagecontentPut(@PathVariable("programId") UU } @Put("/images/{imageDbId}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse imagesImageDbIdPut(@PathVariable("programId") UUID programId, @PathVariable("imageDbId") String imageDbId, @Body BrAPIImage body) { @@ -83,7 +83,7 @@ public HttpResponse imagesImageDbIdPut(@PathVariable("programId") UUID programId } @Post("/images") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse imagesPost(@PathVariable("programId") UUID programId, @Body List body) { return HttpResponse.notFound(); } diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIListController.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIListController.java index 115448d58..3dd6fd1f4 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIListController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIListController.java @@ -67,7 +67,7 @@ public BrAPIListController(ProgramService programService, BrAPIListService listS //@Get(BrapiVersion.BRAPI_V2 + "/lists") @Get("/${micronaut.bi.api.version}/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/lists{?queryParams*}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>> getLists( @PathVariable("programId") UUID programId, @QueryValue @QueryValid(using = ListQueryMapper.class) @Valid ListQuery queryParams diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationLevelsController.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationLevelsController.java index 9c54bed9a..ed2ef1884 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationLevelsController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationLevelsController.java @@ -77,7 +77,7 @@ public BrAPIObservationLevelsController(BrAPIEndpointProvider brAPIEndpointProvi } @Get("/observationlevels") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationlevelsGet(@PathVariable("programId") UUID programId, @Nullable @QueryValue("trialDbId") String experimentId, @Nullable @QueryValue("studyDbId") String environmentId, diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationUnitController.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationUnitController.java index c649626b1..ca2b470f8 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationUnitController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationUnitController.java @@ -67,7 +67,7 @@ public BrAPIObservationUnitController(@Property(name = "brapi.server.reference-s } @Get("/observationunits") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationunitsGet(@PathVariable("programId") UUID programId, @Nullable @QueryValue("observationUnitDbId") String observationUnitDbId, @Nullable @QueryValue("observationUnitName") String observationUnitName, @@ -147,7 +147,7 @@ public HttpResponse observationunitsGet(@PathV } @Get("/observationunits/{observationUnitDbId}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationunitsObservationUnitDbIdGet(@PathVariable("programId") UUID programId, @PathVariable("observationUnitDbId") String observationUnitDbId) { log.debug("observationunitsObservationUnitDbIdGet: fetching ou by externalReferenceId: " + observationUnitDbId); Optional program = programService.getById(programId); @@ -175,21 +175,21 @@ public HttpResponse observationunitsObservat } @Put("/observationunits/{observationUnitDbId}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationunitsObservationUnitDbIdPut(@PathVariable("programId") UUID programId, @PathVariable("observationUnitDbId") String observationUnitDbId, @Body BrAPIObservationUnit body) { //DO NOT IMPLEMENT - Users aren't yet able to update observation units return HttpResponse.notFound(); } @Post("/observationunits") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationunitsPost(@PathVariable("programId") UUID programId, @Body List body) { //DO NOT IMPLEMENT - Users are only able to create observation units via the DeltaBreed UI return HttpResponse.notFound(); } @Put("/observationunits") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationunitsPut(@PathVariable("programId") UUID programId, @Body Map body) { //DO NOT IMPLEMENT - Users aren't yet able to update observation units return HttpResponse.notFound(); @@ -197,7 +197,7 @@ public HttpResponse observationunitsPut(@PathVariable("programId") UUID progr @Get("/observationunits/table") @Produces({"application/json", "text/csv", "text/tsv"}) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationunitsTableGet(@PathVariable("programId") UUID programId, @Nullable @Header("Accept") String accept, @Nullable @QueryValue("observationUnitDbId") String observationUnitDbId, diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationVariableController.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationVariableController.java index 45d6983f3..9727ad1be 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationVariableController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationVariableController.java @@ -75,7 +75,7 @@ public BrAPIObservationVariableController(OntologyService ontologyService, } @Get("/variables") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse variablesGet(@PathVariable("programId") UUID programId, @Nullable @QueryValue("observationVariableDbId") String observationVariableDbId, @Nullable @QueryValue("observationVariableName") String observationVariableName, @@ -146,7 +146,7 @@ public HttpResponse variablesGet(@PathVari } @Get("/variables/{observationVariableDbId}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse variablesObservationVariableDbIdGet(@PathVariable("programId") UUID programId, @PathVariable("observationVariableDbId") String observationVariableDbId) { log.debug("fetching variable: " + observationVariableDbId); @@ -175,7 +175,7 @@ public HttpResponse variablesObservation } @Put("/variables/{observationVariableDbId}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse variablesObservationVariableDbIdPut(@PathVariable("programId") UUID programId, @PathVariable("observationVariableDbId") String observationVariableDbId, @Body BrAPIObservationVariable body) { @@ -184,7 +184,7 @@ public HttpResponse variablesObservationVariableDbIdPut(@PathVariable("progra } @Post("/variables") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse variablesPost(@PathVariable("programId") UUID programId, @Body List body) { //DO NOT IMPLEMENT - Users are only able to create new traits via the DeltaBreed UI return HttpResponse.notFound(); diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationsController.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationsController.java index 5a6c51148..5e70846ac 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationsController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationsController.java @@ -40,7 +40,7 @@ public class BrAPIObservationsController { @Get("/observations") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationsGet(@PathVariable("programId") UUID programId, @Nullable @QueryValue("observationDbId") String observationDbId, @Nullable @QueryValue("observationUnitDbId") String observationUnitDbId, @@ -71,14 +71,14 @@ public HttpResponse observationsGet(@PathVariable("programId") UUID programId, } @Get("/observations/{observationDbId}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationsObservationDbIdGet(@PathVariable("programId") UUID programId, @PathVariable("observationDbId") String observationDbId) { return HttpResponse.notFound(); } @Put("/observations/{observationDbId}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationsObservationDbIdPut(@PathVariable("programId") UUID programId, @PathVariable("observationDbId") String observationDbId, @Body BrAPIObservation body) { @@ -90,7 +90,7 @@ public HttpResponse observationsObservationDbIdPut(@PathVariable("programId") UU } @Post("/observations") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationsPost(@PathVariable("programId") UUID programId, @Body List body) { /* DO NOT IMPLEMENT - users must create observations via file upload @@ -100,7 +100,7 @@ public HttpResponse observationsPost(@PathVariable("programId") UUID programId, } @Put("/observations") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationsPut(@PathVariable("programId") UUID programId, @Body Map body) { /* DO NOT IMPLEMENT - users must create observations via file upload @@ -111,7 +111,7 @@ public HttpResponse observationsPut(@PathVariable("programId") UUID programId, @ @Get("/observations/table") @Produces({"application/json", "text/csv", "text/tsv"}) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationsTableGet(@PathVariable("programId") UUID programId, @Nullable @Header("Accept") String accept, @Nullable @QueryValue("observationUnitDbId") String observationUnitDbId, diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIPedigreeController.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIPedigreeController.java index 51799b346..1e6d673fe 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIPedigreeController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIPedigreeController.java @@ -57,7 +57,7 @@ public BrAPIPedigreeController(BrAPIPedigreeDAO pedigreeDAO, } @Get("/pedigree") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse pedigreeGet(@PathVariable("programId") UUID programId, @Nullable @QueryValue("accessionNumber") String accessionNumber, @Nullable @QueryValue("collection") String collection, @@ -118,14 +118,14 @@ public HttpResponse pedigreeGet(@PathVariable("progra } @Post("/pedigree") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse pedigreePost(@PathVariable("programId") UUID programId, @Body List body) { //DO NOT IMPLEMENT - Users are only able to create pedigree via the DeltaBreed UI return HttpResponse.notFound(); } @Put("/pedigree") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse pedigreePut(@PathVariable("programId") UUID programId, @Body Map body) { //DO NOT IMPLEMENT - Users aren't yet able to update observation units return HttpResponse.notFound(); diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIProgramsController.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIProgramsController.java index a30dbfbed..cd1d30c42 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIProgramsController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIProgramsController.java @@ -126,7 +126,7 @@ public HttpResponse rootProgramsProgramDbIdPut(@PathVariable("programDbId") S //START - endpoints for within the context of a program @Get("/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/programs") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse programsGet(@PathVariable("programId") UUID programId, @QueryValue("abbreviation") Optional abbreviation, @QueryValue("programType") Optional programType, @@ -153,14 +153,14 @@ public HttpResponse programsGet(@PathVariable("program } @Post("/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/programs") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse programsPost(@PathVariable("programId") UUID programId, @Body List body) { //DO NOT IMPLEMENT - Users should only be able to create new programs via the DeltaBreed UI return HttpResponse.notFound(); } @Get("/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/programs/{programDbId}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse programsProgramDbIdGet(@PathVariable("programId") UUID programId, @PathVariable("programDbId") String programDbId) { Optional program = programService.getById(programId) .stream() @@ -172,7 +172,7 @@ public HttpResponse programsProgramDbIdGet(@PathVari } @Put("/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/programs/{programDbId}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse programsProgramDbIdPut(@PathVariable("programId") UUID programId, @PathVariable("programDbId") String programDbId, @Body BrAPIProgram body) { //DO NOT IMPLEMENT - Users should only be able to update programs via the DeltaBreed UI return HttpResponse.notFound(); diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIStudiesController.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIStudiesController.java index 0382ecdb0..39a4d33dd 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIStudiesController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIStudiesController.java @@ -31,6 +31,7 @@ import org.brapi.v2.model.core.BrAPIStudy; import org.brapi.v2.model.core.response.BrAPIStudySingleResponse; import org.breedinginsight.api.auth.ProgramSecured; +import org.breedinginsight.api.auth.ProgramSecuredRole; import org.breedinginsight.api.auth.ProgramSecuredRoleGroup; import org.breedinginsight.api.model.v1.request.query.SearchRequest; import org.breedinginsight.api.model.v1.response.DataResponse; @@ -74,7 +75,8 @@ public BrAPIStudiesController(BrAPIStudyService studyService, StudyQueryMapper s @Get("/studies{?queryParams*}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured( roles = {ProgramSecuredRole.SYSTEM_ADMIN, ProgramSecuredRole.READ_ONLY, ProgramSecuredRole.PROGRAM_ADMIN + ,ProgramSecuredRole.EXPERIMENTAL_COLLABORATOR} ) public HttpResponse>>> getStudies( @PathVariable("programId") UUID programId, @QueryValue @QueryValid(using = StudyQueryMapper.class) @Valid StudyQuery queryParams) { @@ -99,14 +101,14 @@ public HttpResponse>>> getStudies( } @Post("/studies") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse studiesPost(@PathVariable("programId") UUID programId, @Body List body) { //DO NOT IMPLEMENT - Users are only able to create new studies via the DeltaBreed UI return HttpResponse.notFound(); } @Get("/studies/{studyDbId}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse studiesStudyDbIdGet(@PathVariable("programId") UUID programId, @PathVariable("studyDbId") String environmentId) { Optional program = programService.getById(programId); if(program.isEmpty()) { @@ -130,7 +132,7 @@ public HttpResponse studiesStudyDbIdGet(@PathVariable( } @Put("/studies/{studyDbId}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse studiesStudyDbIdPut(@PathVariable("programId") UUID programId, @PathVariable("studyDbId") String studyDbId, @Body BrAPIStudy body) { //DO NOT IMPLEMENT - Users are only able to update studies via the DeltaBreed UI diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPITrialsController.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPITrialsController.java index 666115efa..cd6dca2c3 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPITrialsController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPITrialsController.java @@ -11,8 +11,7 @@ import org.brapi.client.v2.model.exceptions.ApiException; import org.brapi.v2.model.core.BrAPITrial; import org.brapi.v2.model.core.response.BrAPITrialSingleResponse; -import org.breedinginsight.api.auth.ProgramSecured; -import org.breedinginsight.api.auth.ProgramSecuredRoleGroup; +import org.breedinginsight.api.auth.*; import org.breedinginsight.api.model.v1.request.query.SearchRequest; import org.breedinginsight.api.model.v1.response.DataResponse; import org.breedinginsight.api.model.v1.response.Response; @@ -21,6 +20,8 @@ import org.breedinginsight.brapi.v2.model.request.query.ExperimentQuery; import org.breedinginsight.brapi.v2.services.BrAPITrialService; import org.breedinginsight.brapps.importer.services.ExternalReferenceSource; +import org.breedinginsight.model.ProgramUser; +import org.breedinginsight.model.Role; import org.breedinginsight.services.exceptions.DoesNotExistException; import org.breedinginsight.utilities.Utilities; import org.breedinginsight.utilities.response.ResponseUtils; @@ -50,7 +51,8 @@ public BrAPITrialsController(BrAPITrialService experimentService, ExperimentQuer @Get("/trials{?queryParams*}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roles = {ProgramSecuredRole.SYSTEM_ADMIN, ProgramSecuredRole.READ_ONLY, ProgramSecuredRole.PROGRAM_ADMIN + ,ProgramSecuredRole.EXPERIMENTAL_COLLABORATOR }) public HttpResponse>>> getExperiments( @PathVariable("programId") UUID programId, @QueryValue @QueryValid(using = ExperimentQueryMapper.class) @Valid ExperimentQuery queryParams) { @@ -71,7 +73,8 @@ public HttpResponse>>> getExperiments( @Get("/trials/{trialId}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ExperimentCollaboratorSecured + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse getExperimentById( @PathVariable("programId") UUID programId, @PathVariable("trialId") UUID trialId, @@ -92,7 +95,7 @@ public HttpResponse getExperimentById( } @Post("/trials") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse trialsPost(@PathVariable("programId") UUID programId, @Body List body) { //DO NOT IMPLEMENT - Users are only able to create new trials via the DeltaBreed UI return HttpResponse.notFound(); @@ -100,7 +103,7 @@ public HttpResponse trialsPost(@PathVariable("programId") UUID programId, @Bo @Put("/trials/{trialDbId}") - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse trialsTrialDbIdPut(@PathVariable("programId") UUID programId, @PathVariable("trialDbId") String trialDbId, @Body BrAPITrial body) { //DO NOT IMPLEMENT - Users are only able to update trials via the DeltaBreed UI return HttpResponse.notFound(); @@ -116,5 +119,4 @@ private void setDbIds(BrAPITrial trial) { //TODO update locationDbId } - } diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIV2Controller.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIV2Controller.java index b5249516e..6b8f767a6 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIV2Controller.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIV2Controller.java @@ -30,10 +30,7 @@ import org.brapi.v2.model.core.BrAPIServerInfo; import org.brapi.v2.model.core.BrAPIService; import org.brapi.v2.model.core.response.BrAPIServerInfoResponse; -import org.breedinginsight.api.auth.AuthenticatedUser; -import org.breedinginsight.api.auth.ProgramSecured; -import org.breedinginsight.api.auth.ProgramSecuredRoleGroup; -import org.breedinginsight.api.auth.SecurityService; +import org.breedinginsight.api.auth.*; import org.breedinginsight.brapi.v1.controller.BrapiVersion; import org.breedinginsight.model.ProgramBrAPIEndpoints; import org.breedinginsight.services.ProgramService; @@ -170,7 +167,7 @@ private void setBrAPIServerInfo(BrAPIServerInfo serverInfo) { @Get("/${micronaut.bi.api.version}/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/{+path}") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse getCatchall(@PathVariable("path") String path, @PathVariable("programId") UUID programId, HttpRequest request) { return executeRequest(path, programId, request, "GET"); } @@ -178,7 +175,7 @@ public HttpResponse getCatchall(@PathVariable("path") String path, @PathVaria @Post("/${micronaut.bi.api.version}/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/{+path}") @Consumes(MediaType.ALL) @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse postCatchall(@PathVariable("path") String path, @PathVariable("programId") UUID programId, HttpRequest request, @Header("Content-Type") String contentType) { return executeByteRequest(path, programId, request, contentType, "POST"); @@ -187,7 +184,7 @@ public HttpResponse postCatchall(@PathVariable("path") String path, @Pat @Put("/${micronaut.bi.api.version}/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/{+path}") @Consumes(MediaType.ALL) @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse putCatchall(@PathVariable("path") String path, @PathVariable("programId") UUID programId, HttpRequest request, @Header("Content-Type") String contentType) { return executeByteRequest(path, programId, request, contentType, "PUT"); diff --git a/src/main/java/org/breedinginsight/brapi/v2/CropController.java b/src/main/java/org/breedinginsight/brapi/v2/CropController.java index 8e4b5ace2..3319a1acd 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/CropController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/CropController.java @@ -58,7 +58,7 @@ public CropController(ProgramService programService) { */ @Get("/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/commoncropnames") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>>> getCommonCropNames( @PathVariable("programId") UUID programId) { diff --git a/src/main/java/org/breedinginsight/brapi/v2/ProgramController.java b/src/main/java/org/breedinginsight/brapi/v2/ProgramController.java index 9b8c6b948..b93192dfb 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/ProgramController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/ProgramController.java @@ -60,7 +60,7 @@ public ProgramController(ProgramService programService) { */ @Get("/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/programs") @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>>> getPrograms( @PathVariable("programId") UUID programId) { diff --git a/src/main/java/org/breedinginsight/brapi/v2/services/BrAPITrialService.java b/src/main/java/org/breedinginsight/brapi/v2/services/BrAPITrialService.java index 333ceae60..3bd983f96 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/services/BrAPITrialService.java +++ b/src/main/java/org/breedinginsight/brapi/v2/services/BrAPITrialService.java @@ -102,6 +102,7 @@ public List getExperiments(UUID programId) throws ApiException, Does return trialDAO.getTrials(programId); } + public BrAPITrial getTrialDataByUUID(UUID programId, UUID trialId, boolean stats) throws DoesNotExistException { try { BrAPITrial trial = trialDAO.getTrialById(programId,trialId).orElseThrow(() -> new DoesNotExistException("Trial does not exist")); diff --git a/src/main/java/org/breedinginsight/brapps/importer/controllers/ImportController.java b/src/main/java/org/breedinginsight/brapps/importer/controllers/ImportController.java index 9555c3856..d732da0c5 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/controllers/ImportController.java +++ b/src/main/java/org/breedinginsight/brapps/importer/controllers/ImportController.java @@ -25,10 +25,7 @@ import io.micronaut.security.annotation.Secured; import io.micronaut.security.rules.SecurityRule; import lombok.extern.slf4j.Slf4j; -import org.breedinginsight.api.auth.AuthenticatedUser; -import org.breedinginsight.api.auth.ProgramSecured; -import org.breedinginsight.api.auth.ProgramSecuredRole; -import org.breedinginsight.api.auth.SecurityService; +import org.breedinginsight.api.auth.*; import org.breedinginsight.api.model.v1.response.DataResponse; import org.breedinginsight.api.model.v1.response.Response; import org.breedinginsight.api.model.v1.response.metadata.Metadata; @@ -84,7 +81,7 @@ public HttpResponse>> getImportTypes @Get("/programs/{programId}/import/mappings{?draft}") @Produces(MediaType.APPLICATION_JSON) @AddMetadata - @ProgramSecured(roles = {ProgramSecuredRole.PROGRAM_ADMIN, ProgramSecuredRole.SYSTEM_ADMIN}) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse>> getMappings(@PathVariable UUID programId, @QueryValue(defaultValue = "false") Boolean draft) { diff --git a/src/main/java/org/breedinginsight/daos/ExperimentalCollaboratorDAO.java b/src/main/java/org/breedinginsight/daos/ExperimentalCollaboratorDAO.java index 0187c55b5..21e7dbaa7 100644 --- a/src/main/java/org/breedinginsight/daos/ExperimentalCollaboratorDAO.java +++ b/src/main/java/org/breedinginsight/daos/ExperimentalCollaboratorDAO.java @@ -25,6 +25,13 @@ import javax.inject.Inject; import javax.inject.Singleton; +import java.time.OffsetDateTime; +import java.util.List; +import java.util.UUID; + +import static org.breedinginsight.dao.db.Tables.EXPERIMENT_PROGRAM_USER_ROLE; +import static org.breedinginsight.dao.db.Tables.PROGRAM_USER_ROLE; + import java.time.OffsetDateTime; import java.util.UUID; @@ -60,4 +67,41 @@ public ExperimentProgramUserRoleEntity create(UUID experimentId, UUID programUse .returning(EXPERIMENT_PROGRAM_USER_ROLE.fields()) .fetchOneInto(ExperimentProgramUserRoleEntity.class); } + + public List fetchByProgramUserIdAndExperimentId(UUID programUserRoleId, UUID experimentId) { + // Only returns results for active program_user_role rows. + return dsl.select(EXPERIMENT_PROGRAM_USER_ROLE.fields()) + .from(EXPERIMENT_PROGRAM_USER_ROLE) + .innerJoin(PROGRAM_USER_ROLE).on(EXPERIMENT_PROGRAM_USER_ROLE.PROGRAM_USER_ROLE_ID.eq(PROGRAM_USER_ROLE.ID)) + .where(EXPERIMENT_PROGRAM_USER_ROLE.PROGRAM_USER_ROLE_ID.eq(programUserRoleId)) + .and(EXPERIMENT_PROGRAM_USER_ROLE.EXPERIMENT_ID.eq(experimentId)) + .and(PROGRAM_USER_ROLE.ACTIVE.eq(true)) + .fetchInto(ExperimentProgramUserRoleEntity.class); + } + + public List getExperimentIds(UUID programUserRoleId, boolean activeOnly) { + // If activeOnly, this will only return results if the program_user_role row is active. + if (activeOnly) + { + return getExperimentIdsIfActive(programUserRoleId); + } + return getExperimentIds(programUserRoleId); + } + + private List getExperimentIdsIfActive(UUID programUserRoleId) { + return dsl.select(EXPERIMENT_PROGRAM_USER_ROLE.EXPERIMENT_ID) + .from(EXPERIMENT_PROGRAM_USER_ROLE) + .join(PROGRAM_USER_ROLE).on(EXPERIMENT_PROGRAM_USER_ROLE.PROGRAM_USER_ROLE_ID.eq(PROGRAM_USER_ROLE.ID)) + .where(EXPERIMENT_PROGRAM_USER_ROLE.PROGRAM_USER_ROLE_ID.eq(programUserRoleId)) + .and(PROGRAM_USER_ROLE.ACTIVE.eq(true)) + .fetchInto(UUID.class); + } + + private List getExperimentIds(UUID programUserRoleId) { + return dsl.select(EXPERIMENT_PROGRAM_USER_ROLE.EXPERIMENT_ID) + .from(EXPERIMENT_PROGRAM_USER_ROLE) + .where(EXPERIMENT_PROGRAM_USER_ROLE.PROGRAM_USER_ROLE_ID.eq(programUserRoleId)) + .fetchInto(UUID.class); + } + } diff --git a/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java b/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java index 4d502b84e..6e0f7e71e 100644 --- a/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java +++ b/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java @@ -3,7 +3,6 @@ import org.breedinginsight.dao.db.tables.daos.BreedingMethodDao; import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; import org.breedinginsight.daos.BreedingMethodDAO; -import org.jetbrains.annotations.NotNull; import org.jooq.*; import javax.inject.Inject;