org.picketlink.idm.internal.PrivilegeChainQuery Maven / Gradle / Ivy
package org.picketlink.idm.internal;
import org.picketlink.common.properties.Property;
import org.picketlink.common.properties.query.AnnotatedPropertyCriteria;
import org.picketlink.common.properties.query.NamedPropertyCriteria;
import org.picketlink.common.properties.query.PropertyQueries;
import org.picketlink.common.properties.query.TypedPropertyCriteria;
import org.picketlink.common.util.StringUtil;
import org.picketlink.idm.RelationshipManager;
import org.picketlink.idm.model.IdentityType;
import org.picketlink.idm.model.Relationship;
import org.picketlink.idm.model.annotation.InheritsPrivileges;
import org.picketlink.idm.query.RelationshipQuery;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.picketlink.idm.IDMInternalMessages.MESSAGES;
/**
* Stores privilege chain metadata and performs chain queries to determine privilege inheritance
*
* @author Shane Bryzak
*/
public class PrivilegeChainQuery {
/**
* A mapping between a Relationship class and a set of chains that determine privilege inheritance. The Set contains
* mappings between the privileged identity property and the inherited identity property.
*/
private final Map,Map,Property>> privilegeChains =
new HashMap, Map,Property>>();
public void registerRelationshipType(Class extends Relationship> relationshipType) {
if (!privilegeChains.containsKey(relationshipType)) {
List> properties = PropertyQueries.createQuery(relationshipType)
.addCriteria(new AnnotatedPropertyCriteria(InheritsPrivileges.class))
.addCriteria(new TypedPropertyCriteria(IdentityType.class, TypedPropertyCriteria.MatchOption.ALL))
.getResultList();
Map,Property> inheritanceMapping =
new HashMap,Property>();
for (Property p : properties) {
InheritsPrivileges annotation = p.getAnnotatedElement().getAnnotation(InheritsPrivileges.class);
String assigneeName = annotation.value();
if (StringUtil.isNullOrEmpty(assigneeName)) {
throw new IllegalArgumentException(String.format("Specified relationshipType [%s] does not declare valid " +
"@InheritsPrivilege annotation on property [%s] - missing assignee property name",
relationshipType.getName(), p.getName()));
}
// Lookup the assignee property by name
Property assignee = PropertyQueries.createQuery(relationshipType)
.addCriteria(new NamedPropertyCriteria(assigneeName))
.getSingleResult();
inheritanceMapping.put(p, assignee);
}
privilegeChains.put(relationshipType, inheritanceMapping);
}
}
/**
* Checks if the given identity
inherits the privileges assigned to the given assignee
.
*
* @param relationshipManager
* @param identity
* @param assignee
*
* @return
*/
public boolean inheritsPrivileges(RelationshipManager relationshipManager, IdentityType identity, IdentityType assignee) {
if (identity == null) {
throw MESSAGES.nullArgument("identity");
}
if (assignee == null) {
throw MESSAGES.nullArgument("assignee");
}
// Find all of the relationships that the identity participates in, that have one or
// more declared privilege assignments
RelationshipQuery query = relationshipManager.createRelationshipQuery(Relationship.class);
query.setParameter(Relationship.IDENTITY, identity);
boolean hasPrivileges = false;
for (Relationship relationship : new ArrayList(query.getResultList())) {
Map, Property> propertyPropertyMap = this.privilegeChains.get(relationship.getClass());
if (propertyPropertyMap != null) {
for (Property identityProperty : propertyPropertyMap.keySet()) {
Property assigneeProperty = propertyPropertyMap.get(identityProperty);
// only do the check if the relationship is the same type of the declaring class of the assignee property
if (assigneeProperty.getDeclaringClass().equals(relationship.getClass())) {
IdentityType relationshipAssignee = assigneeProperty.getValue(relationship);
// if the relationship assignee is the same as the given target assignee, we have a match.
if (relationshipAssignee.equals(assignee)) {
hasPrivileges = true;
} else if (!identity.equals(relationshipAssignee)) {
// we continue the inheritance lookup if the identity is not the same as the relationship assignee
hasPrivileges = inheritsPrivileges(relationshipManager, relationshipAssignee, assignee);
}
if (hasPrivileges) {
return true;
}
}
}
}
}
// otherwise, let's check if there is a parent-child relationship for the identity, so we can check inheritance from parent
Property parentProperty = PropertyQueries
.createQuery(identity.getClass())
.addCriteria(new TypedPropertyCriteria(identity.getClass(), TypedPropertyCriteria.MatchOption.SUB_TYPE))
.getFirstResult();
if (parentProperty != null) {
IdentityType parentIdentity = parentProperty.getValue(identity);
if (parentIdentity != null) {
return inheritsPrivileges(relationshipManager, parentIdentity, assignee);
}
}
return false;
}
}