From c552fa297ea5350a2f60d540be05d407c4f15ca8 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 14 Dec 2023 13:59:59 -0500 Subject: [PATCH 01/12] persist admin roles --- .../auth/FENCEAuthenticationService.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java index c97e9b6aa..c891d1a04 100644 --- a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java @@ -295,9 +295,23 @@ private User createUserFromFENCEProfile(JsonNode node) { logger.debug("createUserFromFENCEProfile() finished setting fields"); User actual_user = userRepo.findOrCreate(new_user); - - // Clear current set of roles every time we create or retrieve a user - actual_user.setRoles(new HashSet<>()); + + Role topAdmin = null; + Role admin = null; + if (actual_user.getRoles() != null && actual_user.getRoles().isEmpty()) { + actual_user.getRoles().stream() + .filter(userRole -> "PIC-SURE Top Admin".equals(userRole.getName()) || "Admin".equals(userRole.getName())) + .forEach(role -> { + if ("PIC-SURE Top Admin".equals(role.getName())) { + topAdmin = role; + } else if ("Admin".equals(role.getName())) { + admin = role; + } + }); + } + // Clear current set of roles every time we create or retrieve a user but persist admin status + actual_user.setRoles(new HashSet<>(Set.of(topAdmin, admin))); + logger.debug("createUserFromFENCEProfile() cleared roles"); userRepo.persist(actual_user); From f28c1e8cb92514d7a589ba38d0514bf0476b201d Mon Sep 17 00:00:00 2001 From: James Date: Thu, 14 Dec 2023 14:08:46 -0500 Subject: [PATCH 02/12] fix compile issue --- .../auth/FENCEAuthenticationService.java | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java index c891d1a04..fa8930c88 100644 --- a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java @@ -295,22 +295,21 @@ private User createUserFromFENCEProfile(JsonNode node) { logger.debug("createUserFromFENCEProfile() finished setting fields"); User actual_user = userRepo.findOrCreate(new_user); - - Role topAdmin = null; - Role admin = null; - if (actual_user.getRoles() != null && actual_user.getRoles().isEmpty()) { - actual_user.getRoles().stream() - .filter(userRole -> "PIC-SURE Top Admin".equals(userRole.getName()) || "Admin".equals(userRole.getName())) - .forEach(role -> { - if ("PIC-SURE Top Admin".equals(role.getName())) { - topAdmin = role; - } else if ("Admin".equals(role.getName())) { - admin = role; - } - }); - } - // Clear current set of roles every time we create or retrieve a user but persist admin status - actual_user.setRoles(new HashSet<>(Set.of(topAdmin, admin))); + + Role[] roles = new Role[2]; + + actual_user.getRoles().stream() + .filter(userRole -> "PIC-SURE Top Admin".equals(userRole.getName()) || "Admin".equals(userRole.getName())) + .forEach(role -> { + if ("PIC-SURE Top Admin".equals(role.getName())) { + roles[0] = role; + } else if ("Admin".equals(role.getName())) { + roles[1] = role; + } + }); + + // Clear current set of roles every time we create or retrieve a user but persist admin status + actual_user.setRoles(new HashSet<>(Set.of(roles[0], roles[1]))); logger.debug("createUserFromFENCEProfile() cleared roles"); From 21b249493c96f9a64b550e7e87cf5f95d222c401 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 4 Jan 2024 11:37:21 -0500 Subject: [PATCH 03/12] Add manual roles --- .../auth/FENCEAuthenticationService.java | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java index fa8930c88..88d35ff67 100644 --- a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java @@ -10,6 +10,7 @@ import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import javax.annotation.PostConstruct; import javax.inject.Inject; @@ -196,6 +197,7 @@ public Response getFENCEProfile(String callback_url, Map authReq } catch (Exception ex) { logger.error("getFENCEToken() Could not persist the user information, because "+ex.getMessage()); + ex.printStackTrace(); throw new NotAuthorizedException("The user details could not be persisted. Please contact the administrator."); } @@ -296,21 +298,16 @@ private User createUserFromFENCEProfile(JsonNode node) { User actual_user = userRepo.findOrCreate(new_user); - Role[] roles = new Role[2]; - - actual_user.getRoles().stream() - .filter(userRole -> "PIC-SURE Top Admin".equals(userRole.getName()) || "Admin".equals(userRole.getName())) - .forEach(role -> { - if ("PIC-SURE Top Admin".equals(role.getName())) { - roles[0] = role; - } else if ("Admin".equals(role.getName())) { - roles[1] = role; - } - }); + Set roles = new HashSet<>(); + if (actual_user != null) { + roles = actual_user.getRoles().stream() + .filter(userRole -> "PIC-SURE Top Admin".equals(userRole.getName()) || "Admin".equals(userRole.getName()) || userRole.getName().startsWith("MANUAL_")) + .collect(Collectors.toSet()); + } // Clear current set of roles every time we create or retrieve a user but persist admin status - actual_user.setRoles(new HashSet<>(Set.of(roles[0], roles[1]))); - + actual_user.setRoles(roles); + logger.debug("createUserFromFENCEProfile() cleared roles"); userRepo.persist(actual_user); From 0849736472a8dbd0858e5d5686ba74639835f7ce Mon Sep 17 00:00:00 2001 From: James Date: Fri, 5 Jan 2024 10:41:11 -0500 Subject: [PATCH 04/12] check if roles are empty --- .../avillach/auth/service/auth/FENCEAuthenticationService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java index 88d35ff67..19ab25015 100644 --- a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java @@ -36,6 +36,7 @@ import edu.harvard.hms.dbmi.avillach.auth.data.repository.*; import edu.harvard.hms.dbmi.avillach.auth.rest.UserService; import edu.harvard.hms.dbmi.avillach.auth.utils.AuthUtils; +import org.springframework.util.CollectionUtils; public class FENCEAuthenticationService { private Logger logger = LoggerFactory.getLogger(FENCEAuthenticationService.class); @@ -299,7 +300,7 @@ private User createUserFromFENCEProfile(JsonNode node) { User actual_user = userRepo.findOrCreate(new_user); Set roles = new HashSet<>(); - if (actual_user != null) { + if (actual_user != null && !CollectionUtils.isEmpty(actual_user.getRoles())) { roles = actual_user.getRoles().stream() .filter(userRole -> "PIC-SURE Top Admin".equals(userRole.getName()) || "Admin".equals(userRole.getName()) || userRole.getName().startsWith("MANUAL_")) .collect(Collectors.toSet()); From 19339d37d5797929a4709357068ce7f7f7fd5032 Mon Sep 17 00:00:00 2001 From: James Date: Tue, 16 Jan 2024 16:07:42 -0500 Subject: [PATCH 05/12] Add StudyAccessService --- .../avillach/auth/JAXRSConfiguration.java | 3 +- .../auth/rest/StudyAccessService.java | 89 +++++++++++++++++++ .../auth/FENCEAuthenticationService.java | 14 ++- .../dbmi/avillach/StudyAccessServiceTest.java | 63 +++++++++++++ 4 files changed, 163 insertions(+), 6 deletions(-) create mode 100644 pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/rest/StudyAccessService.java create mode 100644 pic-sure-auth-services/src/test/java/edu/harvard/hms/dbmi/avillach/StudyAccessServiceTest.java diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/JAXRSConfiguration.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/JAXRSConfiguration.java index 54756508e..e5d5d42f6 100755 --- a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/JAXRSConfiguration.java +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/JAXRSConfiguration.java @@ -150,8 +150,6 @@ public void init() { mailSession.getProperties().put("mail.smtp.ssl.trust", "smtp.gmail.com"); - logger.info("Auth micro app has been successfully started"); - //Set info for the swagger.json BeanConfig beanConfig = new BeanConfig(); beanConfig.setVersion("1.0.0"); @@ -161,6 +159,7 @@ public void init() { beanConfig.setBasePath("/psama"); beanConfig.setResourcePackage(TokenService.class.getPackage().getName()); beanConfig.setScan(true); + logger.info("Auth micro app has been successfully started"); } /* diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/rest/StudyAccessService.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/rest/StudyAccessService.java new file mode 100644 index 000000000..c43717b81 --- /dev/null +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/rest/StudyAccessService.java @@ -0,0 +1,89 @@ +package edu.harvard.hms.dbmi.avillach.auth.rest; + +import edu.harvard.hms.dbmi.avillach.auth.data.entity.Role; +import edu.harvard.hms.dbmi.avillach.auth.data.repository.RoleRepository; +import edu.harvard.hms.dbmi.avillach.auth.service.auth.FENCEAuthenticationService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; +import javax.inject.Inject; +import javax.transaction.Transactional; +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import java.util.Map; + +import static edu.harvard.hms.dbmi.avillach.auth.utils.AuthNaming.AuthRoleNaming.SUPER_ADMIN; + +/** + *

Endpoint for service handling business logic for adding all the auth + * rules for a given study

+ *

Note: Only users with the super admin role can access this endpoint.

+ */ +@Api +@Path("/studyAccess") +public class StudyAccessService { + Logger logger = LoggerFactory.getLogger(StudyAccessService.class); + + public static final String MANUAL = "MANUAL_"; + public static final String STUDY_IDENTIFIER = "study_identifier"; + public static final String CONSENT_GROUP_CODE = "consent_group_code"; + + @Inject + FENCEAuthenticationService fenceAuthenticationService; + + @ApiOperation(value = "POST a single study and it creates the role, privs, and rules for it, requires SUPER_ADMIN role") + @Transactional + @POST + @RolesAllowed(SUPER_ADMIN) + @Consumes(MediaType.APPLICATION_JSON) + @Path("/") + public Response addStudyAccess(String studyIdentifier) { + if (StringUtils.isBlank(studyIdentifier)) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("Study identifier cannot be blank") + .build(); + } + Map fenceMappingForStudy = null; + try { + Map fenceMapping = fenceAuthenticationService.getFENCEMapping(); + if (fenceMapping == null) { + throw new Exception("Fence mapping is null"); + } + fenceMappingForStudy = fenceMapping.get(studyIdentifier); + } catch(Exception ex) { + logger.error(ex.toString()); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("Error occurred while fetching FENCE mapping") + .build(); + } + if (fenceMappingForStudy == null || fenceMappingForStudy.isEmpty()) { + logger.error("addStudyAccess - Could not find study: " + studyIdentifier + " in FENCE mapping"); + return Response.status(Response.Status.NOT_FOUND) + .entity("Could not find study with the provided identifier") + .build(); + } + String projectId = (String) fenceMappingForStudy.get(STUDY_IDENTIFIER); + String consentCode = (String) fenceMappingForStudy.get(CONSENT_GROUP_CODE); + String newRoleName = StringUtils.isNotBlank(consentCode) ? MANUAL+projectId+"_"+consentCode : MANUAL+projectId; + + logger.debug("addStudyAccess - New manual PSAMA role name: "+newRoleName); + + if (fenceAuthenticationService.upsertRole(null, newRoleName, MANUAL + " role "+newRoleName)) { + logger.info("addStudyAccess - Updated user role. Now it includes `"+newRoleName+"`"); + return Response.ok("Role '" + newRoleName + "' successfully created").build(); + } else { + logger.error("addStudyAccess - could not add " + newRoleName + " role to to database"); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("Could not add role '" + newRoleName + "' to database") + .build(); + } + } +} diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java index 19ab25015..6899c7c04 100644 --- a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java @@ -326,7 +326,6 @@ private User createUserFromFENCEProfile(JsonNode node) { */ public boolean upsertRole(User u, String roleName, String roleDescription) { boolean status = false; - logger.debug("upsertRole() starting for user subject:"+u.getSubject()); // Get the User's list of Roles. The first time, this will be an empty Set. // This method is called for every Role, and the User's list of Roles will @@ -350,7 +349,9 @@ public boolean upsertRole(User u, String roleName, String roleDescription) { roleRepo.persist(r); logger.info("upsertRole() created new role"); } - u.getRoles().add(r); + if (u != null) { + u.getRoles().add(r); + } status = true; } catch (Exception ex) { logger.error("upsertRole() Could not inser/update role "+roleName+" to repo", ex); @@ -435,6 +436,9 @@ private Set addFENCEPrivileges(User u, Role r) { private static String extractProject(String roleName) { String projectPattern = "FENCE_(.*?)(?:_c\\d+)?$"; + if (roleName.startsWith("MANUAL_")) { + projectPattern = "MANUAL_(.*?)(?:_c\\d+)?$"; + } Pattern projectRegex = Pattern.compile(projectPattern); Matcher projectMatcher = projectRegex.matcher(roleName); String project = ""; @@ -451,7 +455,9 @@ private static String extractProject(String roleName) { private static String extractConsentGroup(String roleName) { String consentPattern = "FENCE_.*?_c(\\d+)$"; - + if (roleName.startsWith("MANUAL_")) { + consentPattern = "MANUAL_.*?_c(\\d+)$"; + } Pattern consentRegex = Pattern.compile(consentPattern); Matcher consentMatcher = consentRegex.matcher(roleName); String consentGroup = ""; @@ -1125,7 +1131,7 @@ private Map getFENCEMappingforProjectAndConsent(String projectId, String consent return null; } - private Map getFENCEMapping(){ + public Map getFENCEMapping(){ if(_projectMap == null || _projectMap.isEmpty()) { try { Map fenceMapping = JAXRSConfiguration.objectMapper.readValue( diff --git a/pic-sure-auth-services/src/test/java/edu/harvard/hms/dbmi/avillach/StudyAccessServiceTest.java b/pic-sure-auth-services/src/test/java/edu/harvard/hms/dbmi/avillach/StudyAccessServiceTest.java new file mode 100644 index 000000000..a3811e3ee --- /dev/null +++ b/pic-sure-auth-services/src/test/java/edu/harvard/hms/dbmi/avillach/StudyAccessServiceTest.java @@ -0,0 +1,63 @@ +package edu.harvard.hms.dbmi.avillach; + +import edu.harvard.hms.dbmi.avillach.auth.data.repository.RoleRepository; +import edu.harvard.hms.dbmi.avillach.auth.rest.StudyAccessService; +import edu.harvard.hms.dbmi.avillach.auth.service.auth.FENCEAuthenticationService; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import javax.ws.rs.core.Response; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; + +public class StudyAccessServiceTest { + + @InjectMocks + private StudyAccessService studyAccessService; + + @Mock + private FENCEAuthenticationService fenceAuthenticationService; + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + } + + + @Test + public void testAddStudyAccessWithBlankIdentifier() { + String studyIdentifier = ""; + Response response = studyAccessService.addStudyAccess(studyIdentifier); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); + assertEquals("Study identifier cannot be blank", response.getEntity()); + } + + @Test + public void testAddStudyAccess() { + String studyIdentifier = "testStudy"; + when(fenceAuthenticationService.getFENCEMapping()).thenReturn(Map.of(studyIdentifier, Map.of(StudyAccessService.STUDY_IDENTIFIER, studyIdentifier,StudyAccessService.CONSENT_GROUP_CODE, ""))); + when(fenceAuthenticationService.upsertRole(null, "MANUAL_testStudy", "MANUAL_ role MANUAL_testStudy")).thenReturn(true); + + Response response = studyAccessService.addStudyAccess(studyIdentifier); + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + assertEquals("Role 'MANUAL_testStudy' successfully created", response.getEntity()); + } + + @Test + public void testAddStudyAccessWithConsent() { + String studyIdentifier = "testStudy2.c2"; + when(fenceAuthenticationService.getFENCEMapping()).thenReturn(Map.of(studyIdentifier, Map.of(StudyAccessService.STUDY_IDENTIFIER, "testStudy2", StudyAccessService.CONSENT_GROUP_CODE, "c2"))); + when(fenceAuthenticationService.upsertRole(null, "MANUAL_testStudy2_c2", "MANUAL_ role MANUAL_testStudy2_c2")).thenReturn(true); + Response response = studyAccessService.addStudyAccess(studyIdentifier); + + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + assertEquals("Role 'MANUAL_testStudy2_c2' successfully created", response.getEntity()); + } +} \ No newline at end of file From 244d58738b617c9b0b638b68c6d82175fc2ee1a7 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 17 Jan 2024 11:06:59 -0500 Subject: [PATCH 06/12] Better error code; clean up --- .../hms/dbmi/avillach/auth/rest/StudyAccessService.java | 5 +++-- .../auth/service/auth/FENCEAuthenticationService.java | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/rest/StudyAccessService.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/rest/StudyAccessService.java index c43717b81..cb7a5f1ca 100644 --- a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/rest/StudyAccessService.java +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/rest/StudyAccessService.java @@ -5,6 +5,7 @@ import edu.harvard.hms.dbmi.avillach.auth.service.auth.FENCEAuthenticationService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,7 +46,7 @@ public class StudyAccessService { @RolesAllowed(SUPER_ADMIN) @Consumes(MediaType.APPLICATION_JSON) @Path("/") - public Response addStudyAccess(String studyIdentifier) { + public Response addStudyAccess(@ApiParam(value="The Study Identifier of the new study from the metadata.json") String studyIdentifier) { if (StringUtils.isBlank(studyIdentifier)) { return Response.status(Response.Status.BAD_REQUEST) .entity("Study identifier cannot be blank") @@ -66,7 +67,7 @@ public Response addStudyAccess(String studyIdentifier) { } if (fenceMappingForStudy == null || fenceMappingForStudy.isEmpty()) { logger.error("addStudyAccess - Could not find study: " + studyIdentifier + " in FENCE mapping"); - return Response.status(Response.Status.NOT_FOUND) + return Response.status(Response.Status.BAD_REQUEST) .entity("Could not find study with the provided identifier") .build(); } diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java index 6899c7c04..9e7f9d3d9 100644 --- a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java @@ -198,7 +198,6 @@ public Response getFENCEProfile(String callback_url, Map authReq } catch (Exception ex) { logger.error("getFENCEToken() Could not persist the user information, because "+ex.getMessage()); - ex.printStackTrace(); throw new NotAuthorizedException("The user details could not be persisted. Please contact the administrator."); } From 4747d551f7bb251c6d876c085e4f1bf444395770 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 17 Jan 2024 11:30:19 -0500 Subject: [PATCH 07/12] Bump swagger version? --- .../avillach/auth/JAXRSConfiguration.java | 2 +- .../auth/rest/StudyAccessService.java | 20 +++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/JAXRSConfiguration.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/JAXRSConfiguration.java index e5d5d42f6..63aed0747 100755 --- a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/JAXRSConfiguration.java +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/JAXRSConfiguration.java @@ -152,7 +152,7 @@ public void init() { //Set info for the swagger.json BeanConfig beanConfig = new BeanConfig(); - beanConfig.setVersion("1.0.0"); + beanConfig.setVersion("1.0.1"); beanConfig.setSchemes(new String[] { "https" }); beanConfig.setDescription("APIs for accessing PIC-SURE-AUTH-MICROAPP - a centralized authentication/authorization micro services"); beanConfig.setTitle("PIC-SURE-AUTH-MICROAPP"); diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/rest/StudyAccessService.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/rest/StudyAccessService.java index cb7a5f1ca..3fe0db33b 100644 --- a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/rest/StudyAccessService.java +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/rest/StudyAccessService.java @@ -47,12 +47,13 @@ public class StudyAccessService { @Consumes(MediaType.APPLICATION_JSON) @Path("/") public Response addStudyAccess(@ApiParam(value="The Study Identifier of the new study from the metadata.json") String studyIdentifier) { + if (StringUtils.isBlank(studyIdentifier)) { - return Response.status(Response.Status.BAD_REQUEST) - .entity("Study identifier cannot be blank") - .build(); + return Response.status(Response.Status.BAD_REQUEST).entity("Study identifier cannot be blank").build(); } + Map fenceMappingForStudy = null; + try { Map fenceMapping = fenceAuthenticationService.getFENCEMapping(); if (fenceMapping == null) { @@ -61,16 +62,14 @@ public Response addStudyAccess(@ApiParam(value="The Study Identifier of the new fenceMappingForStudy = fenceMapping.get(studyIdentifier); } catch(Exception ex) { logger.error(ex.toString()); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR) - .entity("Error occurred while fetching FENCE mapping") - .build(); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Error occurred while fetching FENCE mapping").build(); } + if (fenceMappingForStudy == null || fenceMappingForStudy.isEmpty()) { logger.error("addStudyAccess - Could not find study: " + studyIdentifier + " in FENCE mapping"); - return Response.status(Response.Status.BAD_REQUEST) - .entity("Could not find study with the provided identifier") - .build(); + return Response.status(Response.Status.BAD_REQUEST).entity("Could not find study with the provided identifier").build(); } + String projectId = (String) fenceMappingForStudy.get(STUDY_IDENTIFIER); String consentCode = (String) fenceMappingForStudy.get(CONSENT_GROUP_CODE); String newRoleName = StringUtils.isNotBlank(consentCode) ? MANUAL+projectId+"_"+consentCode : MANUAL+projectId; @@ -83,8 +82,7 @@ public Response addStudyAccess(@ApiParam(value="The Study Identifier of the new } else { logger.error("addStudyAccess - could not add " + newRoleName + " role to to database"); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) - .entity("Could not add role '" + newRoleName + "' to database") - .build(); + .entity("Could not add role '" + newRoleName + "' to database").build(); } } } From 1a1fed5f560f0d60177e7acf54f574925f0656bd Mon Sep 17 00:00:00 2001 From: James Date: Wed, 17 Jan 2024 13:03:31 -0500 Subject: [PATCH 08/12] Added jersey-server for tests --- pic-sure-auth-services/pom.xml | 138 ++------------------------------- 1 file changed, 7 insertions(+), 131 deletions(-) diff --git a/pic-sure-auth-services/pom.xml b/pic-sure-auth-services/pom.xml index 8ac7966cd..cc43bca33 100644 --- a/pic-sure-auth-services/pom.xml +++ b/pic-sure-auth-services/pom.xml @@ -11,11 +11,11 @@ pic-sure-auth-services war - 2.10.0 2.3.0 + edu.harvard.hms.dbmi.avillach @@ -79,16 +79,6 @@ hibernate-envers 5.2.5.Final - - - - - - - - - - com.fasterxml.jackson.core jackson-core @@ -99,21 +89,6 @@ jackson-databind ${jackson.version} - - - - - - - - - - - - - - - org.springframework spring-web @@ -152,6 +127,12 @@ 2.23.4 test + + org.glassfish.jersey.core + jersey-server + 2.3.1 + test + com.github.spullara.mustache.java compiler @@ -193,30 +174,6 @@ swagger-jaxrs2-servlet-initializer 2.0.0 - - - - - - - - - - - - - - - - - - - - - - ${project.artifactId} @@ -237,34 +194,6 @@ false - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -313,59 +242,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 8d6572c0282c2eacebfa20c4f7adce265958c47b Mon Sep 17 00:00:00 2001 From: James Date: Fri, 19 Jan 2024 08:20:23 -0500 Subject: [PATCH 09/12] Add guava to pom --- pic-sure-auth-services/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pic-sure-auth-services/pom.xml b/pic-sure-auth-services/pom.xml index cc43bca33..23b4d2a1e 100644 --- a/pic-sure-auth-services/pom.xml +++ b/pic-sure-auth-services/pom.xml @@ -156,6 +156,11 @@ javax.mail-api 1.6.2 + + com.google.guava + guava + 33.0.0-jre + From 083e9807c1de69f46a3e3b63fda89dfe5e319896 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 19 Jan 2024 14:39:20 -0500 Subject: [PATCH 10/12] Adds method to look for accounts missing a subject --- .../auth/data/repository/UserRepository.java | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/data/repository/UserRepository.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/data/repository/UserRepository.java index 2188daa24..d725fec2b 100644 --- a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/data/repository/UserRepository.java +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/data/repository/UserRepository.java @@ -42,6 +42,19 @@ public User findBySubject(String subject) { .getSingleResult(); } + public User findByEmailAndConnection(String email, String connectionId) { + CriteriaQuery query = em.getCriteriaBuilder().createQuery(User.class); + Root queryRoot = query.from(User.class); + query.select(queryRoot); + CriteriaBuilder cb = cb(); + return em.createQuery(query + .where( + cb.equal(queryRoot.join("connection") + .get("id"), connectionId), + eq(cb, queryRoot, "email", email))) + .getSingleResult(); + } + public User findBySubjectAndConnection(String subject, String connectionId) { CriteriaQuery query = em.getCriteriaBuilder().createQuery(User.class); Root queryRoot = query.from(User.class); @@ -86,8 +99,16 @@ public User findOrCreate(User inputUser) { + ", subject: " + user.getSubject()); } catch (NoResultException e) { logger.debug("findOrCreate() subject " + subject + - " could not be found by `entityManager`, going to create a new user."); - user = createUser(inputUser); + " could not be found by `entityManager`, checking by email and connection"); + try { + // If the user isn't found by subject then check by email and connection just + // in case they were created by jenkins + user = findByEmailAndConnection(inputUser.getEmail(), inputUser.getConnection().getId()); + } catch (NoResultException ex) { + logger.debug("findOrCreate() email " + inputUser.getEmail() + + " could not be found by `entityManager`, creating a new user"); + user = createUser(inputUser); + } } catch (NonUniqueResultException e) { logger.error("findOrCreate() " + e.getClass().getSimpleName() + ": " + e.getMessage()); } From 93dcd8662ac4aa5d9e94c106e813c87890204335 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 24 Jan 2024 13:13:10 -0500 Subject: [PATCH 11/12] Check if subject is empty --- .../dbmi/avillach/auth/data/repository/UserRepository.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/data/repository/UserRepository.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/data/repository/UserRepository.java index d725fec2b..cabd37235 100644 --- a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/data/repository/UserRepository.java +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/data/repository/UserRepository.java @@ -5,6 +5,7 @@ import edu.harvard.hms.dbmi.avillach.auth.data.entity.Role; import edu.harvard.hms.dbmi.avillach.auth.data.entity.TermsOfService; import edu.harvard.hms.dbmi.avillach.auth.data.entity.User; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -104,6 +105,10 @@ public User findOrCreate(User inputUser) { // If the user isn't found by subject then check by email and connection just // in case they were created by jenkins user = findByEmailAndConnection(inputUser.getEmail(), inputUser.getConnection().getId()); + if (StringUtils.isEmpty(user.getSubject())) { + user.setSubject(inputUser.getSubject()); + user.setGeneralMetadata(inputUser.getGeneralMetadata()); + } } catch (NoResultException ex) { logger.debug("findOrCreate() email " + inputUser.getEmail() + " could not be found by `entityManager`, creating a new user"); From 97e41e794e23bca1c1c61011c148186e8dbc006a Mon Sep 17 00:00:00 2001 From: James Date: Wed, 6 Mar 2024 08:58:51 -0500 Subject: [PATCH 12/12] Fix error messages --- .../auth/service/auth/FENCEAuthenticationService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java index 9e7f9d3d9..51afc1794 100644 --- a/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java +++ b/pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java @@ -142,7 +142,7 @@ private JsonNode getFENCEAccessToken(String callback_url, String fence_code) { headers.toArray(new Header[headers.size()]) ); } catch (Exception ex) { - logger.error("getFENCEAccessToken() failed to call FENCE token service, "+ex.getMessage()); + logger.error("getFENCEAccessToken() failed to call FENCE token service, " + ex); } logger.debug("getFENCEAccessToken() finished: "+resp.asText()); return resp; @@ -179,7 +179,7 @@ public Response getFENCEProfile(String callback_url, Map authReq } catch (Exception ex) { logger.error("getFENCEProfile() could not retrieve the user profile from the auth provider, because "+ex.getMessage(), ex); throw new NotAuthorizedException("Could not get the user profile "+ - "from the Gen3 authentication provider."+ex.getMessage()); + "from the Gen3 authentication provider." + ex); } User current_user = null; @@ -197,7 +197,7 @@ public Response getFENCEProfile(String callback_url, Map authReq UserService.clearCache(current_user); } catch (Exception ex) { - logger.error("getFENCEToken() Could not persist the user information, because "+ex.getMessage()); + logger.error("getFENCEToken() Could not persist the user information, because " + ex); throw new NotAuthorizedException("The user details could not be persisted. Please contact the administrator."); }