/* * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.agiletec.aps.system.services.authorization; import com.agiletec.aps.system.common.AbstractService; import com.agiletec.aps.system.common.entity.model.IApsEntity; import com.agiletec.aps.system.exception.ApsSystemException; import com.agiletec.aps.system.services.group.Group; import com.agiletec.aps.system.services.group.GroupUtilizer; import com.agiletec.aps.system.services.group.IGroupManager; import com.agiletec.aps.system.services.page.IPage; import com.agiletec.aps.system.services.role.IRoleManager; import com.agiletec.aps.system.services.role.Permission; import com.agiletec.aps.system.services.role.Role; import com.agiletec.aps.system.services.user.UserDetails; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Servizio di autorizzazione. Il servizio espone tutti i metodi necessari per * la verifica verifica delle autorizzazioni utente, qualsiasi sia la sua * provenienza e definizione. * @author E.Santoboni */ @Aspect public class AuthorizationManager extends AbstractService implements IAuthorizationManager, GroupUtilizer { private static final Logger _logger = LoggerFactory.getLogger(AuthorizationManager.class); @Override public void init() throws Exception { _logger.debug("{} ready", this.getClass().getName()); } @Override @Deprecated public boolean isAuth(UserDetails user, IApsAuthority auth) { return this.checkAuth(user, auth); } @Override public boolean isAuthOnGroupAndPermission(UserDetails user, String groupName, String permissionName, boolean chechAdmin) { if (null == user || null == groupName || null == permissionName) { return false; } List<Role> roles = new ArrayList<Role>(); List<Role> rolesWithPermission = this.getRoleManager().getRolesWithPermission(permissionName); if (null != rolesWithPermission) { roles.addAll(rolesWithPermission); } if (chechAdmin) { List<Role> rolesWithSupPermission = this.getRoleManager().getRolesWithPermission(Permission.SUPERUSER); if (null != rolesWithSupPermission) { roles.addAll(rolesWithSupPermission); } } for (int i = 0; i < roles.size(); i++) { Role role = roles.get(i); if (null != role) { boolean check = this.isAuthOnGroupAndRole(user, groupName, role.getName(), chechAdmin); if (check) { return true; } } } return false; } @Override public boolean isAuthOnGroupAndRole(UserDetails user, String groupName, String roleName, boolean chechAdmin) { if (null == user || (null == groupName && null == roleName)) { return false; } List<Authorization> userAuths = user.getAuthorizations(); for (int i = 0; i < userAuths.size(); i++) { Authorization userAuth = userAuths.get(i); if (null == userAuth) { continue; } Group group = userAuth.getGroup(); if ((null == group && null != groupName) || (null != group && null == groupName)) { continue; } else if (null != group && null != groupName) { if (!chechAdmin && !groupName.equals(group.getName())) { continue; } else if (chechAdmin && !Group.ADMINS_GROUP_NAME.equals(group.getName())) { continue; } } Role role = userAuth.getRole(); if (null == roleName) { return true; } else { boolean isSuper = role.hasPermission(Permission.SUPERUSER); if (role.getName().equals(roleName) || (chechAdmin && isSuper)) { return true; } } } return false; } @Override public List<IApsAuthority> getRelatedAuthorities(UserDetails user, IApsAuthority auth) { if (null == user || null == auth) { return null; } String requiredAuthName = auth.getAuthority(); boolean isRole = (auth instanceof Role); return (List<IApsAuthority>) this.getRelatedAuthorities(user, requiredAuthName, isRole); } private List getRelatedAuthorities(UserDetails user, String requiredAuthName, boolean isRole) { if (null == user || null == requiredAuthName || (isRole && null == this.getRoleManager().getRole(requiredAuthName)) || (!isRole && null == this.getGroupManager().getGroup(requiredAuthName))) { return null; } List<String> adminRoleNames = new ArrayList<String>(); if (isRole) { List<Role> adminRoles = this.getRolesWithPermission(user, Permission.SUPERUSER); if (null != adminRoles && !adminRoles.isEmpty()) { for (int i = 0; i < adminRoles.size(); i++) { Role role = adminRoles.get(i); if (null != role) { adminRoleNames.add(role.getName()); } } } } List authorities = new ArrayList<IApsAuthority>(); List<Authorization> userAuths = user.getAuthorizations(); for (int i = 0; i < userAuths.size(); i++) { Authorization userAuth = userAuths.get(i); if (null == userAuth) { continue; } if (!isRole && null != userAuth.getGroup() && (userAuth.getGroup().getName().equals(Group.ADMINS_GROUP_NAME) || requiredAuthName.equals(userAuth.getGroup().getAuthority()))) { authorities.add(userAuth.getRole()); } if (isRole && null != userAuth.getRole() && (adminRoleNames.contains(userAuth.getRole().getName()) || requiredAuthName.equals(userAuth.getRole().getAuthority()))) { if (userAuth.getGroup().getName().equals(Group.ADMINS_GROUP_NAME)) { return this.getGroupManager().getGroups(); } else { authorities.add(userAuth.getGroup()); } } } return authorities; } @Override public boolean isAuth(UserDetails user, Group group) { return this.isAuthOnGroup(user, group.getName()); } @Override public List<IApsAuthority> getAuthoritiesByGroup(UserDetails user, Group group) { return this.getRelatedAuthorities(user, group); } @Override public List<Role> getRolesByGroup(UserDetails user, Group group) { return this.getRelatedAuthorities(user, group.getName(), false); } @Override public boolean isAuth(UserDetails user, IApsEntity entity) { if (null == entity || null == user) { return false; } String mainGroupName = entity.getMainGroup(); if (mainGroupName.equals(Group.FREE_GROUP_NAME) || this.checkAuth(user, mainGroupName, false) || this.checkAuth(user, Group.ADMINS_GROUP_NAME, false)) { return true; } Set<String> groups = entity.getGroups(); return isAuth(user, groups); } @Override public boolean isAuth(UserDetails user, Set<String> groups) { if (null == user) { return false; } if (this.checkAuth(user, Group.ADMINS_GROUP_NAME, false)) { return true; } if (null == groups || groups.isEmpty()) { return false; } Iterator<String> iter = groups.iterator(); while (iter.hasNext()) { String groupName = iter.next(); if (groupName.equals(Group.FREE_GROUP_NAME) || this.checkAuth(user, groupName, false)) { return true; } } return false; } @Override public boolean isAuth(UserDetails user, Permission permission) { return this.isAuthOnPermission(user, permission.getName()); } @Override public List<IApsAuthority> getAuthoritiesByPermission(UserDetails user, Permission permission) { if (null == permission) { return null; } return this.getAuthoritiesByPermissionName(user, permission.getName()); } @Override public List<Group> getGroupsByPermission(UserDetails user, Permission permission) { if (null == permission) { return null; } return this.getGroupsByPermission(user, permission.getName()); } @Override public List<Group> getGroupsByPermission(UserDetails user, String permissionName) { if (null == user) { return null; } List<Group> groups = new ArrayList<Group>(); List<IApsAuthority> auths = this.getAuthoritiesByPermissionName(user, permissionName); for (int i = 0; i < auths.size(); i++) { IApsAuthority auth = auths.get(i); if (null != auth && auth instanceof Group) { String groupName = auth.getAuthority(); if (Group.ADMINS_GROUP_NAME.equals(groupName)) { return this.getGroupManager().getGroups(); } else { if (!groups.contains((Group) auth)) { groups.add((Group) auth); } } } } return groups; } private List getAuthoritiesByPermissionName(UserDetails user, String permissionName) { if (null == user) { return null; } if (null == permissionName) { return null; } List auths = new ArrayList(); this.addAuthoritiesByPermissionName(user, permissionName, auths); this.addAuthoritiesByPermissionName(user, Permission.SUPERUSER, auths); return auths; } private void addAuthoritiesByPermissionName(UserDetails user, String permissionName, List auths) { List<Role> roles = this.getRolesWithPermission(user, permissionName); for (int i = 0; i < roles.size(); i++) { Role role = roles.get(i); List groupAuths = this.getRelatedAuthorities(user, role); if (null != groupAuths) { auths.addAll(groupAuths); } } } @Override public boolean isAuth(UserDetails user, IPage page) { if (null == user) { return false; } if (this.isAuthOnGroup(user, Group.ADMINS_GROUP_NAME)) { return true; } String pageGroup = page.getGroup(); if (Group.FREE_GROUP_NAME.equals(pageGroup)) { return true; } boolean isAuthorized = this.isAuthOnGroup(user, pageGroup); if (isAuthorized) { return true; } Collection<String> extraGroups = page.getExtraGroups(); if (null != extraGroups && !extraGroups.isEmpty()) { if (extraGroups.contains(Group.FREE_GROUP_NAME)) { return true; } Iterator<String> iter = extraGroups.iterator(); while (iter.hasNext()) { String extraGroupName = iter.next(); if (this.isAuthOnGroup(user, extraGroupName)) { return true; } } } return false; } @Override public boolean isAuthOnGroup(UserDetails user, String groupName) { return ((this.checkAuth(user, groupName, false) || this.checkAuth(user, Group.ADMINS_GROUP_NAME, false))); } @Override public List<IApsAuthority> getAuthoritiesByGroup(UserDetails user, String groupName) { return this.getRelatedAuthorities(user, groupName, false); } @Override public List<Role> getRolesByGroup(UserDetails user, String groupName) { return this.getRelatedAuthorities(user, groupName, false); } @Override public boolean isAuthOnRole(UserDetails user, String roleName) { return ((this.isAuthOnPermission(user, Permission.SUPERUSER) || this.checkAuth(user, roleName, true))); } @Override public List<IApsAuthority> getAuthoritiesByRole(UserDetails user, String roleName) { return this.getRelatedAuthorities(user, roleName, true); } @Override public List<Group> getGroupsByRole(UserDetails user, String roleName) { return this.getRelatedAuthorities(user, roleName, true); } @Override public boolean isAuthOnPermission(UserDetails user, String permissionName) { boolean check = this.isAuthOnSinglePermission(user, permissionName); if (check) { return true; } return this.isAuthOnSinglePermission(user, Permission.SUPERUSER); } private boolean isAuthOnSinglePermission(UserDetails user, String permissionName) { if (null == user) { return false; } List<Role> rolesWithPermission = this.getRolesWithPermission(user, permissionName); for (int i = 0; i < rolesWithPermission.size(); i++) { Role role = rolesWithPermission.get(i); boolean check = this.checkAuth(user, role.getAuthority(), true); if (check) { return true; } } return false; } private List<Role> getRolesWithPermission(UserDetails user, String permissionName) { if (null == user) { return null; } List<Role> roles = new ArrayList<Role>(); List<Authorization> auths = user.getAuthorizations(); for (int i = 0; i < auths.size(); i++) { Authorization auth = auths.get(i); if (null == auth) { continue; } if (null != auth.getRole() && auth.getRole().hasPermission(permissionName)) { roles.add(auth.getRole()); } } return roles; } @Override @Deprecated public List<Group> getGroupsOfUser(UserDetails user) { return this.getUserGroups(user); } @Override public List<Group> getUserGroups(UserDetails user) { if (null == user) { return null; } List<Group> groups = new ArrayList<Group>(); List<Authorization> auths = user.getAuthorizations(); for (int i = 0; i < auths.size(); i++) { Authorization auth = auths.get(i); if (null != auth && null != auth.getGroup()) { String groupName = auth.getGroup().getName(); if (Group.ADMINS_GROUP_NAME.equals(groupName)) { return this.getGroupManager().getGroups(); } else { groups.add(auth.getGroup()); } } } return groups; } @Override public List<Role> getUserRoles(UserDetails user) { if (null == user) { return null; } List<Role> roles = new ArrayList<Role>(); List<Authorization> auths = user.getAuthorizations(); for (int i = 0; i < auths.size(); i++) { Authorization auth = auths.get(i); if (null != auth && null != auth.getRole()) { roles.add(auth.getRole()); } } return roles; } @Deprecated private boolean checkAuth(UserDetails user, IApsAuthority requiredAuth) { if (null == requiredAuth) { return false; } boolean isRole = (requiredAuth instanceof Role); String requiredAuthName = requiredAuth.getAuthority(); return this.checkAuth(user, requiredAuthName, isRole); } private boolean checkAuth(UserDetails user, String requiredAuthName, boolean isRole) { if (null == requiredAuthName) { return false; } List<Authorization> auths = user.getAuthorizations(); for (int i = 0; i < auths.size(); i++) { Authorization auth = auths.get(i); if (null == auth) { continue; } if (isRole && null != auth.getRole() && requiredAuthName.equals(auth.getRole().getAuthority())) { return true; } if (!isRole && null != auth.getGroup() && requiredAuthName.equals(auth.getGroup().getAuthority())) { return true; } } return false; } @Override public List<Authorization> getUserAuthorizations(String username) throws ApsSystemException { List<Authorization> authorizations = null; try { Map<String, Group> groups = (Map<String, Group>) this.getAuthorityMap(this.getGroupManager().getGroups()); Map<String, Role> roles = (Map<String, Role>) this.getAuthorityMap(this.getRoleManager().getRoles()); authorizations = this.getAuthorizationDAO().getUserAuthorizations(username, groups, roles); } catch (Throwable t) { _logger.error("Error extracting user authorizations for user '{}'", username, t); throw new ApsSystemException("Error extracting user authorizations for user " + username, t); } return authorizations; } private Map getAuthorityMap(List list) { Map<String, IApsAuthority> map = new HashMap<String, IApsAuthority>(); for (int i = 0; i < list.size(); i++) { IApsAuthority authority = (IApsAuthority) list.get(i); map.put(authority.getAuthority(), authority); } return map; } @Override public void addUserAuthorization(String username, String groupName, String roleName) throws ApsSystemException { try { Group group = (null != groupName) ? this.getGroupManager().getGroup(groupName) : null; if (null != groupName && null == group) { _logger.warn("invalid authorization - invalid referenced group name"); return; } Role role = (null != roleName) ? this.getRoleManager().getRole(roleName) : null; if (null != roleName && null == role) { _logger.warn("invalid authorization - invalid referenced role name"); return; } Authorization authorization = new Authorization(group, role); this.addUserAuthorization(username, authorization); } catch (Throwable t) { _logger.error("Error adding user authorization for user '{}'", username, t); throw new ApsSystemException("Error adding user authorization for user " + username, t); } } @Override public void addUserAuthorization(String username, Authorization authorization) throws ApsSystemException { if (null == username || null == authorization) { return; } try { if (this.checkAuthorization(authorization)) { this.getAuthorizationDAO().addUserAuthorization(username, authorization); } } catch (Throwable t) { _logger.error("Error adding user authorization for user '{}'", username, t); throw new ApsSystemException("Error adding user authorization for user " + username, t); } } @Override public void addUserAuthorizations(String username, List<Authorization> authorizations) throws ApsSystemException { if (null == username) { return; } try { List<Authorization> toAdd = this.checkAuthorizations(authorizations); if (null == toAdd) { return; } this.getAuthorizationDAO().addUserAuthorizations(username, toAdd); } catch (Throwable t) { _logger.error("Error adding user authorizations for user '{}'", username, t); throw new ApsSystemException("Error adding user authorizations for user " + username, t); } } @Override public void updateUserAuthorizations(String username, List<Authorization> authorizations) throws ApsSystemException { if (null == username) { return; } try { List<Authorization> toSet = this.checkAuthorizations(authorizations); if (null == toSet) { return; } this.getAuthorizationDAO().updateUserAuthorizations(username, toSet); } catch (Throwable t) { _logger.error("Error updating user authorizations for user '{}'", username, t); throw new ApsSystemException("Error updating user authorizations for user " + username, t); } } private List<Authorization> checkAuthorizations(List<Authorization> authorizations) throws Throwable { if (null == authorizations) { return null; } List<Authorization> checked = new ArrayList<Authorization>(); for (int i = 0; i < authorizations.size(); i++) { Authorization authorization = authorizations.get(i); if (this.checkAuthorization(authorization)) { checked.add(authorization); } } return checked; } private boolean checkAuthorization(Authorization authorization) throws Throwable { if (null == authorization) { _logger.warn("invalid authorization - null object"); return false; } String groupName = (null != authorization.getGroup()) ? authorization.getGroup().getName() : null; String roleName = (null != authorization.getRole()) ? authorization.getRole().getName() : null; if (null == roleName && null == groupName) { _logger.warn("invalid authorization - null group and role"); return false; } if (null != groupName && null == this.getGroupManager().getGroup(groupName)) { _logger.warn("invalid authorization - invalid referenced group"); return false; } if (null != roleName && null == this.getRoleManager().getRole(roleName)) { _logger.warn("invalid authorization - invalid referenced role"); return false; } return true; } @Override public void deleteUserAuthorization(String username, String groupname, String rolename) throws ApsSystemException { try { this.getAuthorizationDAO().deleteUserAuthorization(username, groupname, rolename); } catch (Throwable t) { _logger.error("Error deleting user authorization for user '{}'", username, t); throw new ApsSystemException("Error deleting user authorization for user " + username, t); } } @Override public void deleteUserAuthorizations(String username) throws ApsSystemException { try { this.getAuthorizationDAO().deleteUserAuthorizations(username); } catch (Throwable t) { _logger.error("Error deleting user authorizations for user '{}'", username, t); throw new ApsSystemException("Error deleting user authorizations for user " + username, t); } } @AfterReturning(pointcut = "execution(* com.agiletec.aps.system.services.user.IUserManager.removeUser(..)) && args(key)") public void deleteUser(Object key) { String username = null; if (key instanceof String) { username = key.toString(); } else if (key instanceof UserDetails) { UserDetails userDetails = (UserDetails) key; username = userDetails.getUsername(); } if (username != null) { try { this.deleteUserAuthorizations(username); } catch (Throwable t) { _logger.error("Error deleting user authorizations. user: {}", username, t); } } } @Override public List<String> getUsersByRole(IApsAuthority authority, boolean includeAdmin) throws ApsSystemException { if (null == authority || !(authority instanceof Role) || null == this.getRoleManager().getRole(authority.getAuthority())) { return null; } return this.getUsersByAuthorities(null, authority.getAuthority(), includeAdmin); } @Override public List<String> getUsersByRole(String roleName, boolean includeAdmin) throws ApsSystemException { Role role = this.getRoleManager().getRole(roleName); if (null == role) { return null; } return this.getUsersByAuthorities(null, roleName, includeAdmin); } @Override public List<String> getUsersByGroup(IApsAuthority authority, boolean includeAdmin) throws ApsSystemException { if (null == authority || !(authority instanceof Group) || null == this.getGroupManager().getGroup(authority.getAuthority())) { return null; } return this.getUsersByAuthorities(authority.getAuthority(), null, includeAdmin); } @Override public List<String> getUsersByGroup(String groupName, boolean includeAdmin) throws ApsSystemException { Group group = this.getGroupManager().getGroup(groupName); if (null == group) { return null; } return this.getUsersByAuthorities(groupName, null, includeAdmin); } @Override public List<String> getUsersByAuthorities(String groupName, String roleName, boolean includeAdmin) throws ApsSystemException { List<String> usernames = null; try { List<String> groupNames = null; if (!StringUtils.isEmpty(groupName)) { groupNames = new ArrayList<String>(); groupNames.add(groupName); if (includeAdmin && !groupName.equals(Group.ADMINS_GROUP_NAME)) { groupNames.add(Group.ADMINS_GROUP_NAME); } } List<String> roleNames = null; if (!StringUtils.isEmpty(roleName)) { roleNames = new ArrayList<String>(); roleNames.add(roleName); if (includeAdmin) { List<Role> adminRoles = this.getRoleManager().getRolesWithPermission(Permission.SUPERUSER); if (null != adminRoles) { for (int i = 0; i < adminRoles.size(); i++) { Role role = adminRoles.get(i); if (null != role && !roleNames.contains(role.getName())) { roleNames.add(role.getName()); } } } } } usernames = this.getAuthorizationDAO().getUsersByAuthorities(groupNames, roleNames); } catch (Throwable t) { _logger.error("Error extracting usernames by authorities - group '{}' : role {}", groupName, roleName, t); throw new ApsSystemException("Error extracting usernames by authorities", t); } return usernames; } @Override public List<String> getUsersByAuthority(IApsAuthority authority, boolean includeAdmin) throws ApsSystemException { if (authority instanceof Group) { return this.getUsersByGroup(authority, includeAdmin); } else { return this.getUsersByRole(authority, includeAdmin); } } @Override public List getGroupUtilizers(String groupName) throws ApsSystemException { return this.getUsersByGroup(groupName, false); } protected IAuthorizationDAO getAuthorizationDAO() { return _authorizationDAO; } public void setAuthorizationDAO(IAuthorizationDAO authorizationDAO) { this._authorizationDAO = authorizationDAO; } protected IRoleManager getRoleManager() { return _roleManager; } public void setRoleManager(IRoleManager roleManager) { this._roleManager = roleManager; } protected IGroupManager getGroupManager() { return _groupManager; } public void setGroupManager(IGroupManager groupManager) { this._groupManager = groupManager; } private IAuthorizationDAO _authorizationDAO; private IRoleManager _roleManager; private IGroupManager _groupManager; }