/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.enterprise.server.authz;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.ExcludeDefaultInterceptors;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.authz.Role;
import org.rhq.core.domain.bundle.BundleGroup;
import org.rhq.core.domain.criteria.RoleCriteria;
import org.rhq.core.domain.resource.group.LdapGroup;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.server.PersistenceUtility;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.util.collection.ArrayUtils;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.alert.AlertNotificationManagerLocal;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.resource.group.LdapGroupManagerLocal;
import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
import org.rhq.enterprise.server.util.CriteriaQueryRunner;
/**
* This bean provides functionality to manipulate the security {@link Role role}s. That is, adding/modifying/deleting
* roles and their associated subjects and permissions is performed by this manager.
*
* @author John Mazzitelli
*/
@Stateless
public class RoleManagerBean implements RoleManagerLocal, RoleManagerRemote {
@SuppressWarnings("unused")
private final Log log = LogFactory.getLog(RoleManagerBean.class);
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityManager;
@EJB
private RoleManagerLocal roleManager; // self-referencing
@EJB
private SubjectManagerLocal subjectManager;
@EJB
private AuthorizationManagerLocal authorizationManager;
@EJB
//@IgnoreDependency
private AlertNotificationManagerLocal alertNotificationManager;
@EJB
//@IgnoreDependency
private LdapGroupManagerLocal ldapGroupManager;
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#findRolesBySubject(int subjectId,PageControl pageControl)
*/
@Override
@SuppressWarnings("unchecked")
// the first param, subject, is not the subject making the request, its the subject whose roles are to be returned.
// therefore, we won't want our security interceptor to check this method since the subject won't have a session associated with it
@ExcludeDefaultInterceptors
public PageList<Role> findRolesBySubject(int subjectId, PageControl pc) {
Subject subject = entityManager.find(Subject.class, subjectId); // attach it
PageList<Role> roles = PersistenceUtility.createPaginationFilter(entityManager, subject.getRoles(), pc);
if (roles != null) {
// eagerly load in the members - think about writing a left-join query or use EAGER
for (Role role : roles) {
role.getMemberCount();
}
}
return roles;
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#findRoles(PageControl)
*/
@Override
@SuppressWarnings("unchecked")
public PageList<Role> findRoles(PageControl pc) {
pc.initDefaultOrderingField("r.name");
String queryName = Role.QUERY_FIND_ALL;
Query queryCount = PersistenceUtility.createCountQuery(entityManager, queryName);
Query query = PersistenceUtility.createQueryWithOrderBy(entityManager, queryName, pc);
long count = (Long) queryCount.getSingleResult();
List<Role> roles = query.getResultList();
if (roles != null) {
// eagerly load in the members - can't use left-join due to PersistenceUtility usage; perhaps use EAGER
for (Role role : roles) {
role.getMemberCount();
}
} else {
roles = new ArrayList<Role>();
}
return new PageList<Role>(roles, (int) count, pc);
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#createRole(Subject, Role)
*/
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public Role createRole(Subject whoami, Role newRole) {
// Make sure there's not an existing role with the same name.
RoleCriteria criteria = new RoleCriteria();
criteria.addFilterName(newRole.getName());
criteria.setStrict(true);
PageList<Role> roles = findRolesByCriteria(whoami, criteria);
if (!roles.isEmpty()) {
throw new EntityExistsException("A user role [" + newRole.getName() + "] already exists.");
}
Boolean isSystemRole = newRole.getFsystem();
if (isSystemRole) {
throw new IllegalArgumentException("Unable to create system role [" + newRole.getName()
+ "] - new system roles cannot be created.");
}
processDependentPermissions(newRole);
Set<LdapGroup> ldapGroups = newRole.getLdapGroups();
for (LdapGroup ldapGroup : ldapGroups) {
ldapGroup.setRole(newRole);
}
entityManager.persist(newRole);
// Now we must merge subjects and resource groups, since those fields in Role do not have persist cascade
// enabled.
int[] subjectIds = new int[newRole.getSubjects().size()];
int i = 0;
for (Subject subject : newRole.getSubjects()) {
subjectIds[i++] = subject.getId();
}
addSubjectsToRole(whoami, newRole.getId(), subjectIds);
int[] resourceGroupIds = new int[newRole.getResourceGroups().size()];
i = 0;
for (ResourceGroup resourceGroup : newRole.getResourceGroups()) {
resourceGroupIds[i++] = resourceGroup.getId();
}
addResourceGroupsToRole(whoami, newRole.getId(), resourceGroupIds);
return newRole;
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#deleteRoles(Subject, int[])
*/
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void deleteRoles(Subject subject, int[] doomedRoleIds) {
if (doomedRoleIds != null) {
for (int roleId : doomedRoleIds) {
Role doomedRole = entityManager.find(Role.class, roleId);
//remove attached Subjects
Set<Subject> subjectsToUnhook = new HashSet<Subject>(doomedRole.getSubjects()); // avoid concurrent mod exception
for (Subject doomedSubjectRelationship : subjectsToUnhook) {
doomedRole.removeSubject(doomedSubjectRelationship);
entityManager.merge(doomedSubjectRelationship);
}
//remove attached ResourceGroups
Set<ResourceGroup> groupsToUnhook = new HashSet<ResourceGroup>(doomedRole.getResourceGroups()); // avoid concurrent mod exception
for (ResourceGroup doomedResourceGroupRelationship : groupsToUnhook) {
doomedRole.removeResourceGroup(doomedResourceGroupRelationship);
entityManager.merge(doomedResourceGroupRelationship);
}
//remove attached Bundle Groups
Set<BundleGroup> bundleGroupsToUnhook = new HashSet<BundleGroup>(doomedRole.getBundleGroups()); // avoid concurrent mod exception
for (BundleGroup doomedBundleGroupRelationship : bundleGroupsToUnhook) {
doomedRole.removeBundleGroup(doomedBundleGroupRelationship);
entityManager.merge(doomedBundleGroupRelationship);
}
//remove attached LDAP Subjects
Set<Subject> ldapSubjectsToUnhook = new HashSet<Subject>(doomedRole.getLdapSubjects()); // avoid concurrent mod exception
for (Subject doomedLdapSubjectRelationship : ldapSubjectsToUnhook) {
doomedRole.removeLdapSubject(doomedLdapSubjectRelationship);
entityManager.merge(doomedLdapSubjectRelationship);
}
doomedRole = entityManager.merge(doomedRole);
if (doomedRole.getFsystem()) {
throw new PermissionException("You cannot delete an internal system role");
}
alertNotificationManager.cleanseAlertNotificationByRole(doomedRole.getId());
// Fetch the lazy Sets on the Role to be returned.
//[BZ 754693:] we must fetch the lazy sets of LDAP Groups here for correct cascade removal
doomedRole.getResourceGroups().size();
doomedRole.getSubjects().size();
doomedRole.getLdapGroups().size();
entityManager.remove(doomedRole);
}
}
return;
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#addRolesToSubject(Subject, int, int[])
*/
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void addRolesToSubject(Subject subject, int subjectId, int[] roleIds) {
addRolesToSubject(subject, subjectId, roleIds, false);
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#addRolesToSubject(Subject, int, int[])
*/
@RequiredPermission(Permission.MANAGE_SECURITY)
public void addRolesToSubject(Subject subject, int subjectId, int[] roleIds, boolean isLdap) {
if (roleIds != null) {
Subject subjectToModify = subjectManager.getSubjectById(subjectId); // attach it
if (subjectToModify == null) {
throw new IllegalArgumentException("Could not find subject[" + subjectId + "] to add roles to");
}
if (subjectToModify.getFsystem() || (authorizationManager.isSystemSuperuser(subjectToModify))) {
throw new PermissionException("You cannot assign roles to user [" + subjectToModify.getName()
+ "] - roles are fixed for this user");
}
subjectToModify.getRoles().size();
for (Integer roleId : roleIds) {
Role role = entityManager.find(Role.class, roleId);
if (role == null) {
throw new IllegalArgumentException("Tried to add role[" + roleId + "] to subject[" + subjectId
+ "], but role was not found");
}
role.addSubject(subjectToModify);
if (isLdap) {
role.addLdapSubject(subjectToModify);
}
}
}
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#addSubjectsToRole(Subject, int, int[])
*/
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void addSubjectsToRole(Subject subject, int roleId, int[] subjectIds) {
if (subjectIds != null) {
Role role = getRoleById(roleId); // attach it
if (role == null) {
throw new IllegalArgumentException("Could not find role[" + roleId + "] to add subjects to");
}
for (Integer subjectId : subjectIds) {
Subject newSubject = entityManager.find(Subject.class, subjectId);
if (newSubject == null) {
throw new IllegalArgumentException("Tried to add subject[" + subjectId + "] to role[" + roleId
+ "], but subject was not found");
}
if (newSubject.getFsystem() || (authorizationManager.isSystemSuperuser(newSubject))) {
throw new PermissionException("You cannot alter the roles for user [" + newSubject.getName()
+ "] - roles are fixed for this user");
}
role.addSubject(newSubject);
}
}
return;
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#removeRolesFromSubject(Subject, int, int[])
*/
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void removeRolesFromSubject(Subject subject, int subjectId, int[] roleIds) {
if (roleIds != null) {
Subject subjectToModify = subjectManager.getSubjectById(subjectId); // attach it
if (subjectToModify.getFsystem() || (authorizationManager.isSystemSuperuser(subjectToModify))) {
throw new PermissionException("You cannot remove roles from user [" + subjectToModify.getName()
+ "] - roles are fixed for this user");
}
for (Integer roleId : roleIds) {
Role role = entityManager.find(Role.class, roleId);
if (role != null) {
role.removeSubject(subjectToModify);
}
}
}
return;
}
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void setAssignedSubjectRoles(Subject subject, int subjectId, int[] roleIds) {
Subject subjectToModify = subjectManager.getSubjectById(subjectId); // attach it
List<Integer> currentRoles = new ArrayList<Integer>();
for (Role role : subjectToModify.getRoles()) {
currentRoles.add(role.getId());
}
List<Integer> newRoles = ArrayUtils.wrapInList(roleIds); // members needing addition
newRoles.removeAll(currentRoles);
if (newRoles.size() > 0) {
int[] newRoleIds = new int[newRoles.size()];
int i = 0;
for (Integer id : newRoles) {
newRoleIds[i++] = id;
}
roleManager.addRolesToSubject(subject, subjectId, newRoleIds);
}
List<Integer> removedRoles = new ArrayList<Integer>(currentRoles); // members needing removal
removedRoles.removeAll(ArrayUtils.wrapInList(roleIds));
if (removedRoles.size() > 0) {
int[] removedRoleIds = new int[removedRoles.size()];
int i = 0;
for (Integer id : removedRoles) {
removedRoleIds[i++] = id;
}
roleManager.removeRolesFromSubject(subject, subjectId, removedRoleIds);
}
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#getRoleById(Integer)
*/
@Override
public Role getRoleById(Integer roleId) {
Role role = entityManager.find(Role.class, roleId);
return role;
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#setPermissions(Subject, Integer, Set)
*/
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void setPermissions(Subject subject, Integer roleId, Set<Permission> permissions) {
Role role = entityManager.find(Role.class, roleId);
Set<Permission> rolePermissions = role.getPermissions();
rolePermissions.clear();
rolePermissions.addAll(permissions);
entityManager.merge(role);
entityManager.flush();
return;
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#getPermissions(Integer)
*/
@Override
public Set<Permission> getPermissions(Integer roleId) {
Role role = entityManager.find(Role.class, roleId);
Set<Permission> rolePermissions = role.getPermissions();
return rolePermissions;
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#updateRole(Subject, Role)
*/
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public Role updateRole(Subject whoami, Role role) {
Role attachedRole = entityManager.find(Role.class, role.getId());
if (attachedRole == null) {
throw new IllegalStateException("Cannot update " + role + ", since no role exists with that id.");
}
// First update the simple fields and the permissions.
attachedRole.setName(role.getName());
attachedRole.setDescription(role.getDescription());
attachedRole.setPermissions(role.getPermissions());
processDependentPermissions(attachedRole);
// Then update the subjects, resourceGroups, ldapGroups, and/or bundle groups, but only if those fields are
// non-null on the passed-in Role.
Set<Subject> newSubjects = role.getSubjects();
if (newSubjects != null) {
Set<Subject> currentSubjects = attachedRole.getSubjects();
// wrap in new HashSet to avoid ConcurrentModificationExceptions.
Set<Subject> subjectsToRemove = new HashSet<Subject>(currentSubjects);
for (Subject subject : currentSubjects) {
// Never remove a system user.
if (subject.getFsystem()) {
subjectsToRemove.remove(subject);
}
}
for (Subject subject : subjectsToRemove) {
attachedRole.removeSubject(subject);
}
for (Subject subject : newSubjects) {
Subject attachedSubject = entityManager.find(Subject.class, subject.getId());
attachedRole.addSubject(attachedSubject);
}
}
Set<ResourceGroup> newResourceGroups = role.getResourceGroups();
if (newResourceGroups != null) {
// wrap in new HashSet to avoid ConcurrentModificationExceptions.
Set<ResourceGroup> currentResourceGroups = new HashSet<ResourceGroup>(attachedRole.getResourceGroups());
for (ResourceGroup resourceGroup : currentResourceGroups) {
attachedRole.removeResourceGroup(resourceGroup);
}
for (ResourceGroup resourceGroup : newResourceGroups) {
ResourceGroup attachedResourceGroup = entityManager.find(ResourceGroup.class, resourceGroup.getId());
attachedRole.addResourceGroup(attachedResourceGroup);
}
}
Set<LdapGroup> newLdapGroups = role.getLdapGroups();
if (newLdapGroups != null) {
// wrap in new HashSet to avoid ConcurrentModificationExceptions.
Set<LdapGroup> currentLdapGroups = new HashSet<LdapGroup>(attachedRole.getLdapGroups());
for (LdapGroup ldapGroup : currentLdapGroups) {
// Delete removed groups
if (!newLdapGroups.contains(ldapGroup)) {
attachedRole.removeLdapGroup(ldapGroup);
entityManager.remove(ldapGroup);
}
}
// Add new groups, but filter those that are still attached
for (LdapGroup ldapGroup : newLdapGroups) {
LdapGroup attachedLdapGroup = (ldapGroup.getId() != 0) ? entityManager.find(LdapGroup.class,
ldapGroup.getId()) : null;
if (attachedLdapGroup == null && !currentLdapGroups.contains(ldapGroup)) {
ldapGroup.setRole(attachedRole);
entityManager.persist(ldapGroup);
attachedLdapGroup = ldapGroup;
}
if (attachedLdapGroup!=null) {
attachedRole.addLdapGroup(attachedLdapGroup);
}
}
}
Set<BundleGroup> newBundleGroups = role.getBundleGroups();
if (newBundleGroups != null) {
// wrap in new HashSet to avoid ConcurrentModificationExceptions.
Set<BundleGroup> currentBundleGroups = attachedRole.getBundleGroups();
Set<BundleGroup> bundleGroupsToRemove = new HashSet<BundleGroup>(currentBundleGroups);
for (BundleGroup bg : newBundleGroups) {
bundleGroupsToRemove.remove(bg);
}
for (BundleGroup bg : bundleGroupsToRemove) {
attachedRole.removeBundleGroup(bg);
}
for (BundleGroup bg : newBundleGroups) {
BundleGroup attachedBundleGroup = entityManager.find(BundleGroup.class, bg.getId());
attachedRole.addBundleGroup(attachedBundleGroup);
}
}
// Fetch the lazy Sets on the Role to be returned.
attachedRole.getResourceGroups().size();
attachedRole.getSubjects().size();
attachedRole.getLdapGroups().size();
attachedRole.getBundleGroups().size();
return attachedRole;
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#findSubjectsByRole(Integer roleId,PageControl pageControl)
*/
public PageList<Subject> findSubjectsByRole(Subject subject, Integer roleId, PageControl pc) {
return findSubjectsByRole(roleId, pc);
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#findSubjectsByRole(Integer,PageControl)
*/
@Override
@SuppressWarnings("unchecked")
public PageList<Subject> findSubjectsByRole(Integer roleId, PageControl pc) {
pc.initDefaultOrderingField("s.name");
String queryName = Subject.QUERY_GET_SUBJECTS_ASSIGNED_TO_ROLE;
Query queryCount = PersistenceUtility.createCountQuery(entityManager, queryName);
Query query = PersistenceUtility.createQueryWithOrderBy(entityManager, queryName, pc);
queryCount.setParameter("id", roleId);
query.setParameter("id", roleId);
long count = (Long) queryCount.getSingleResult();
List<Subject> subjects = query.getResultList();
return new PageList<Subject>(subjects, (int) count, pc);
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#findRolesByIds(Integer[],PageControl)
*/
@Override
@SuppressWarnings("unchecked")
public PageList<Role> findRolesByIds(Integer[] roleIds, PageControl pc) {
if ((roleIds == null) || (roleIds.length == 0)) {
return new PageList<Role>(pc);
}
pc.initDefaultOrderingField("r.name");
String queryName = Role.QUERY_FIND_BY_IDS;
Query queryCount = PersistenceUtility.createCountQuery(entityManager, queryName);
Query query = PersistenceUtility.createQueryWithOrderBy(entityManager, queryName, pc);
List<Integer> roleIdsList = Arrays.asList(roleIds);
queryCount.setParameter("ids", roleIdsList);
query.setParameter("ids", roleIdsList);
long count = (Long) queryCount.getSingleResult();
List<Role> roles = query.getResultList();
// eagerly load in the members - can't use left-join due to PersistenceUtility usage; perhaps use EAGER
for (Role role : roles) {
role.getMemberCount();
}
return new PageList<Role>(roles, (int) count, pc);
}
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
@SuppressWarnings("unchecked")
public PageList<Role> findAvailableRolesForSubject(Subject subject, Integer subjectId, Integer[] pendingRoleIds,
PageControl pc) {
pc.initDefaultOrderingField("r.name");
String queryName;
if ((pendingRoleIds == null) || (pendingRoleIds.length == 0)) {
queryName = Role.QUERY_FIND_AVAILABLE_ROLES;
} else {
queryName = Role.QUERY_FIND_AVAILABLE_ROLES_WITH_EXCLUDES;
}
Query queryCount = PersistenceUtility.createCountQuery(entityManager, queryName, "distinct r");
Query query = PersistenceUtility.createQueryWithOrderBy(entityManager, queryName, pc);
queryCount.setParameter("subjectId", subjectId);
query.setParameter("subjectId", subjectId);
if ((pendingRoleIds != null) && (pendingRoleIds.length > 0)) {
List<Integer> pendingIdsList = Arrays.asList(pendingRoleIds);
queryCount.setParameter("excludes", pendingIdsList);
query.setParameter("excludes", pendingIdsList);
}
long count = (Long) queryCount.getSingleResult();
List<Role> roles = query.getResultList();
// eagerly load in the members - can't use left-join due to PersistenceUtility usage; perhaps use EAGER
for (Role role : roles) {
role.getMemberCount();
}
return new PageList<Role>(roles, (int) count, pc);
}
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public PageList<Role> findSubjectUnassignedRoles(Subject subject, int subjectId, PageControl pc) {
return findAvailableRolesForSubject(subject, subjectId, null, pc);
}
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void addBundleGroupsToRole(Subject subject, int roleId, int[] bundleGroupIds) {
if ((bundleGroupIds != null) && (bundleGroupIds.length > 0)) {
Role role = entityManager.find(Role.class, roleId);
if (role == null) {
throw new IllegalArgumentException("Could not find role[" + roleId + "] in order to add resourceGroups");
}
role.getBundleGroups().size(); // load them in
for (Integer bundleGroupId : bundleGroupIds) {
BundleGroup bundleGroup = entityManager.find(BundleGroup.class, bundleGroupId);
if (bundleGroup == null) {
throw new IllegalArgumentException("Tried to add BundleGroup[" + bundleGroupId + "] to role["
+ roleId + "], but bundleGroup was not found.");
}
role.addBundleGroup(bundleGroup);
}
}
return;
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#addResourceGroupsToRole(Subject, int, int[])
*/
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void addResourceGroupsToRole(Subject subject, int roleId, int[] groupIds) {
if ((groupIds != null) && (groupIds.length > 0)) {
Role role = entityManager.find(Role.class, roleId);
if (role == null) {
throw new IllegalArgumentException("Could not find role[" + roleId + "] to add resourceGroups to");
}
role.getResourceGroups().size(); // load them in
for (Integer groupId : groupIds) {
ResourceGroup group = entityManager.find(ResourceGroup.class, groupId);
if (group == null) {
throw new IllegalArgumentException("Tried to add resourceGroup[" + groupId + "] to role[" + roleId
+ "], but resourceGroup was not found.");
}
role.addResourceGroup(group);
}
}
return;
}
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void removeBundleGroupsFromRole(Subject subject, int roleId, int[] bundleGroupIds) {
if ((bundleGroupIds != null) && (bundleGroupIds.length > 0)) {
Role role = entityManager.find(Role.class, roleId);
if (role == null) {
throw new IllegalArgumentException("Could not find role[" + roleId
+ "] in order to remove BundleGroups");
}
role.getBundleGroups().size(); // load them in
for (Integer bundleGroupId : bundleGroupIds) {
BundleGroup bundleGroup = entityManager.find(BundleGroup.class, bundleGroupId);
if (bundleGroup == null) {
throw new IllegalArgumentException("Tried to remove BundleGroup[" + bundleGroupId + "] from role["
+ roleId + "], but BundleGroup was not found");
}
role.removeBundleGroup(bundleGroup);
}
}
}
/**
* @see org.rhq.enterprise.server.authz.RoleManagerLocal#removeResourceGroupsFromRole(Subject, int, int[])
*/
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void removeResourceGroupsFromRole(Subject subject, int roleId, int[] groupIds) {
if ((groupIds != null) && (groupIds.length > 0)) {
Role role = entityManager.find(Role.class, roleId);
if (role == null) {
throw new IllegalArgumentException("Could not find role[" + roleId + "] to remove resourceGroups from");
}
role.getResourceGroups().size(); // load them in
for (Integer groupId : groupIds) {
ResourceGroup doomedGroup = entityManager.find(ResourceGroup.class, groupId);
if (doomedGroup == null) {
throw new IllegalArgumentException("Tried to remove doomedGroup[" + groupId + "] from role["
+ roleId + "], but subject was not found");
}
role.removeResourceGroup(doomedGroup);
}
}
}
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void setAssignedBundleGroups(Subject subject, int roleId, int[] bundleGroupIds) {
Role role = getRole(subject, roleId);
List<Integer> currentBundleGroups = new ArrayList<Integer>();
for (BundleGroup group : role.getBundleGroups()) {
currentBundleGroups.add(group.getId());
}
List<Integer> newBundleGroups = ArrayUtils.wrapInList(bundleGroupIds); // members needing addition
newBundleGroups.removeAll(currentBundleGroups);
int[] newBundleGroupIds = ArrayUtils.unwrapCollection(newBundleGroups);
roleManager.addBundleGroupsToRole(subject, roleId, newBundleGroupIds);
List<Integer> removedBundleGroups = new ArrayList<Integer>(currentBundleGroups); // members needing removal
removedBundleGroups.removeAll(ArrayUtils.wrapInList(bundleGroupIds));
int[] removedGroupIds = ArrayUtils.unwrapCollection(removedBundleGroups);
roleManager.removeBundleGroupsFromRole(subject, roleId, removedGroupIds);
}
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void setAssignedResourceGroups(Subject subject, int roleId, int[] groupIds) {
Role role = getRole(subject, roleId);
List<Integer> currentGroups = new ArrayList<Integer>();
for (ResourceGroup group : role.getResourceGroups()) {
currentGroups.add(group.getId());
}
List<Integer> newGroups = ArrayUtils.wrapInList(groupIds); // members needing addition
newGroups.removeAll(currentGroups);
int[] newGroupIds = ArrayUtils.unwrapCollection(newGroups);
roleManager.addResourceGroupsToRole(subject, roleId, newGroupIds);
List<Integer> removedGroups = new ArrayList<Integer>(currentGroups); // members needing removal
removedGroups.removeAll(ArrayUtils.wrapInList(groupIds));
int[] removedGroupIds = ArrayUtils.unwrapCollection(removedGroups);
roleManager.removeResourceGroupsFromRole(subject, roleId, removedGroupIds);
}
private void processDependentPermissions(Role role) {
/*
* if you can control user/roles, then you can give yourself permissions, too; so we might as well
* automagically give all permissions to users that are explicitly given the MANAGE_SECURITY permission
*/
if (role.getPermissions().contains(Permission.MANAGE_SECURITY)) {
role.getPermissions().addAll(EnumSet.allOf(Permission.class));
}
/*
* similarly, MANAGE_INVENTORY implies all Resource perms
*/
if (role.getPermissions().contains(Permission.MANAGE_INVENTORY)) {
role.getPermissions().addAll(Permission.RESOURCE_ALL);
}
/*
* write-access implies read-access
*/
if (role.getPermissions().contains(Permission.CONFIGURE_WRITE)) {
role.getPermissions().add(Permission.CONFIGURE_READ);
}
/*
* and lack of read-access implies lack of write-access
*/
if (!role.getPermissions().contains(Permission.CONFIGURE_READ)) {
role.getPermissions().remove(Permission.CONFIGURE_WRITE);
}
/*
* and MANAGE_BUNDLE implies all Bundle perms
*/
if (role.getPermissions().contains(Permission.MANAGE_BUNDLE)) {
role.getPermissions().addAll(Permission.BUNDLE_ALL);
}
/*
* and MANAGE_BUNDLE_GROUPS implies global bundle view
*/
if (role.getPermissions().contains(Permission.MANAGE_BUNDLE_GROUPS)) {
role.getPermissions().add(Permission.VIEW_BUNDLES);
}
}
@Override
public PageList<Role> findSubjectAssignedRoles(Subject subject, int subjectId, PageControl pc) {
PageList<Role> assignedRoles = findRolesBySubject(subjectId, pc);
return assignedRoles;
}
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void removeSubjectsFromRole(Subject subject, int roleId, int[] subjectIds) {
if ((subjectIds != null) && (subjectIds.length > 0)) {
Role role = entityManager.find(Role.class, roleId);
if (role == null) {
throw new IllegalArgumentException("Could not find role[" + roleId + "] to remove subjects from");
}
role.getSubjects().size(); // load them in
for (Integer subjectId : subjectIds) {
Subject doomedSubject = entityManager.find(Subject.class, subjectId);
if (doomedSubject == null) {
throw new IllegalArgumentException("Tried to remove subject[" + subjectId + "] from role[" + roleId
+ "], but subject was not found");
}
if (doomedSubject.getFsystem() || (authorizationManager.isSystemSuperuser(doomedSubject))) {
throw new PermissionException("You cannot remove user[" + doomedSubject.getName() + "] from role["
+ roleId + "] - roles are fixed for this user");
}
role.removeSubject(doomedSubject);
}
}
}
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void setAssignedSubjects(Subject subject, int roleId, int[] subjectIds) {
Role role = getRole(subject, roleId);
List<Integer> currentSubjects = new ArrayList<Integer>();
for (Subject currentSubject : role.getSubjects()) {
currentSubjects.add(currentSubject.getId());
}
List<Integer> newSubjects = ArrayUtils.wrapInList(subjectIds); // members needing addition
newSubjects.removeAll(currentSubjects);
if (newSubjects.size() > 0) {
int[] newSubjectIds = new int[newSubjects.size()];
int i = 0;
for (Integer id : newSubjects) {
newSubjectIds[i++] = id;
}
roleManager.addSubjectsToRole(subject, roleId, newSubjectIds);
}
List<Integer> removedSubjects = new ArrayList<Integer>(currentSubjects); // members needing removal
removedSubjects.removeAll(ArrayUtils.wrapInList(subjectIds));
if (removedSubjects.size() > 0) {
int[] removedSubjectIds = new int[removedSubjects.size()];
int i = 0;
for (Integer id : removedSubjects) {
removedSubjectIds[i++] = id;
}
roleManager.removeSubjectsFromRole(subject, roleId, removedSubjectIds);
}
}
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void removeRolesFromBundleGroup(Subject subject, int bundleGroupId, int[] roleIds) {
if ((roleIds != null) && (roleIds.length > 0)) {
BundleGroup bundleGroup = entityManager.find(BundleGroup.class, bundleGroupId);
if (bundleGroup == null) {
throw new IllegalArgumentException("Could not find BundleGroup[" + bundleGroupId
+ "] in order to remove roles");
}
bundleGroup.getRoles().size(); // load them in
for (Integer roleId : roleIds) {
Role doomedRole = entityManager.find(Role.class, roleId);
if (doomedRole == null) {
throw new IllegalArgumentException("Tried to remove role[" + roleId + "] from BundleGroup["
+ bundleGroupId + "], but role was not found");
}
doomedRole.removeBundleGroup(bundleGroup);
}
}
return;
}
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void removeRolesFromResourceGroup(Subject subject, int groupId, int[] roleIds) {
if ((roleIds != null) && (roleIds.length > 0)) {
ResourceGroup group = entityManager.find(ResourceGroup.class, groupId);
if (group == null) {
throw new IllegalArgumentException("Could not find resourceGroup[" + groupId + "] to remove roles from");
}
group.getRoles().size(); // load them in
for (Integer roleId : roleIds) {
Role doomedRole = entityManager.find(Role.class, roleId);
if (doomedRole == null) {
throw new IllegalArgumentException("Tried to remove role[" + roleId + "] from resourceGroup["
+ groupId + "], but role was not found");
}
group.removeRole(doomedRole);
}
}
return;
}
@Override
public Role getRole(Subject subject, int roleId) {
return entityManager.find(Role.class, roleId);
}
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void addRolesToBundleGroup(Subject subject, int bundleGroupId, int[] roleIds) {
if ((roleIds != null) && (roleIds.length > 0)) {
BundleGroup bundleGroup = entityManager.find(BundleGroup.class, bundleGroupId);
if (bundleGroup == null) {
throw new IllegalArgumentException("Could not find bundleGroup[" + bundleGroupId
+ "] in order to add roles");
}
bundleGroup.getRoles().size(); // load them in
for (Integer roleId : roleIds) {
Role role = entityManager.find(Role.class, roleId);
if (role == null) {
throw new IllegalArgumentException("Tried to add role[" + roleId + "] to bundleGroup["
+ bundleGroupId + "], but role was not found");
}
role.addBundleGroup(bundleGroup);
}
}
return;
}
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public void addRolesToResourceGroup(Subject subject, int groupId, int[] roleIds) {
if ((roleIds != null) && (roleIds.length > 0)) {
ResourceGroup group = entityManager.find(ResourceGroup.class, groupId);
if (group == null) {
throw new IllegalArgumentException("Could not find resourceGroup[" + groupId + "] to add roles to");
}
group.getRoles().size(); // load them in
for (Integer roleId : roleIds) {
Role role = entityManager.find(Role.class, roleId);
if (role == null) {
throw new IllegalArgumentException("Tried to add role[" + roleId + "] to resourceGroup[" + groupId
+ "], but role was not found");
}
group.addRole(role);
}
}
return;
}
@Override
@SuppressWarnings("unchecked")
public PageList<Role> findRolesByCriteria(Subject subject, RoleCriteria criteria) {
if (criteria.isSecurityManagerRequired()
&& !authorizationManager.hasGlobalPermission(subject, Permission.MANAGE_SECURITY)) {
throw new PermissionException("Subject [" + subject.getName()
+ "] requires SecurityManager permission for requested query criteria.");
}
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
CriteriaQueryRunner<Role> queryRunner = new CriteriaQueryRunner<Role>(criteria, generator, entityManager);
PageList<Role> roles = queryRunner.execute();
return roles;
}
}