Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit e15e891

Browse files
committedMay 15, 2024·
Refactor FENCEAuthenticationService and RoleRepository
Implemented an extensive refactor of FENCEAuthenticationService's user role management. Updated functionalities include: removal of roles not in the project_access_set, detection of previously assigned roles, assigning database-existing roles to users, and creation and upserting of non-existing roles in the database. Corrected the logic to re-assign new roles to the user after persistence of these roles. Adjustments also made in RoleRepository to return roles by names.
1 parent 43524f5 commit e15e891

File tree

2 files changed

+66
-21
lines changed

2 files changed

+66
-21
lines changed
 

‎pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/data/repository/RoleRepository.java

+7-4
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55

66
import javax.enterprise.context.ApplicationScoped;
77
import javax.transaction.Transactional;
8-
import java.util.ArrayList;
9-
import java.util.HashSet;
10-
import java.util.Set;
11-
import java.util.UUID;
8+
import java.util.*;
129

1310
/**
1411
* <p>Provides operations for the Role entity to interact with a database.</p>
@@ -46,4 +43,10 @@ public void persistAll(ArrayList<Role> newRoles) {
4643
em.clear();
4744
}
4845
}
46+
47+
public Set<Role> getRolesByNames(Set<String> rolesThatExist) {
48+
return new HashSet<>(em.createQuery("SELECT r FROM role r WHERE r.name IN :rolesThatExist", Role.class)
49+
.setParameter("rolesThatExist", rolesThatExist)
50+
.getResultList());
51+
}
4952
}

‎pic-sure-auth-services/src/main/java/edu/harvard/hms/dbmi/avillach/auth/service/auth/FENCEAuthenticationService.java

+59-17
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@
66
import static edu.harvard.hms.dbmi.avillach.auth.JAXRSConfiguration.fence_standard_access_rules;
77
import static edu.harvard.hms.dbmi.avillach.auth.JAXRSConfiguration.fence_topmed_consent_group_concept_path;
88

9-
import java.io.IOException;
109
import java.util.*;
1110
import java.util.regex.Matcher;
1211
import java.util.regex.Pattern;
13-
import java.util.stream.Collectors;
1412

1513
import javax.annotation.PostConstruct;
1614
import javax.inject.Inject;
@@ -221,27 +219,71 @@ public Response getFENCEProfile(String callback_url, Map<String, String> authReq
221219
project_access_set.add(newRoleName);
222220
}
223221

224-
// given a set of all access role names, we can create a sinlge query to get all Role objects
225-
// that match the names in the set
226-
Set<String> roles = roleRepo.getRoleNamesByNames(project_access_set);
222+
/*
223+
Considerations for updating the user's roles:
224+
1. If the user has a role that is not in the project_access_set, we need to remove it.
225+
a. Unless it is a manual role, PIC-SURE Top Admin, Admin, and Manual, in which case we do not need to do anything.
226+
2. If the user does not have a role that is in the project_access_set, we need to add it.
227+
a. We can first check if the role exists in the database, and if it does, we can add it to the user.
228+
b. If the role does not exist in the database, we need to create it and add it to the user.
229+
3. If the user has a role that is in the project_access_set, we do not need to do anything.
230+
*/
231+
232+
// Step 1: Remove roles that are not in the project_access_set
233+
Set<Role> rolesToRemove = new HashSet<>();
234+
// Also, track the roles that are assigned to the user and in the project_access_set
235+
Set<String> rolesAssigned = new HashSet<>();
236+
for (Role role : current_user.getRoles()) {
237+
// .filter(userRole -> "PIC-SURE Top Admin".equals(userRole.getName()) || "Admin".equals(userRole.getName()) || userRole.getName().startsWith("MANUAL_"))
238+
if (!project_access_set.contains(role.getName())
239+
&& !role.getName().startsWith("MANUAL_")
240+
&& !role.getName().equals(fence_open_access_role_name)
241+
&& !role.getName().equals("PIC-SURE Top Admin")
242+
&& !role.getName().equals("Admin")) {
243+
rolesToRemove.add(role);
244+
}
245+
246+
if (project_access_set.contains(role.getName())) {
247+
rolesAssigned.add(role.getName());
248+
}
249+
}
250+
251+
// Remove roles that are not in the project_access_set
252+
if (!CollectionUtils.isEmpty(rolesToRemove)) {
253+
logger.info("getFENCEProfile() removing roles: {}", rolesToRemove);
254+
current_user.getRoles().removeAll(rolesToRemove);
255+
}
256+
257+
// Given the set of roles assigned and that set of roles that should be assigned, we can reduce the set of roles from the project_access_set
258+
// to only those that are not in the rolesAssigned set
259+
project_access_set.removeAll(rolesAssigned);
260+
261+
// Given our reduced list of roles that should be assigned, we can determine which of those roles are not in the database
262+
// This also tells use which roles are in the database
263+
Set<String> rolesThatExist = roleRepo.getRoleNamesByNames(project_access_set);
264+
265+
// Assign the roles that exist in the database to the user
266+
logger.info("getFENCEProfile() roles that exist in the database: {}", rolesThatExist);
267+
roleRepo.getRolesByNames(rolesThatExist).forEach(role -> current_user.getRoles().add(role));
227268

228269
// Given a set of all access role names that exist in the database we can now determine which do not exist
229270
// and create them
230-
project_access_set.removeAll(roles);
231-
logger.info("getFENCEProfile() roles that do not exist in the database: {}", project_access_set);
271+
project_access_set.removeAll(rolesThatExist);
232272

273+
logger.info("getFENCEProfile() roles that do not exist in the database: {}", project_access_set);
233274
// Given the set of all access role names that do not exist in the database we can now create them
234275
ArrayList<Role> newRoles = new ArrayList<>();
235276
for (String access_role_name : project_access_set) {
236277
newRoles.add(createAndUpsertRole(access_role_name, current_user));
237278
}
238279

239-
// add the new roles to the user
240-
current_user.getRoles().addAll(newRoles);
241-
242280
// Persist the new roles
281+
logger.info("getFENCEProfile() persisting {} new roles", newRoles.size());
243282
roleRepo.persistAll(newRoles);
244283

284+
// Assign the new roles to the user
285+
current_user.getRoles().addAll(newRoles);
286+
245287
final String idp = extractIdp(current_user);
246288
if (current_user.getRoles() != null && (!current_user.getRoles().isEmpty() || openAccessIdpValues.contains(idp))) {
247289
Role openAccessRole = roleRepo.getUniqueResultByColumn("name", fence_open_access_role_name);
@@ -316,15 +358,15 @@ private User createUserFromFENCEProfile(JsonNode node) {
316358

317359
User actual_user = userRepo.findOrCreate(new_user);
318360

319-
Set<Role> roles = new HashSet<>();
320-
if (actual_user != null && !CollectionUtils.isEmpty(actual_user.getRoles())) {
321-
roles = actual_user.getRoles().stream()
322-
.filter(userRole -> "PIC-SURE Top Admin".equals(userRole.getName()) || "Admin".equals(userRole.getName()) || userRole.getName().startsWith("MANUAL_"))
323-
.collect(Collectors.toSet());
324-
}
361+
// Set<Role> roles = new HashSet<>();
362+
// if (actual_user != null && !CollectionUtils.isEmpty(actual_user.getRoles())) {
363+
// roles = actual_user.getRoles().stream()
364+
// .filter(userRole -> "PIC-SURE Top Admin".equals(userRole.getName()) || "Admin".equals(userRole.getName()) || userRole.getName().startsWith("MANUAL_"))
365+
// .collect(Collectors.toSet());
366+
// }
325367

326368
// Clear current set of roles every time we create or retrieve a user but persist admin status
327-
actual_user.setRoles(roles);
369+
// actual_user.setRoles(roles);
328370

329371
logger.debug("createUserFromFENCEProfile() cleared roles");
330372

0 commit comments

Comments
 (0)
Please sign in to comment.