/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.security.impl; import java.io.IOException; import java.util.Collection; import java.util.HashSet; import java.util.Properties; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.geoserver.security.GeoServerRoleService; import org.geoserver.security.GeoServerUserGroupService; /** * Helper Object for role calculations * * @author christian * */ public class RoleCalculator { protected GeoServerRoleService roleService; protected GeoServerUserGroupService userGroupService; /** * Constructor * * @param roleService */ public RoleCalculator (GeoServerRoleService roleService) { this(null,roleService); } /** * Constructor * * @param userGroupService * @param roleService */ public RoleCalculator (GeoServerUserGroupService userGroupService,GeoServerRoleService roleService) { this.userGroupService=userGroupService; this.roleService=roleService; assertRoleServiceNotNull(); } public void setRoleService(GeoServerRoleService service) { roleService=service; assertRoleServiceNotNull(); } public GeoServerRoleService getRoleService() { return roleService; } public void setUserGroupService(GeoServerUserGroupService service) { userGroupService=service; } public GeoServerUserGroupService getUserGroupService() { return userGroupService; } /** * Check if the role service is not null * */ protected void assertRoleServiceNotNull() { if (roleService==null) { throw new RuntimeException("role service Service is null"); } } /** * Convenience method for {@link #calculateRoles(GeoServerUser)} * * @param username * * @throws IOException */ public SortedSet<GeoServerRole> calculateRoles(String username) throws IOException { return calculateRoles(new GeoServerUser(username)); } /** * Calculate the {@link GeoServerRole} objects for a user * * The algorithm * * get the roles directly assigned to the user * get the groups of the user if a {@link GeoServerUserGroupService} service * is given, for each "enabled" group, add the roles of the group * * * for earch role search for ancestor roles and * add them to the set * * After role calculation has finished, personalize each * role with role attributes if necessary * * If the user has the admin role of the active role service, * {@link GeoServerRole#ADMIN_ROLE} is also included in the set. * * @param user * * @throws IOException */ public SortedSet<GeoServerRole> calculateRoles(GeoServerUser user) throws IOException { Set<GeoServerRole> set1 = new HashSet<GeoServerRole>(); // alle roles for the user set1.addAll(getRoleService().getRolesForUser(user.getUsername())); addInheritedRoles(set1); // add all roles for enabled groups if (getUserGroupService()!=null) { for (GeoServerUserGroup group : getUserGroupService().getGroupsForUser(user)) { if (group.isEnabled()) set1.addAll(calculateRoles(group)); } } // personalize roles SortedSet<GeoServerRole> set2 = personalizeRoles(user, set1); // add mapped system roles addMappedSystemRoles(set2); return set2; } public void addMappedSystemRoles(Collection<GeoServerRole> set) { // if the user has the admin role of the role service the // GeoserverRole.ADMIN_ROLE must also be in the set GeoServerRole adminRole = roleService.getAdminRole(); if (adminRole!=null && set.contains(adminRole)) { set.add(GeoServerRole.ADMIN_ROLE); } // if the user has the group admin role of the role service the // GeoserverRole.ADMIN_ROLE must also be in the set GeoServerRole groupAdminRole = roleService.getGroupAdminRole(); if (groupAdminRole!=null && set.contains(groupAdminRole)) { set.add(GeoServerRole.GROUP_ADMIN_ROLE); } } /** * Collects the ascendents for a {@link GeoServerRole} object * * @param role * @param inherited */ protected void addParentRole(GeoServerRole role,Collection<GeoServerRole> inherited) throws IOException{ GeoServerRole parentRole = getRoleService().getParentRole(role); if (parentRole==null) return; // end of recursion if (inherited.contains(parentRole)) return; // end of recursion inherited.add(parentRole); // recursion addParentRole(parentRole, inherited); } /** * Calculate the {@link GeoServerRole} objects for a group * including inherited roles * * @param group * * @throws IOException */ public SortedSet<GeoServerRole> calculateRoles(GeoServerUserGroup group) throws IOException { SortedSet<GeoServerRole> roles = new TreeSet<GeoServerRole>(); roles.addAll(getRoleService().getRolesForGroup(group.getGroupname())); addInheritedRoles(roles); return roles; } /** * Adds inherited roles to a role set * * @param coll * @throws IOException */ public void addInheritedRoles(Collection<GeoServerRole> coll) throws IOException { Set<GeoServerRole> inherited = new HashSet<GeoServerRole>(); for (GeoServerRole role : coll) addParentRole(role, inherited); coll.addAll(inherited); } /** * Takes the role set for a user and * personalizes the roles (matching user properties * and role parameters) * * @param user * @param roles * * @throws IOException */ public SortedSet<GeoServerRole> personalizeRoles(GeoServerUser user, Collection<GeoServerRole> roles) throws IOException{ SortedSet<GeoServerRole> set = new TreeSet<GeoServerRole>(); for (GeoServerRole role : roles) { Properties personalizedProps = getRoleService().personalizeRoleParams( role.getAuthority(), role.getProperties(), user.getUsername(), user.getProperties()); if (personalizedProps==null) { set.add(role); } else { // create personalized role GeoServerRole pRole = getRoleService().createRoleObject(role.getAuthority()); pRole.setUserName(user.getUsername()); for (Object key : personalizedProps.keySet()) pRole.getProperties().put(key, personalizedProps.get(key)); set.add(pRole); } } return set; } }