diff --git a/pom.xml b/pom.xml index 5d8467960fafbf22986b920bae7a2542d0a43d7a..d92ff1f2dd22cd477f702ec2486f675c117c39c6 100644 --- a/pom.xml +++ b/pom.xml @@ -246,7 +246,14 @@ <artifactId>svenson</artifactId> <version>1.5.8</version> </dependency> - </dependencies> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.16</version> + <scope>provided</scope> + </dependency> + + </dependencies> <build> <finalName>portal-backend</finalName> diff --git a/src/main/java/eu/hbp/mip/controllers/PathologiesAPI.java b/src/main/java/eu/hbp/mip/controllers/PathologiesAPI.java index 175ad297761e25356f50b4b6686fcc01d9f5fa2d..5e9a9d34452f81ff5293bccaf3a5a5aca0624057 100644 --- a/src/main/java/eu/hbp/mip/controllers/PathologiesAPI.java +++ b/src/main/java/eu/hbp/mip/controllers/PathologiesAPI.java @@ -70,7 +70,6 @@ public class PathologiesAPI { } logger.LogUserAction("Successfully loaded all authorized pathologies"); - return ResponseEntity.ok().body(ClaimUtils.getAuthorizedPathologies( - activeUserService.getActiveUser().getUsername(), logger, authentication.getAuthorities(), allPathologies)); + return ResponseEntity.ok().body(ClaimUtils.getAuthorizedPathologies(logger, authentication, allPathologies)); } } diff --git a/src/main/java/eu/hbp/mip/models/DAOs/ExperimentDAO.java b/src/main/java/eu/hbp/mip/models/DAOs/ExperimentDAO.java index 30d5ee123121545aa7a77ce8d25f83169cbe9c4f..e369e5cf6eff7b2641a4c9815e269eada28b37d9 100644 --- a/src/main/java/eu/hbp/mip/models/DAOs/ExperimentDAO.java +++ b/src/main/java/eu/hbp/mip/models/DAOs/ExperimentDAO.java @@ -7,6 +7,8 @@ import eu.hbp.mip.models.DTOs.AlgorithmDTO; import eu.hbp.mip.models.DTOs.ExperimentDTO; import eu.hbp.mip.utils.JsonConverters; import io.swagger.annotations.ApiModel; +import lombok.Getter; +import lombok.Setter; import javax.persistence.*; import java.util.*; @@ -15,6 +17,8 @@ import java.util.*; * Created by habfast on 21/04/16. */ @Entity +@Getter +@Setter @Table(name = "`experiment`") @ApiModel @JsonInclude(JsonInclude.Include.NON_NULL) @@ -109,108 +113,4 @@ public class ExperimentDAO { experimentDTO.setViewed(this.viewed); return experimentDTO; } - - public String getAlgorithm() { - return algorithm; - } - - public void setAlgorithm(String algorithm) { - this.algorithm = algorithm; - } - - public String getAlgorithmId() { - return algorithmId; - } - - public void setAlgorithmId(String algorithmId) { - this.algorithmId = algorithmId; - } - - public String getWorkflowHistoryId() { - return workflowHistoryId; - } - - public void setWorkflowHistoryId(String workflowHistoryId) { - this.workflowHistoryId = workflowHistoryId; - } - - public Status getStatus() { - return status; - } - - public void setStatus(Status status) { - this.status = status; - } - - public String getResult() { - return result; - } - - public void setResult(String result) { - this.result = result; - } - - public Date getFinished() { - return finished; - } - - public void setFinished(Date finished) { - this.finished = finished; - } - - public Date getCreated() { - return created; - } - - public void setCreated(Date created) { - this.created = created; - } - - public Date getUpdated() { - return updated; - } - - public void setUpdated(Date updated) { - this.updated = updated; - } - - public UUID getUuid() { - return uuid; - } - - public void setUuid(UUID uuid) { - this.uuid = uuid; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public UserDAO getCreatedBy() { - return createdBy; - } - - public void setCreatedBy(UserDAO createdBy) { - this.createdBy = createdBy; - } - - public boolean isViewed() { - return viewed; - } - - public void setViewed(boolean viewed) { - this.viewed = viewed; - } - - public boolean isShared() { - return shared; - } - - public void setShared(boolean shared) { - this.shared = shared; - } } diff --git a/src/main/java/eu/hbp/mip/models/DAOs/UserDAO.java b/src/main/java/eu/hbp/mip/models/DAOs/UserDAO.java index a94e5da1c177648965a8f3f192356fa5c2da8a07..9279b3793c44c449302c083b823da674d7e4d46f 100644 --- a/src/main/java/eu/hbp/mip/models/DAOs/UserDAO.java +++ b/src/main/java/eu/hbp/mip/models/DAOs/UserDAO.java @@ -7,12 +7,16 @@ package eu.hbp.mip.models.DAOs; import com.fasterxml.jackson.annotation.JsonInclude; import com.google.gson.annotations.Expose; import io.swagger.annotations.ApiModel; +import lombok.Getter; +import lombok.Setter; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity +@Getter +@Setter @Table(name = "`user`") @ApiModel @JsonInclude(JsonInclude.Include.NON_NULL) @@ -22,6 +26,9 @@ public class UserDAO { @Expose private String username; + @Expose + private String subjectId; + @Expose private String fullname; @@ -35,42 +42,12 @@ public class UserDAO { // Empty constructor is needed by Hibernate } - public UserDAO(String username, String fullname, String email) { + public UserDAO(String username, String fullname, String email, String subjectId) { this.username = username; this.fullname = fullname; this.email = email; this.agreeNDA = false; - } - - public String getFullname() { - return fullname; - } - - public void setFullname(String fullname) { - this.fullname = fullname; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public Boolean getAgreeNDA() { - return agreeNDA; - } + this.subjectId = subjectId; - public void setAgreeNDA(Boolean agreeNDA) { - this.agreeNDA = agreeNDA; } } diff --git a/src/main/java/eu/hbp/mip/services/ActiveUserService.java b/src/main/java/eu/hbp/mip/services/ActiveUserService.java index f1fe049c24673aa2a11cec62f4b266225e17376a..ee65c170ad2b09ebe6d0e602b5af2316cbf82c48 100644 --- a/src/main/java/eu/hbp/mip/services/ActiveUserService.java +++ b/src/main/java/eu/hbp/mip/services/ActiveUserService.java @@ -44,17 +44,17 @@ public class ActiveUserService { // If Authentication is OFF, create anonymous user with accepted NDA if (!authenticationIsEnabled) { - user = new UserDAO("anonymous", "anonymous", "anonymous@anonymous.com"); + user = new UserDAO("anonymous", "anonymous", "anonymous@anonymous.com","anonymousId"); user.setAgreeNDA(true); userRepository.save(user); return user; } - //TODO: + // If authentication is ON get user info from Token KeycloakPrincipal keycloakPrincipal = (KeycloakPrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); IDToken idToken = keycloakPrincipal.getKeycloakSecurityContext().getIdToken(); - user = new UserDAO(idToken.getPreferredUsername(), idToken.getName(), idToken.getEmail()); + user = new UserDAO(idToken.getPreferredUsername(), idToken.getName(), idToken.getEmail(), idToken.getId()); UserDAO userInDatabase = userRepository.findByUsername(user.getUsername()); if (userInDatabase == null || !userInDatabase.equals(user)) { diff --git a/src/main/java/eu/hbp/mip/services/ExperimentService.java b/src/main/java/eu/hbp/mip/services/ExperimentService.java index 869db8836a24d9e0e39a42fe663db4d2590c2100..2bc16b0f9939df9c015e25fde52c562d496c1c03 100644 --- a/src/main/java/eu/hbp/mip/services/ExperimentService.java +++ b/src/main/java/eu/hbp/mip/services/ExperimentService.java @@ -90,7 +90,7 @@ public class ExperimentService { if (size > 50) throw new BadRequestException("Invalid size input, max size is 50."); Specification<ExperimentDAO> spec; - if(!authenticationIsEnabled || ClaimUtils.validateAccessRightsOnExperiments(user.getUsername(), authentication.getAuthorities(), logger)) + if(!authenticationIsEnabled || ClaimUtils.validateAccessRightsOnExperiments(authentication, logger)) { spec = Specification .where(new ExperimentSpecifications.ExperimentWithName(name)) @@ -147,7 +147,7 @@ public class ExperimentService { !experimentDAO.isShared() && !experimentDAO.getCreatedBy().getUsername().equals(user.getUsername()) && authenticationIsEnabled - && ClaimUtils.validateAccessRightsOnExperiments(user.getUsername(), authentication.getAuthorities(), logger) + && ClaimUtils.validateAccessRightsOnExperiments(authentication, logger) ) { logger.LogUserAction("Accessing Experiment is unauthorized."); throw new UnauthorizedException("You don't have access to the experiment."); @@ -184,7 +184,7 @@ public class ExperimentService { if (authenticationIsEnabled) { String experimentDatasets = getDatasetFromExperimentParameters(experimentDTO, logger); - ClaimUtils.validateAccessRightsOnDatasets(user.getUsername(), authentication.getAuthorities(), experimentDatasets, logger); + ClaimUtils.validateAccessRightsOnDatasets(authentication, experimentDatasets, logger); } // Run with the appropriate engine @@ -222,7 +222,7 @@ public class ExperimentService { if (authenticationIsEnabled) { String experimentDatasets = getDatasetFromExperimentParameters(experimentDTO, logger); - ClaimUtils.validateAccessRightsOnDatasets(user.getUsername(), authentication.getAuthorities(), experimentDatasets, logger); + ClaimUtils.validateAccessRightsOnDatasets(authentication, experimentDatasets, logger); } String body = gson.toJson(algorithmParameters); @@ -739,7 +739,7 @@ public class ExperimentService { if (result == null) { experimentDAO.setStatus(ExperimentDAO.Status.error); } else { - experimentDAO.setResult("[" + result + "]"); + experimentDAO.setResult(result); experimentDAO.setStatus(ExperimentDAO.Status.success); resultFound = true; } diff --git a/src/main/java/eu/hbp/mip/utils/ClaimUtils.java b/src/main/java/eu/hbp/mip/utils/ClaimUtils.java index 501cea1b09a5755d7129450c16721fa71aba1602..902bf9f9fe677e39760e94553b27ff27a57c1c96 100644 --- a/src/main/java/eu/hbp/mip/utils/ClaimUtils.java +++ b/src/main/java/eu/hbp/mip/utils/ClaimUtils.java @@ -3,7 +3,9 @@ package eu.hbp.mip.utils; import com.google.gson.Gson; import eu.hbp.mip.models.DTOs.PathologyDTO; import eu.hbp.mip.utils.Exceptions.UnauthorizedException; -import org.springframework.security.core.GrantedAuthority; +import org.keycloak.KeycloakPrincipal; +import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; +import org.springframework.security.core.Authentication; import java.util.*; @@ -13,26 +15,28 @@ public class ClaimUtils { private static final Gson gson = new Gson(); public static String allDatasetsAllowedClaim() { - return "role_research_dataset_all"; + return "research_dataset_all"; } public static String allExperimentsAllowedClaim() { - return "role_research_experiment_all"; + return "research_experiment_all"; } public static String getDatasetClaim(String datasetCode) { - return "role_research_dataset_" + datasetCode.toLowerCase(); + return "research_dataset_" + datasetCode.toLowerCase(); } - public static void validateAccessRightsOnDatasets(String username, Collection<? extends GrantedAuthority> authorities, - String experimentDatasets, Logger logger) { + public static void validateAccessRightsOnDatasets(Authentication authentication, + String experimentDatasets, Logger logger) { + + ArrayList<String> authorities = getKeycloakAuthorities(authentication); // Don't check for dataset claims if "super" claim exists allowing everything - if (!hasRoleAccess(username, authorities, ClaimUtils.allDatasetsAllowedClaim(), logger)) { + if (!hasRoleAccess(authorities, ClaimUtils.allDatasetsAllowedClaim(), logger)) { for (String dataset : experimentDatasets.split(",")) { String datasetRole = ClaimUtils.getDatasetClaim(dataset); - if (!hasRoleAccess(username, authorities, datasetRole, logger)) { + if (!hasRoleAccess(authorities, datasetRole, logger)) { logger.LogUserAction("You are not allowed to use dataset: " + dataset); throw new UnauthorizedException("You are not authorized to use these datasets."); } @@ -41,19 +45,23 @@ public class ClaimUtils { } } - public static boolean validateAccessRightsOnExperiments(String username, Collection<? extends GrantedAuthority> authorities, Logger logger) { + public static boolean validateAccessRightsOnExperiments(Authentication authentication, Logger logger) { + + ArrayList<String> authorities = getKeycloakAuthorities(authentication); // Check for experiment_all claims - return hasRoleAccess(username, authorities, ClaimUtils.allExperimentsAllowedClaim(), logger); + return hasRoleAccess(authorities, ClaimUtils.allExperimentsAllowedClaim(), logger); } - public static String getAuthorizedPathologies(String username, Logger logger, Collection<? extends GrantedAuthority> authorities, + public static String getAuthorizedPathologies(Logger logger, Authentication authentication, List<PathologyDTO> allPathologies) { // --- Providing only the allowed pathologies/datasets to the user --- logger.LogUserAction("Filter out the unauthorised datasets."); + ArrayList<String> authorities = getKeycloakAuthorities(authentication); + // If the "dataset_all" claim exists then return everything - if (hasRoleAccess(username, authorities, ClaimUtils.allDatasetsAllowedClaim(), logger)) { + if (hasRoleAccess(authorities, ClaimUtils.allDatasetsAllowedClaim(), logger)) { return gson.toJson(allPathologies); } @@ -61,7 +69,7 @@ public class ClaimUtils { for (PathologyDTO curPathology : allPathologies) { List<PathologyDTO.PathologyDatasetDTO> userPathologyDatasets = new ArrayList<>(); for (PathologyDTO.PathologyDatasetDTO dataset : curPathology.getDatasets()) { - if (hasRoleAccess(username, authorities, ClaimUtils.getDatasetClaim(dataset.getCode()), logger)) { + if (hasRoleAccess(authorities, ClaimUtils.getDatasetClaim(dataset.getCode()), logger)) { logger.LogUserAction("Added dataset: " + dataset.getCode()); userPathologyDatasets.add(dataset); } @@ -83,7 +91,7 @@ public class ClaimUtils { return gson.toJson(userPathologies); } - private static boolean hasRoleAccess(String username, Collection<? extends GrantedAuthority> authorities,String role, Logger logger) + private static boolean hasRoleAccess(ArrayList<String> authorities, String role, Logger logger) { List<String> userClaims = Arrays.asList(authorities.toString().toLowerCase() .replaceAll("[\\s+\\]\\[]", "").split(",")); @@ -91,4 +99,10 @@ public class ClaimUtils { logger.LogUserAction("User Claims: " + userClaims); return userClaims.contains(role.toLowerCase()); } + + private static ArrayList<String> getKeycloakAuthorities(Authentication authentication){ + KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) authentication; + KeycloakPrincipal keycloakPrincipal = (KeycloakPrincipal) token.getPrincipal(); + return (ArrayList<String>)keycloakPrincipal.getKeycloakSecurityContext().getIdToken().getOtherClaims().get("authorities"); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index b44e1ae9e6f819465f823e018922dd28c72a6a0d..84053f9128a3a2c724ae1aa3ecab8ad0ff9b2e39 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -11,7 +11,7 @@ logging: ### AUTHENTICATION ### authentication: - enabled: false + enabled: true ### DATABASE CONFIGURATION ### diff --git a/src/main/resources/db/migration/V7_0__NewDatabaseStructure.sql b/src/main/resources/db/migration/V7_0__NewDatabaseStructure.sql index 04c6f3f996b7b7e12311ce7058be89812cea1faf..c39158269bd59362cfd010913c33f17a03e1a4ce 100644 --- a/src/main/resources/db/migration/V7_0__NewDatabaseStructure.sql +++ b/src/main/resources/db/migration/V7_0__NewDatabaseStructure.sql @@ -67,6 +67,9 @@ DROP COLUMN team, DROP COLUMN web, DROP COLUMN apikey; +ALTER TABLE "user" +ADD COLUMN subjectID text; + DROP TABLE "config_title", "config_yaxisvariables"; DROP TABLE "dataset_variable", "dataset_grouping", "dataset_data", "dataset_header"; DROP TABLE "query_variable", "query_grouping", "query_filter", "query_covariable";