diff --git a/roda-core/roda-core/src/main/java/org/roda/core/model/utils/LdapUtility.java b/roda-core/roda-core/src/main/java/org/roda/core/model/utils/LdapUtility.java index 54d87c06f9..e0d58fe62b 100644 --- a/roda-core/roda-core/src/main/java/org/roda/core/model/utils/LdapUtility.java +++ b/roda-core/roda-core/src/main/java/org/roda/core/model/utils/LdapUtility.java @@ -1588,7 +1588,11 @@ private void setMemberGroups(final String memberDN, final Set groups) th final Set newgroupDNs = new HashSet<>(); for (String groupName : newGroups) { LdapGroup ldapGroup = ldapGroupRepository.findByCommonName(groupName); - newgroupDNs.add(ldapGroup.getId().toString()); + if (ldapGroup == null) { + LOGGER.warn("Group {} doesn't exist", groupName); + } else { + newgroupDNs.add(ldapGroup.getId().toString()); + } } // removing all the groups in newgroups, oldgroups becomes the Set diff --git a/roda-core/roda-core/src/main/java/org/roda/core/plugins/SecurityManager.java b/roda-core/roda-core/src/main/java/org/roda/core/plugins/SecurityManager.java index ad4d6542bd..260d7a746b 100644 --- a/roda-core/roda-core/src/main/java/org/roda/core/plugins/SecurityManager.java +++ b/roda-core/roda-core/src/main/java/org/roda/core/plugins/SecurityManager.java @@ -1,7 +1,10 @@ package org.roda.core.plugins; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.BiConsumer; import org.apache.commons.lang3.StringUtils; @@ -100,6 +103,7 @@ public User processLogin(final String username, final Map attrib User user = null; try { + // find user with username user = RodaCoreFactory.getModelService().retrieveUser(username); } catch (GenericException e) { if (!(e.getCause() instanceof NamingException)) { @@ -108,31 +112,54 @@ public User processLogin(final String username, final Map attrib } if (user == null || user.equals(new User())) { - User newUser = new User(username); - newUser = UserUtility.resetGroupsAndRoles(newUser); - - // try to set user email from cas principal attributes - mapAttribute(newUser, attributes, "fullname", (u, a) -> u.setFullName(a)); - mapAttribute(newUser, attributes, "email", (u, a) -> u.setEmail(a)); - - // Try to find a user with email - User retrievedUserByEmail = null; - if (StringUtils.isNotBlank(newUser.getEmail())) { + // couldn't find with username, so try to find with email + Object emailAttribute = attributes.get("email"); + if (emailAttribute instanceof String email && StringUtils.isNotBlank(email)) { try { - retrievedUserByEmail = RodaCoreFactory.getModelService().retrieveUserByEmail(newUser.getEmail()); + user = RodaCoreFactory.getModelService().retrieveUserByEmail(email); } catch (GenericException e) { if (!(e.getCause() instanceof NamingException)) { throw e; } } } + } + + if (user == null || user.equals(new User())) { + // couldn't find user with username nor email, so create a new one + user = new User(username); + user = UserUtility.resetGroupsAndRoles(user); - if (retrievedUserByEmail != null) { - user = retrievedUserByEmail; - } else { - // If no user was found with username or e-mail, a new one is created. - user = RodaCoreFactory.getModelService().createUser(newUser, true); + // try to set user email, full name and groups from cas principal attributes + mapStringAttribute(user, attributes, "fullname", (u, a) -> u.setFullName(a)); + mapStringAttribute(user, attributes, "email", (u, a) -> u.setEmail(a)); + mapSetAttribute(user, attributes, "memberOf", (u, a) -> u.setGroups(a)); + + user = RodaCoreFactory.getModelService().createUser(user, true); + } + else { + // found user and authentication externally, so update user email, full name and + // groups from cas principal + // attributes if they have changed + if (attributes.get("email") instanceof String email && !user.getEmail().equals(attributes.get("email"))) { + user.setEmail(email); + } + if (attributes.get("fullname") instanceof String fullname + && !user.getFullName().equals(attributes.get("fullname"))) { + user.setFullName(fullname); } + if (attributes.get("memberOf") instanceof Collection memberOf) { + Set groups = new HashSet<>(); + for (Object group : memberOf) { + if (group instanceof String groupString) { + groups.add(groupString); + } + } + if (!user.getGroups().equals(groups)) { + user.setGroups(groups); + } + } + RodaCoreFactory.getModelService().updateUser(user, null, true); } if (!user.isActive()) { @@ -143,7 +170,7 @@ public User processLogin(final String username, final Map attrib return user; } - private void mapAttribute(User user, Map attributes, String attributeKey, + private void mapStringAttribute(User user, Map attributes, String attributeKey, BiConsumer mapping) { Object attributeValue = attributes.get(attributeKey); if (attributeValue instanceof String value) { @@ -151,6 +178,23 @@ private void mapAttribute(User user, Map attributes, String attr } } + private void mapSetAttribute(User user, Map attributes, String attributeKey, + BiConsumer> mapping) { + Object attributeValue = attributes.get(attributeKey); + Set newCollection = new HashSet<>(); + if (attributeValue instanceof Collection valueCollection) { + for (Object value : valueCollection) { + if (value instanceof String valueString) { + newCollection.add(valueString); + } + } + } + else if (attributeValue instanceof String group) { + newCollection.add(group); + } + mapping.accept(user, newCollection); + } + public void logout(HttpServletRequest request, List extraAttributesToBeRemovedFromSession) { String loginMethod = (String) request.getSession().getAttribute(RODA_LOGIN_METHOD); request.getSession().removeAttribute(RODA_LOGIN_METHOD); diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/api/v2/controller/MembersController.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/api/v2/controller/MembersController.java index 60b308327d..def337a94e 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/api/v2/controller/MembersController.java +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/api/v2/controller/MembersController.java @@ -2,7 +2,9 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -10,6 +12,7 @@ import javax.crypto.SecretKey; +import org.apache.commons.lang3.StringUtils; import org.apereo.cas.client.authentication.AttributePrincipal; import org.roda.core.RodaCoreFactory; import org.roda.core.common.JwtUtils; @@ -60,7 +63,6 @@ import org.roda.wui.client.management.recaptcha.RecaptchaException; import org.roda.wui.client.services.MembersRestService; import org.roda.wui.common.ControllerAssistant; -import org.roda.wui.common.client.tools.StringUtils; import org.roda.wui.common.model.RequestContext; import org.roda.wui.common.utils.RequestUtils; import org.slf4j.Logger; @@ -134,6 +136,7 @@ public static User casLoginHelper(final String username, final HttpServletReques User user = null; try { + // find user with username user = RodaCoreFactory.getModelService().retrieveUser(username); } catch (GenericException e) { if (!(e.getCause() instanceof NamingException)) { @@ -141,36 +144,59 @@ public static User casLoginHelper(final String username, final HttpServletReques } } - if (user == null) { - User newUser = new User(username); - newUser = UserUtility.resetGroupsAndRoles(newUser); - - // try to set user email from cas principal attributes - if (request.getUserPrincipal() instanceof AttributePrincipal attributePrincipal) { - Map attributes = attributePrincipal.getAttributes(); - - mapCasAttribute(newUser, attributes, "fullname", (u, a) -> u.setFullName(a)); - mapCasAttribute(newUser, attributes, "email", (u, a) -> u.setEmail(a)); - } + Map attributes = null; + if (request.getUserPrincipal() instanceof AttributePrincipal attributesPrincipal) { + attributes = attributesPrincipal.getAttributes(); + } - // Try to find a user with email - User retrievedUserByEmail = null; - if (StringUtils.isNotBlank(newUser.getEmail())) { + if ((user == null || user.equals(new User())) && attributes != null) { + // couldn't find with username, so try to find with email + Object emailAttribute = attributes.get("email"); + if (emailAttribute instanceof String email && StringUtils.isNotBlank(email)) { try { - retrievedUserByEmail = RodaCoreFactory.getModelService().retrieveUserByEmail(newUser.getEmail()); + user = RodaCoreFactory.getModelService().retrieveUserByEmail(email); } catch (GenericException e) { if (!(e.getCause() instanceof NamingException)) { throw e; } } } + } - if (retrievedUserByEmail != null) { - user = retrievedUserByEmail; - } else { - // If no user was found with username or e-mail, a new one is created. - user = RodaCoreFactory.getModelService().createUser(newUser, true); + if ((user == null || user.equals(new User())) && attributes != null) { + // couldn't find user with username nor email, so create a new one + user = new User(username); + user = UserUtility.resetGroupsAndRoles(user); + + // try to set user email, full name and groups from cas principal attributes + mapCasStringAttribute(user, attributes, "fullname", (u, a) -> u.setFullName(a)); + mapCasStringAttribute(user, attributes, "email", (u, a) -> u.setEmail(a)); + mapCasSetAttribute(user, attributes, "memberOf", (u, a) -> u.setGroups(a)); + + user = RodaCoreFactory.getModelService().createUser(user, true); + } else { + // found user and authentication externally, so update user email, full name and + // groups from cas principal + // attributes if they have changed + if (attributes.get("email") instanceof String email && !user.getEmail().equals(attributes.get("email"))) { + user.setEmail(email); + } + if (attributes.get("fullname") instanceof String fullname + && !user.getFullName().equals(attributes.get("fullname"))) { + user.setFullName(fullname); } + if (attributes.get("memberOf") instanceof Collection memberOf) { + Set groups = new HashSet<>(); + for (Object group : memberOf) { + if (group instanceof String groupString) { + groups.add(groupString); + } + } + if (!user.getGroups().equals(groups)) { + user.setGroups(groups); + } + } + RodaCoreFactory.getModelService().updateUser(user, null, true); } if (!user.isActive()) { @@ -181,7 +207,7 @@ public static User casLoginHelper(final String username, final HttpServletReques return user; } - private static void mapCasAttribute(User user, Map attributes, String attributeKey, + private static void mapCasStringAttribute(User user, Map attributes, String attributeKey, BiConsumer mapping) { Object attributeValue = attributes.get(attributeKey); if (attributeValue instanceof String value) { @@ -189,6 +215,22 @@ private static void mapCasAttribute(User user, Map attributes, S } } + private static void mapCasSetAttribute(User user, Map attributes, String attributeKey, + BiConsumer> mapping) { + Object attributeValue = attributes.get(attributeKey); + Set newCollection = new HashSet<>(); + if (attributeValue instanceof Collection valueCollection) { + for (Object value : valueCollection) { + if (value instanceof String valueString) { + newCollection.add(valueString); + } + } + } else if (attributeValue instanceof String group) { + newCollection.add(group); + } + mapping.accept(user, newCollection); + } + @Override public User getUser(String name) { RequestContext requestContext = RequestUtils.parseHTTPRequest(request);