/*
* RHQ Management Platform
* Copyright (C) 2005-2011 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.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ejb.Stateless;
import javax.interceptor.ExcludeDefaultInterceptors;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.authz.Permission.Target;
import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.enterprise.server.RHQConstants;
/**
* @author Joseph Marques
*/
// we exclude the default interceptors because the required permissions interceptor calls into some of these
// and other methods that take a Subject may not have a session attached to that Subject
@ExcludeDefaultInterceptors
@Stateless
public class AuthorizationManagerBean implements AuthorizationManagerLocal {
private static final int SUBJECT_ID_OVERLORD = 1;
private static final int SUBJECT_ID_RHQADMIN = 2;
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityManager;
@Override
@SuppressWarnings("unchecked")
public Set<Permission> getExplicitGlobalPermissions(Subject subject) {
Query query = entityManager.createNamedQuery(Subject.QUERY_GET_GLOBAL_PERMISSIONS);
query.setParameter("subject", subject);
List<Permission> intermediate = query.getResultList();
Set<Permission> results = new HashSet<Permission>();
for (Permission permission : intermediate) {
if (permission.getTarget() == Target.GLOBAL) {
results.add(permission);
}
}
return results;
}
@Override
@SuppressWarnings("unchecked")
public Set<Permission> getExplicitGroupPermissions(Subject subject, int groupId) {
Set<Permission> result = new HashSet<Permission>();
ResourceGroup group = entityManager.find(ResourceGroup.class, groupId);
Subject owner = group.getSubject();
if (null == owner) {
// role-owned group
Query query = entityManager.createNamedQuery(Subject.QUERY_GET_PERMISSIONS_BY_GROUP_ID);
query.setParameter("subject", subject);
query.setParameter("groupId", groupId);
List<Permission> resultList = query.getResultList();
for (Permission permission : resultList) {
result.add(permission);
}
} else {
// don't let a user other than the owner do anything with this group
if (subject.equals(owner)) {
Query query = entityManager.createNamedQuery(Subject.QUERY_GET_PERMISSIONS_BY_PRIVATE_GROUP_ID);
query.setParameter("subjectId", subject.getId());
query.setParameter("privateGroupId", groupId);
List<Object[]> resultList = query.getResultList();
for (Object[] row : resultList) {
result.add((Permission) row[0]);
}
}
}
return result;
}
@Override
public Set<Permission> getImplicitGroupPermissions(Subject subject, int groupId) {
Set<Permission> permissions = isInventoryManager(subject) ? Permission.RESOURCE_ALL
: getExplicitGroupPermissions(subject, groupId);
return permissions;
}
@Override
@SuppressWarnings("unchecked")
public Set<Permission> getExplicitResourcePermissions(Subject subject, int resourceId) {
Query query = entityManager.createNamedQuery(Subject.QUERY_GET_PERMISSIONS_BY_RESOURCE_ID);
query.setParameter("subject", subject);
query.setParameter("resourceId", resourceId);
List<Permission> intermediate = query.getResultList();
Set<Permission> results = new HashSet<Permission>();
for (Permission permission : intermediate) {
results.add(permission);
}
return results;
}
@Override
public Set<Permission> getImplicitResourcePermissions(Subject subject, int resourceId) {
Set<Permission> permissions = isInventoryManager(subject) ? Permission.RESOURCE_ALL
: getExplicitResourcePermissions(subject, resourceId);
return permissions;
}
@Override
public boolean hasGlobalPermission(Subject subject, Permission permission) {
if (isOverlord(subject)) {
return true;
}
Query query = entityManager.createNamedQuery(Subject.QUERY_HAS_GLOBAL_PERMISSION);
query.setParameter("subject", subject);
query.setParameter("permission", permission);
long count = (Long) query.getSingleResult();
return (count != 0);
}
@Override
@SuppressWarnings("unchecked")
public boolean hasGroupPermission(Subject subject, Permission permission, int groupId) {
if (isInventoryManager(subject)) {
return true;
}
ResourceGroup group = entityManager.find(ResourceGroup.class, groupId);
Subject owner = group.getSubject();
if (null == owner) {
// role-owned group
Query query = entityManager.createNamedQuery(Subject.QUERY_HAS_GROUP_PERMISSION);
query.setParameter("subject", subject);
query.setParameter("permission", permission);
query.setParameter("groupId", groupId);
long count = (Long) query.getSingleResult();
return (count != 0);
} else {
// don't let a user other than the owner do anything with this group
if (!subject.equals(owner)) {
return false;
}
Query query = entityManager.createNamedQuery(Subject.QUERY_HAS_PRIVATE_GROUP_PERMISSION);
query.setParameter("subjectId", subject.getId());
query.setParameter("permission", permission);
query.setParameter("privateGroupId", groupId);
List<Object[]> resultList = query.getResultList();
return (!resultList.isEmpty());
}
}
@Override
public boolean hasResourcePermission(Subject subject, Permission permission, int resourceId) {
if (isInventoryManager(subject)) {
return true;
}
Query query = entityManager.createNamedQuery(Subject.QUERY_HAS_RESOURCE_PERMISSION);
query.setParameter("subject", subject);
query.setParameter("permission", permission);
query.setParameter("resourceId", resourceId);
long count = (Long) query.getSingleResult();
return (count != 0);
}
@SuppressWarnings("unchecked")
@Override
public boolean hasBundlePermission(Subject subject, Permission permission, int bundleId) {
Query query = entityManager.createNamedQuery(Subject.QUERY_HAS_BUNDLE_PERMISSION);
query.setParameter("subject", subject);
query.setParameter("permission", permission);
query.setParameter("bundleId", bundleId);
long count = (Long) query.getSingleResult();
return (count != 0);
}
@Override
@SuppressWarnings("unchecked")
public Set<Permission> getBundlePermissions(Subject subject, int bundleId) {
Query query = entityManager.createNamedQuery(Subject.QUERY_GET_PERMISSIONS_BY_BUNDLE_ID);
query.setParameter("subject", subject);
query.setParameter("bundleId", bundleId);
List<Permission> intermediate = query.getResultList();
Set<Permission> results = new HashSet<Permission>();
for (Permission permission : intermediate) {
results.add(permission);
}
return results;
}
@Override
@SuppressWarnings("unchecked")
public Set<Permission> getBundleGroupPermissions(Subject subject, int bundleGroupId) {
Query query = entityManager.createNamedQuery(Subject.QUERY_GET_PERMISSIONS_BY_BUNDLE_GROUP_ID);
query.setParameter("subject", subject);
query.setParameter("bundleGroupId", bundleGroupId);
List<Permission> intermediate = query.getResultList();
Set<Permission> results = new HashSet<Permission>();
for (Permission permission : intermediate) {
results.add(permission);
}
return results;
}
@Override
@SuppressWarnings("unchecked")
public boolean hasBundlePermission(Subject subject, Permission permission, Collection<Integer> bundleIds) {
if (isSystemSuperuser(subject)) {
return true;
}
Query query = entityManager.createNamedQuery(Subject.QUERY_GET_BUNDLES_BY_PERMISSION);
query.setParameter("subject", subject);
query.setParameter("permission", permission);
List<Integer> results = query.getResultList();
return results.containsAll(bundleIds);
}
@SuppressWarnings("unchecked")
@Override
public boolean hasBundleGroupPermission(Subject subject, Permission permission, int bundleGroupId) {
Query query = entityManager.createNamedQuery(Subject.QUERY_HAS_BUNDLE_GROUP_PERMISSION);
query.setParameter("subject", subject);
query.setParameter("permission", permission);
query.setParameter("bundleGroupId", bundleGroupId);
long count = (Long) query.getSingleResult();
return (count != 0);
}
@Override
public boolean hasAutoGroupPermission(Subject subject, Permission permission, int parentResourceId,
int resourceTypeId) {
if (isInventoryManager(subject)) {
return true;
}
Query query = entityManager.createNamedQuery(Subject.QUERY_HAS_AUTO_GROUP_PERMISSION);
query.setParameter("permission", permission);
query.setParameter("parentResourceId", parentResourceId);
query.setParameter("resourceTypeId", resourceTypeId);
query.setParameter("subjectId", -1);
long baseCount = (Long) query.getSingleResult();
query.setParameter("subjectId", subject.getId());
long subjectCount = (Long) query.getSingleResult();
/*
* an auto-group is viewable if the count of resources with parent/type filters is identical
* to the count of those same resources additionally filtered by standard authorization
*
*/
return (baseCount == subjectCount);
}
@Override
public boolean canViewResource(Subject subject, int resourceId) {
if (isInventoryManager(subject)) {
return true;
}
Query query = entityManager.createNamedQuery(Subject.QUERY_CAN_VIEW_RESOURCE);
query.setParameter("subject", subject);
query.setParameter("resourceId", resourceId);
long count = (Long) query.getSingleResult();
return (count != 0);
}
@Override
public boolean canViewResources(Subject subject, List<Integer> resourceIds) {
if (isInventoryManager(subject)) {
return true;
}
Query query = entityManager.createNamedQuery(Subject.QUERY_CAN_VIEW_RESOURCES);
query.setParameter("subject", subject);
query.setParameter("resourceIds", resourceIds);
long count = (Long) query.getSingleResult();
return count == resourceIds.size();
}
@Override
public boolean canViewGroup(Subject subject, int groupId) {
if (isInventoryManager(subject)) {
return true;
}
Query query = entityManager.createNamedQuery(Subject.QUERY_CAN_VIEW_GROUP);
query.setParameter("subject", subject);
query.setParameter("groupId", groupId);
long count = (Long) query.getSingleResult();
return (count != 0);
}
@Override
public boolean canViewAutoGroup(Subject subject, int parentResourceId, int resourceTypeId) {
if (isInventoryManager(subject)) {
return true;
}
Query query = entityManager.createNamedQuery(Subject.QUERY_CAN_VIEW_AUTO_GROUP);
query.setParameter("parentResourceId", parentResourceId);
query.setParameter("resourceTypeId", resourceTypeId);
query.setParameter("subjectId", -1);
long baseCount = (Long) query.getSingleResult();
query.setParameter("subjectId", subject.getId());
long subjectCount = (Long) query.getSingleResult();
/*
* an auto-group is viewable if the count of resources with parent/type filters is identical
* to the count of those same resources additionally filtered by standard authorization
*
*/
return (baseCount == subjectCount);
}
@Override
public boolean canViewBundle(Subject subject, int bundleId) {
if (hasGlobalPermission(subject, Permission.VIEW_BUNDLES)) {
return true;
}
Query query = entityManager.createNamedQuery(Subject.QUERY_CAN_VIEW_BUNDLE);
query.setParameter("subject", subject);
query.setParameter("bundleId", bundleId);
long count = (Long) query.getSingleResult();
return (count != 0);
}
@Override
public boolean canViewBundleGroup(Subject subject, int bundleGroupId) {
if (hasGlobalPermission(subject, Permission.VIEW_BUNDLES)) {
return true;
}
Query query = entityManager.createNamedQuery(Subject.QUERY_CAN_VIEW_BUNDLE_GROUP);
query.setParameter("subject", subject);
query.setParameter("bundleGroupId", bundleGroupId);
long count = (Long) query.getSingleResult();
return (count != 0);
}
@Override
public boolean isInventoryManager(Subject subject) {
return hasGlobalPermission(subject, Permission.MANAGE_INVENTORY);
}
@Override
@SuppressWarnings("unchecked")
public boolean hasResourcePermission(Subject subject, Permission permission, Collection<Integer> resourceIds) {
if (isInventoryManager(subject)) {
return true;
}
Query query = entityManager.createNamedQuery(Subject.QUERY_GET_RESOURCES_BY_PERMISSION);
query.setParameter("subject", subject);
query.setParameter("permission", permission);
List<Integer> results = query.getResultList();
return results.containsAll(resourceIds);
}
@Override
public boolean isSystemSuperuser(Subject subject) {
// We know that our overlord is always id=1 and the rhqadmin user is always id=2.
return (subject != null)
&& ((subject.getId() == SUBJECT_ID_OVERLORD) || (subject.getId() == SUBJECT_ID_RHQADMIN));
}
@Override
public boolean isOverlord(Subject subject) {
// We know that our overlord is always id=1.
return (subject != null) && (subject.getId() == SUBJECT_ID_OVERLORD);
}
@Override
public boolean canUpdateRepo(Subject subject, int repoId) {
if (hasGlobalPermission(subject, Permission.MANAGE_REPOSITORIES)) {
return true;
}
Query q = entityManager.createNamedQuery(Repo.QUERY_CHECK_REPO_OWNED_BY_SUBJECT_ID);
q.setParameter("repoId", repoId);
q.setParameter("subjectId", subject.getId());
Long num = (Long) q.getSingleResult();
return num > 0;
}
@Override
public boolean canViewRepo(Subject subject, int repoId) {
if (hasGlobalPermission(subject, Permission.MANAGE_REPOSITORIES)) {
return true;
}
Query q = entityManager.createNamedQuery(Repo.QUERY_CHECK_REPO_VISIBLE_BY_SUBJECT_ID);
q.setParameter("repoId", repoId);
q.setParameter("subjectId", subject.getId());
Long num = (Long) q.getSingleResult();
return num > 0;
}
}