VIVO-695 VIVO-699 Refactor and optimize the PropertyRestrictionBean

Formerly the PropertyRestrictionPolicyHelper.
This commit is contained in:
Jim Blake 2014-12-10 15:01:51 -05:00
parent da9e244c18
commit 481d3fc1d8
30 changed files with 1321 additions and 1116 deletions

View file

@ -2,12 +2,10 @@
package edu.cornell.mannlib.vitro.webapp.auth.permissions;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionBean;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.RequestedAction;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.display.DisplayDataProperty;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.display.DisplayDataPropertyStatement;
@ -30,10 +28,8 @@ public class DisplayByRolePermission extends Permission {
private final String roleName;
private final RoleLevel roleLevel;
private final ServletContext ctx;
public DisplayByRolePermission(String roleName, RoleLevel roleLevel,
ServletContext ctx) {
public DisplayByRolePermission(String roleName, RoleLevel roleLevel) {
super(NAMESPACE + roleName);
if (roleName == null) {
@ -42,13 +38,9 @@ public class DisplayByRolePermission extends Permission {
if (roleLevel == null) {
throw new NullPointerException("roleLevel may not be null.");
}
if (ctx == null) {
throw new NullPointerException("context may not be null.");
}
this.roleName = roleName;
this.roleLevel = roleLevel;
this.ctx = ctx;
}
@Override
@ -110,22 +102,21 @@ public class DisplayByRolePermission extends Permission {
* subject, its predicate, and its object.
*/
private boolean isAuthorized(DisplayObjectPropertyStatement action) {
String subjectUri = action.getSubjectUri();
String subjectUri = action.getSubjectUri();
String objectUri = action.getObjectUri();
Property op = action.getProperty();
return canDisplayResource(subjectUri)
&& canDisplayPredicate(op)
return canDisplayResource(subjectUri) && canDisplayPredicate(op)
&& canDisplayResource(objectUri);
}
private boolean canDisplayResource(String resourceUri) {
return PropertyRestrictionPolicyHelper.getBean(ctx).canDisplayResource(
return PropertyRestrictionBean.getBean().canDisplayResource(
resourceUri, this.roleLevel);
}
private boolean canDisplayPredicate(Property predicate) {
return PropertyRestrictionPolicyHelper.getBean(ctx)
.canDisplayPredicate(predicate, this.roleLevel);
return PropertyRestrictionBean.getBean().canDisplayPredicate(predicate,
this.roleLevel);
}
@Override

View file

@ -2,12 +2,10 @@
package edu.cornell.mannlib.vitro.webapp.auth.permissions;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionBean;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.RequestedAction;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AbstractDataPropertyStatementAction;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AbstractObjectPropertyStatementAction;
@ -27,10 +25,8 @@ public class EditByRolePermission extends Permission {
private final String roleName;
private final RoleLevel roleLevel;
private final ServletContext ctx;
public EditByRolePermission(String roleName, RoleLevel roleLevel,
ServletContext ctx) {
public EditByRolePermission(String roleName, RoleLevel roleLevel) {
super(NAMESPACE + roleName);
if (roleName == null) {
@ -39,13 +35,9 @@ public class EditByRolePermission extends Permission {
if (roleLevel == null) {
throw new NullPointerException("roleLevel may not be null.");
}
if (ctx == null) {
throw new NullPointerException("context may not be null.");
}
this.roleName = roleName;
this.roleLevel = roleLevel;
this.ctx = ctx;
}
/**
@ -80,8 +72,7 @@ public class EditByRolePermission extends Permission {
private boolean isAuthorized(AbstractDataPropertyStatementAction action) {
String subjectUri = action.getSubjectUri();
Property predicate = action.getPredicate();
return canModifyResource(subjectUri)
&& canModifyPredicate(predicate);
return canModifyResource(subjectUri) && canModifyPredicate(predicate);
}
/**
@ -92,19 +83,18 @@ public class EditByRolePermission extends Permission {
String subjectUri = action.getSubjectUri();
Property predicate = action.getPredicate();
String objectUri = action.getObjectUri();
return canModifyResource(subjectUri)
&& canModifyPredicate(predicate)
return canModifyResource(subjectUri) && canModifyPredicate(predicate)
&& canModifyResource(objectUri);
}
private boolean canModifyResource(String resourceUri) {
return PropertyRestrictionPolicyHelper.getBean(ctx).canModifyResource(
resourceUri, roleLevel);
return PropertyRestrictionBean.getBean().canModifyResource(resourceUri,
roleLevel);
}
private boolean canModifyPredicate(Property predicate) {
return PropertyRestrictionPolicyHelper.getBean(ctx).canModifyPredicate(
predicate, roleLevel);
return PropertyRestrictionBean.getBean().canModifyPredicate(predicate,
roleLevel);
}
@Override

View file

@ -150,9 +150,9 @@ public class PermissionRegistry {
List<Permission> permissions = new ArrayList<Permission>();
permissions.addAll(SimplePermission.getAllInstances());
permissions.addAll(createDisplayByRolePermissions(ctx));
permissions.addAll(createEditByRolePermissions(ctx));
permissions.addAll(createPublishByRolePermissions(ctx));
permissions.addAll(createDisplayByRolePermissions());
permissions.addAll(createEditByRolePermissions());
permissions.addAll(createPublishByRolePermissions());
PermissionRegistry.createRegistry(ctx, permissions);
@ -169,17 +169,12 @@ public class PermissionRegistry {
* same rights as PUBLIC. Other permissions give them their self-editing
* privileges.
*/
private Collection<Permission> createDisplayByRolePermissions(
ServletContext ctx) {
private Collection<Permission> createDisplayByRolePermissions() {
List<Permission> list = new ArrayList<Permission>();
list.add(new DisplayByRolePermission("Admin", RoleLevel.DB_ADMIN,
ctx));
list.add(new DisplayByRolePermission("Curator", RoleLevel.CURATOR,
ctx));
list.add(new DisplayByRolePermission("Editor", RoleLevel.EDITOR,
ctx));
list.add(new DisplayByRolePermission("Public", RoleLevel.PUBLIC,
ctx));
list.add(new DisplayByRolePermission("Admin", RoleLevel.DB_ADMIN));
list.add(new DisplayByRolePermission("Curator", RoleLevel.CURATOR));
list.add(new DisplayByRolePermission("Editor", RoleLevel.EDITOR));
list.add(new DisplayByRolePermission("Public", RoleLevel.PUBLIC));
return list;
}
@ -191,12 +186,11 @@ public class PermissionRegistry {
*
* Other permissions give self-editors their editing privileges.
*/
private Collection<Permission> createEditByRolePermissions(
ServletContext ctx) {
private Collection<Permission> createEditByRolePermissions() {
List<Permission> list = new ArrayList<Permission>();
list.add(new EditByRolePermission("Admin", RoleLevel.DB_ADMIN, ctx));
list.add(new EditByRolePermission("Curator", RoleLevel.CURATOR, ctx));
list.add(new EditByRolePermission("Editor", RoleLevel.EDITOR, ctx));
list.add(new EditByRolePermission("Admin", RoleLevel.DB_ADMIN));
list.add(new EditByRolePermission("Curator", RoleLevel.CURATOR));
list.add(new EditByRolePermission("Editor", RoleLevel.EDITOR));
return list;
}
@ -210,17 +204,12 @@ public class PermissionRegistry {
* same rights as PUBLIC. Other permissions give them their self-editing
* privileges.
*/
private Collection<Permission> createPublishByRolePermissions(
ServletContext ctx) {
private Collection<Permission> createPublishByRolePermissions() {
List<Permission> list = new ArrayList<Permission>();
list.add(new PublishByRolePermission("Admin", RoleLevel.DB_ADMIN,
ctx));
list.add(new PublishByRolePermission("Curator", RoleLevel.CURATOR,
ctx));
list.add(new PublishByRolePermission("Editor", RoleLevel.EDITOR,
ctx));
list.add(new PublishByRolePermission("Public", RoleLevel.PUBLIC,
ctx));
list.add(new PublishByRolePermission("Admin", RoleLevel.DB_ADMIN));
list.add(new PublishByRolePermission("Curator", RoleLevel.CURATOR));
list.add(new PublishByRolePermission("Editor", RoleLevel.EDITOR));
list.add(new PublishByRolePermission("Public", RoleLevel.PUBLIC));
return list;
}
}

View file

@ -2,12 +2,10 @@
package edu.cornell.mannlib.vitro.webapp.auth.permissions;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionBean;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.RequestedAction;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.publish.PublishDataProperty;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.publish.PublishDataPropertyStatement;
@ -29,10 +27,8 @@ public class PublishByRolePermission extends Permission {
private final String roleName;
private final RoleLevel roleLevel;
private final ServletContext ctx;
public PublishByRolePermission(String roleName, RoleLevel roleLevel,
ServletContext ctx) {
public PublishByRolePermission(String roleName, RoleLevel roleLevel) {
super(NAMESPACE + roleName);
if (roleName == null) {
@ -41,13 +37,9 @@ public class PublishByRolePermission extends Permission {
if (roleLevel == null) {
throw new NullPointerException("roleLevel may not be null.");
}
if (ctx == null) {
throw new NullPointerException("context may not be null.");
}
this.roleName = roleName;
this.roleLevel = roleLevel;
this.ctx = ctx;
}
@Override
@ -116,13 +108,13 @@ public class PublishByRolePermission extends Permission {
}
private boolean canPublishResource(String resourceUri) {
return PropertyRestrictionPolicyHelper.getBean(ctx).canPublishResource(
return PropertyRestrictionBean.getBean().canPublishResource(
resourceUri, this.roleLevel);
}
private boolean canPublishPredicate(Property predicate) {
return PropertyRestrictionPolicyHelper.getBean(ctx)
.canPublishPredicate(predicate, this.roleLevel);
return PropertyRestrictionBean.getBean().canPublishPredicate(predicate,
this.roleLevel);
}
@Override

View file

@ -4,7 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.auth.policy;
import javax.servlet.ServletContext;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionBean;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
@ -23,13 +23,13 @@ public abstract class BaseSelfEditingPolicy {
}
protected boolean canModifyResource(String uri) {
return PropertyRestrictionPolicyHelper.getBean(ctx).canModifyResource(
uri, roleLevel);
return PropertyRestrictionBean.getBean().canModifyResource(uri,
roleLevel);
}
protected boolean canModifyPredicate(Property predicate) {
return PropertyRestrictionPolicyHelper.getBean(ctx).canModifyPredicate(
predicate, roleLevel);
return PropertyRestrictionBean.getBean().canModifyPredicate(predicate,
roleLevel);
}
protected PolicyDecision cantModifyResource(String uri) {

View file

@ -11,7 +11,7 @@ import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.common.HasAssociatedIndividual;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionBean;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
@ -114,14 +114,18 @@ public class DisplayRestrictedDataToSelfPolicy implements PolicyIface {
String subjectUri = action.getSubjectUri();
Property predicate = action.getProperty();
String objectUri = action.getObjectUri();
if (canDisplayResource(subjectUri) && canDisplayPredicate(predicate)
if (canDisplayResource(subjectUri)
&& canDisplayPredicate(predicate)
&& canDisplayResource(objectUri)
&& isAboutAssociatedIndividual(individuals, subjectUri, objectUri)) {
&& isAboutAssociatedIndividual(individuals, subjectUri,
objectUri)) {
return authorized("user may view ObjectPropertyStatement "
+ subjectUri + " ==> " + predicate.getURI() + " ==> " + objectUri);
+ subjectUri + " ==> " + predicate.getURI() + " ==> "
+ objectUri);
} else {
return defaultDecision("user may not view ObjectPropertyStatement "
+ subjectUri + " ==> " + predicate.getURI() + " ==> " + objectUri);
+ subjectUri + " ==> " + predicate.getURI() + " ==> "
+ objectUri);
}
}
@ -138,13 +142,13 @@ public class DisplayRestrictedDataToSelfPolicy implements PolicyIface {
}
private boolean canDisplayResource(String uri) {
return PropertyRestrictionPolicyHelper.getBean(ctx).canDisplayResource(
uri, RoleLevel.SELF);
return PropertyRestrictionBean.getBean().canDisplayResource(uri,
RoleLevel.SELF);
}
private boolean canDisplayPredicate(Property predicate) {
return PropertyRestrictionPolicyHelper.getBean(ctx)
.canDisplayPredicate(predicate, RoleLevel.SELF);
return PropertyRestrictionBean.getBean().canDisplayPredicate(predicate,
RoleLevel.SELF);
}
private boolean isAboutAssociatedIndividual(Collection<String> selves,

View file

@ -0,0 +1,207 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.auth.policy.bean;
import java.util.Arrays;
import java.util.Collection;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
import edu.cornell.mannlib.vitro.webapp.beans.Property;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
/**
* Assists the role-based policies in determining whether a property or resource
* may be displayed, modified, or published in linked open data.
*
* There is a singleton bean that holds the current threshold role levels for
* displaying, modifying, or publishing restricted properties.
*
* Create this bean after the context models are in place.
*
* Add PropertyRestrictionListener to your EditProcessObject if you are editing
* a property, to ensure that the bean stays current.
*/
public abstract class PropertyRestrictionBean {
private static final Log log = LogFactory
.getLog(PropertyRestrictionBean.class);
private static final PropertyRestrictionBean NULL = new PropertyRestrictionBeanNull();
protected static volatile PropertyRestrictionBean instance = NULL;
protected static final Collection<String> PROHIBITED_NAMESPACES = Arrays
.asList(new String[] { VitroVocabulary.vitroURI, "" });
protected static final Collection<String> PERMITTED_EXCEPTIONS = Arrays
.asList(new String[] { VitroVocabulary.MONIKER,
VitroVocabulary.MODTIME, VitroVocabulary.IND_MAIN_IMAGE,
VitroVocabulary.LINK, VitroVocabulary.PRIMARY_LINK,
VitroVocabulary.ADDITIONAL_LINK,
VitroVocabulary.LINK_ANCHOR, VitroVocabulary.LINK_URL });
// ----------------------------------------------------------------------
// static methods
// ----------------------------------------------------------------------
public static PropertyRestrictionBean getBean() {
return instance;
}
// ----------------------------------------------------------------------
// instance methods
// ----------------------------------------------------------------------
/**
* Any resource can be displayed.
*
* (Someday we may want to implement display restrictions based on VClass.)
*/
public abstract boolean canDisplayResource(String resourceUri,
RoleLevel userRole);
/**
* A resource cannot be modified if its namespace is in the prohibited list
* (but some exceptions are allowed).
*
* (Someday we may want to implement modify restrictions based on VClass.)
*/
public abstract boolean canModifyResource(String resourceUri,
RoleLevel userRole);
/**
* Any resource can be published.
*
* (Someday we may want to implement publish restrictions based on VClass.)
*/
public abstract boolean canPublishResource(String resourceUri,
RoleLevel userRole);
/**
* If display of a predicate is restricted, the user's role must be at least
* as high as the restriction level.
*/
public abstract boolean canDisplayPredicate(Property predicate,
RoleLevel userRole);
/**
* A predicate cannot be modified if its namespace is in the prohibited list
* (some exceptions are allowed).
*
* If modification of a predicate is restricted, the user's role must be at
* least as high as the restriction level.
*/
public abstract boolean canModifyPredicate(Property predicate,
RoleLevel userRole);
/**
* If publishing of a predicate is restricted, the user's role must be at
* least as high as the restriction level.
*/
public abstract boolean canPublishPredicate(Property predicate,
RoleLevel userRole);
/**
* The threshold values for this property may have changed.
*/
public abstract void updateProperty(PropertyRestrictionLevels levels);
// ----------------------------------------------------------------------
// The null implementation
// ----------------------------------------------------------------------
/**
* A placeholder for when the bean instance is not set.
*/
private static class PropertyRestrictionBeanNull extends
PropertyRestrictionBean {
@Override
public boolean canDisplayResource(String resourceUri, RoleLevel userRole) {
warn();
return false;
}
@Override
public boolean canModifyResource(String resourceUri, RoleLevel userRole) {
warn();
return false;
}
@Override
public boolean canPublishResource(String resourceUri, RoleLevel userRole) {
warn();
return false;
}
@Override
public boolean canDisplayPredicate(Property predicate,
RoleLevel userRole) {
warn();
return false;
}
@Override
public boolean canModifyPredicate(Property predicate, RoleLevel userRole) {
warn();
return false;
}
@Override
public boolean canPublishPredicate(Property predicate,
RoleLevel userRole) {
warn();
return false;
}
@Override
public void updateProperty(PropertyRestrictionLevels levels) {
warn();
}
private void warn() {
try {
throw new IllegalStateException();
} catch (IllegalStateException e) {
log.warn("No PropertyRestrictionBean in place.", e);
}
}
}
// ----------------------------------------------------------------------
// Setup class
// ----------------------------------------------------------------------
/**
* Create the bean at startup and remove it at shutdown.
*/
public static class Setup implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext();
StartupStatus ss = StartupStatus.getBean(ctx);
try {
instance = new PropertyRestrictionBeanImpl(
PROHIBITED_NAMESPACES, PERMITTED_EXCEPTIONS,
ModelAccess.on(ctx));
} catch (Exception e) {
ss.fatal(this,
"could not set up PropertyRestrictionBean", e);
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
instance = NULL;
}
}
}

View file

@ -0,0 +1,252 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.auth.policy.bean;
import static edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionLevels.Which.DISPLAY;
import static edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionLevels.Which.MODIFY;
import static edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionLevels.Which.PUBLISH;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.rdf.model.impl.Util;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionLevels.Which;
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
import edu.cornell.mannlib.vitro.webapp.beans.Property;
import edu.cornell.mannlib.vitro.webapp.dao.PropertyDao.FullPropertyKey;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ContextModelAccess;
/**
* On creation, populate a map of PropertyRestrictionLevels.
*
* When a change is detected, update the map accordingly.
*
* ------------------------------
*
* How is authorization determined?
*
* Resources are easy. If they aren't in a prohibited namespace, or are an
* exception to the prohibition, they are accessible.
*
* Properties are harder. The prohibited namespace and exceptions still apply,
* but if we pass that test, then we check the threshold map.
*
* When a test is made, we look for thresholds in the map. First we look for the
* full key of domain-base-range, in case we are testing a faux property. Faux
* properties are recorded in the map with the full key.
*
* If we don't find the full key, then perhaps we are testing a faux property
* that has no settings, or perhaps we are testing an object property. We look
* for the partial key of null-base-null, which covers both of these cases,
* since object properties (and data properties) are recorded the map with a
* partial key.
*
* Similarly, if we find a null threshold value in the full key, we look back to
* the partial key for a threshold.
*
* If we find no non-null threshold value then the property is unrestricted for
* that feature.
*
* -----------------------------
*
* It would perhaps be a silly optimization, but if we find a key with 3 null
* thresholds, we could remove it from the map without changing the behavior.
*/
public class PropertyRestrictionBeanImpl extends PropertyRestrictionBean {
private static final Log log = LogFactory
.getLog(PropertyRestrictionBeanImpl.class);
private final Set<String> prohibitedNamespaces;
private final Set<String> permittedExceptions;
private final Map<FullPropertyKey, PropertyRestrictionLevels> thresholdMap = new ConcurrentHashMap<>();
public PropertyRestrictionBeanImpl(Collection<String> prohibitedNamespaces,
Collection<String> permittedExceptions, ContextModelAccess models) {
Objects.requireNonNull(prohibitedNamespaces,
"prohibitedNamespaces may not be null.");
this.prohibitedNamespaces = Collections.unmodifiableSet(new TreeSet<>(
prohibitedNamespaces));
Objects.requireNonNull(permittedExceptions,
"permittedExceptions may not be null.");
this.permittedExceptions = Collections.unmodifiableSet(new TreeSet<>(
permittedExceptions));
Objects.requireNonNull(models, "models may not be null.");
populateThresholdMap(models.getWebappDaoFactory());
}
private void populateThresholdMap(WebappDaoFactory wadf) {
for (ObjectProperty oProp : wadf.getObjectPropertyDao()
.getAllObjectProperties()) {
addObjectPropertyToMap(oProp);
for (FauxProperty fProp : wadf.getFauxPropertyDao()
.getFauxPropertiesForBaseUri(oProp.getURI())) {
addFauxPropertyToMap(fProp);
}
}
for (DataProperty dProp : wadf.getDataPropertyDao()
.getAllDataProperties()) {
addDataPropertyToMap(dProp);
}
}
private void addObjectPropertyToMap(ObjectProperty oProp) {
FullPropertyKey key = new FullPropertyKey(oProp.getURI());
PropertyRestrictionLevels levels = new PropertyRestrictionLevels(key,
oProp.getHiddenFromDisplayBelowRoleLevel(),
oProp.getProhibitedFromUpdateBelowRoleLevel(),
oProp.getHiddenFromPublishBelowRoleLevel());
thresholdMap.put(key, levels);
}
private void addFauxPropertyToMap(FauxProperty fProp) {
FullPropertyKey key = new FullPropertyKey(fProp.getDomainURI(),
fProp.getBaseURI(), fProp.getRangeURI());
PropertyRestrictionLevels levels = new PropertyRestrictionLevels(key,
fProp.getHiddenFromDisplayBelowRoleLevel(),
fProp.getProhibitedFromUpdateBelowRoleLevel(),
fProp.getHiddenFromPublishBelowRoleLevel());
thresholdMap.put(key, levels);
}
private void addDataPropertyToMap(DataProperty dProp) {
FullPropertyKey key = new FullPropertyKey(dProp.getURI());
PropertyRestrictionLevels levels = new PropertyRestrictionLevels(key,
dProp.getHiddenFromDisplayBelowRoleLevel(),
dProp.getProhibitedFromUpdateBelowRoleLevel(),
dProp.getHiddenFromPublishBelowRoleLevel());
thresholdMap.put(key, levels);
}
@Override
public boolean canDisplayResource(String resourceUri, RoleLevel userRole) {
return (resourceUri != null) && (userRole != null);
}
@Override
public boolean canModifyResource(String resourceUri, RoleLevel userRole) {
if (resourceUri == null || userRole == null) {
return false;
}
if (prohibitedNamespaces.contains(namespace(resourceUri))
&& !permittedExceptions.contains(resourceUri)) {
return false;
}
return true;
}
@Override
public boolean canPublishResource(String resourceUri, RoleLevel userRole) {
return (resourceUri != null) && (userRole != null);
}
@Override
public boolean canDisplayPredicate(Property predicate, RoleLevel userRole) {
if (predicate == null || predicate.getURI() == null) {
return false;
}
return isAuthorized(userRole, getThreshold(predicate, DISPLAY));
}
@Override
public boolean canModifyPredicate(Property predicate, RoleLevel userRole) {
if (predicate == null || predicate.getURI() == null) {
return false;
}
return isAuthorized(userRole, getPropertyModifyThreshold(predicate));
}
@Override
public boolean canPublishPredicate(Property predicate, RoleLevel userRole) {
if (predicate == null || predicate.getURI() == null) {
return false;
}
return isAuthorized(userRole, getThreshold(predicate, PUBLISH));
}
@Override
public void updateProperty(PropertyRestrictionLevels levels) {
thresholdMap.put(levels.getKey(), levels);
}
private boolean isAuthorized(RoleLevel userRole, RoleLevel thresholdRole) {
if (userRole == null) {
return false;
}
if (thresholdRole == null) {
return true;
}
return userRole.compareTo(thresholdRole) >= 0;
}
private RoleLevel getPropertyModifyThreshold(Property p) {
if (prohibitedNamespaces.contains(namespace(p.getURI()))
&& !permittedExceptions.contains(p.getURI())) {
return RoleLevel.NOBODY;
}
return getThreshold(p, MODIFY);
}
private RoleLevel getThreshold(Property p, Which which) {
RoleLevel qualifiedLevel = getThreshold(new FullPropertyKey(p), which);
if (qualifiedLevel != null) {
return qualifiedLevel;
}
RoleLevel bareLevel = getThreshold(new FullPropertyKey(p.getURI()),
which);
return bareLevel;
}
private RoleLevel getThreshold(FullPropertyKey key, Which which) {
PropertyRestrictionLevels levels = thresholdMap.get(key);
if (levels == null) {
return null;
} else {
return levels.getLevel(which);
}
}
private String namespace(String uri) {
return uri.substring(0, Util.splitNamespace(uri));
}
@Override
public String toString() {
SortedSet<FullPropertyKey> keys = new TreeSet<>(
new Comparator<FullPropertyKey>() {
@Override
public int compare(FullPropertyKey o1, FullPropertyKey o2) {
return o1.toString().compareTo(o2.toString());
}
});
keys.addAll(thresholdMap.keySet());
StringBuilder buffer = new StringBuilder();
for (FullPropertyKey key : keys) {
buffer.append(key + " " + thresholdMap.get(key).getLevel(DISPLAY)
+ " " + thresholdMap.get(key).getLevel(MODIFY) + " "
+ thresholdMap.get(key).getLevel(PUBLISH) + "\n");
}
return buffer.toString();
}
}

View file

@ -0,0 +1,68 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.auth.policy.bean;
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
import edu.cornell.mannlib.vitro.webapp.dao.PropertyDao.FullPropertyKey;
/**
* The threshold levels for operations on a given property.
*
* This is based on the assumption that the FullPropertyKey is sufficient to
* distinguish all properties. An object property and a data property may not
* share the same key. A faux property must have a different key from any object
* property.
*/
public class PropertyRestrictionLevels {
private final FullPropertyKey key;
private final RoleLevel displayThreshold;
private final RoleLevel modifyThreshold;
private final RoleLevel publishThreshold;
public enum Which {
DISPLAY, MODIFY, PUBLISH
}
public PropertyRestrictionLevels(FullPropertyKey key,
RoleRestrictedProperty p) {
this(key, p.getHiddenFromDisplayBelowRoleLevel(), p
.getProhibitedFromUpdateBelowRoleLevel(), p
.getHiddenFromPublishBelowRoleLevel());
}
public PropertyRestrictionLevels(FullPropertyKey key,
RoleLevel displayThreshold, RoleLevel modifyThreshold,
RoleLevel publishThreshold) {
this.key = key;
this.displayThreshold = displayThreshold;
this.modifyThreshold = modifyThreshold;
this.publishThreshold = publishThreshold;
}
public FullPropertyKey getKey() {
return key;
}
public RoleLevel getLevel(Which which) {
if (which == null) {
return null;
} else {
switch (which) {
case DISPLAY:
return displayThreshold;
case MODIFY:
return modifyThreshold;
default:
return publishThreshold;
}
}
}
@Override
public String toString() {
return "PropertyRestrictionLevels[key=" + key + ", display="
+ displayThreshold + ", modify=" + modifyThreshold
+ ", publish=" + publishThreshold + "]";
}
}

View file

@ -2,20 +2,12 @@
package edu.cornell.mannlib.vitro.webapp.auth.policy.bean;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.DISPLAY;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.Model;
import edu.cornell.mannlib.vedit.beans.EditProcessObject;
import edu.cornell.mannlib.vedit.listener.ChangeListener;
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.dao.PropertyDao.FullPropertyKey;
/**
* Add this ChangeListener to your EditProcessObject when modifying the
@ -26,12 +18,6 @@ public class PropertyRestrictionListener implements ChangeListener {
private static final Log log = LogFactory
.getLog(PropertyRestrictionListener.class);
private final ServletContext ctx;
public PropertyRestrictionListener(ServletContext ctx) {
this.ctx = ctx;
}
/**
* If the deleted property had a non-null restriction, rebuild the bean.
*/
@ -39,84 +25,43 @@ public class PropertyRestrictionListener implements ChangeListener {
public void doDeleted(Object oldObj, EditProcessObject epo) {
if (oldObj instanceof RoleRestrictedProperty) {
RoleRestrictedProperty p = (RoleRestrictedProperty) oldObj;
if (anyRoleChanged(p.getHiddenFromDisplayBelowRoleLevel(),
p.getProhibitedFromUpdateBelowRoleLevel(),
p.getHiddenFromPublishBelowRoleLevel(), null, null, null)) {
log.debug("rebuilding the PropertyRestrictionPolicyHelper after deletion");
createAndSetBean();
}
FullPropertyKey key = new FullPropertyKey(p);
updateLevels(new PropertyRestrictionLevels(key, p));
} else {
log.warn("Not an instance of RoleRestrictedProperty: " + oldObj);
}
}
/**
* If the inserted property has a non-null restriction, rebuild the bean.
* Update the inserted property.
*/
@Override
public void doInserted(Object newObj, EditProcessObject epo) {
if (newObj instanceof RoleRestrictedProperty) {
RoleRestrictedProperty p = (RoleRestrictedProperty) newObj;
if (anyRoleChanged(null, null, null,
p.getHiddenFromDisplayBelowRoleLevel(),
p.getProhibitedFromUpdateBelowRoleLevel(),
p.getHiddenFromPublishBelowRoleLevel())) {
log.debug("rebuilding the PropertyRestrictionPolicyHelper after insertion");
createAndSetBean();
}
FullPropertyKey key = new FullPropertyKey(p);
updateLevels(new PropertyRestrictionLevels(key, p));
} else {
log.warn("Not an instance of RoleRestrictedProperty: " + newObj);
}
}
/**
* If the updated property has changed its restrictions, rebuild the bean.
* Update the changed property.
*/
@Override
public void doUpdated(Object oldObj, Object newObj, EditProcessObject epo) {
if (oldObj instanceof RoleRestrictedProperty
&& newObj instanceof RoleRestrictedProperty) {
RoleRestrictedProperty oldP = (RoleRestrictedProperty) oldObj;
if (newObj instanceof RoleRestrictedProperty) {
RoleRestrictedProperty newP = (RoleRestrictedProperty) newObj;
if (anyRoleChanged(oldP.getHiddenFromDisplayBelowRoleLevel(),
oldP.getProhibitedFromUpdateBelowRoleLevel(),
oldP.getHiddenFromPublishBelowRoleLevel(),
newP.getHiddenFromDisplayBelowRoleLevel(),
newP.getProhibitedFromUpdateBelowRoleLevel(),
newP.getHiddenFromPublishBelowRoleLevel())) {
log.debug("rebuilding the PropertyRestrictionPolicyHelper after update");
createAndSetBean();
}
FullPropertyKey key = new FullPropertyKey(newP);
updateLevels(new PropertyRestrictionLevels(key, newP));
} else {
log.warn("Not instances of RoleRestrictedProperty: " + oldObj
+ ", " + newObj);
}
}
private boolean anyRoleChanged(RoleLevel oldDisplayRole,
RoleLevel oldUpdateRole, RoleLevel oldPublishRole,
RoleLevel newDisplayRole, RoleLevel newUpdateRole,
RoleLevel newPublishRole) {
return (!isTheSame(oldDisplayRole, newDisplayRole))
|| (!isTheSame(oldUpdateRole, newUpdateRole))
|| (!isTheSame(oldPublishRole, newPublishRole));
}
private boolean isTheSame(RoleLevel oldRole, RoleLevel newRole) {
if ((oldRole == null) && (newRole == null)) {
return true;
} else if ((oldRole == null) || (newRole == null)) {
return false;
} else {
return oldRole.compareTo(newRole) == 0;
}
}
private void createAndSetBean() {
OntModel model = ModelAccess.on(ctx).getOntModel();
Model displayModel = ModelAccess.on(ctx).getOntModel(DISPLAY);
PropertyRestrictionPolicyHelper bean = PropertyRestrictionPolicyHelper
.createBean(model, displayModel);
PropertyRestrictionPolicyHelper.setBean(ctx, bean);
private void updateLevels(PropertyRestrictionLevels levels) {
PropertyRestrictionBean.getBean().updateProperty(levels);
}
}

View file

@ -1,498 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.auth.policy.bean;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.DISPLAY;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.rdf.model.impl.Util;
import com.hp.hpl.jena.shared.Lock;
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
import edu.cornell.mannlib.vitro.webapp.beans.Property;
import edu.cornell.mannlib.vitro.webapp.dao.PropertyDao.FullPropertyKey;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
import edu.cornell.mannlib.vitro.webapp.utils.ApplicationConfigurationOntologyUtils;
/**
* Assists the role-based policies in determining whether a property or resource
* may be displayed, modified, or published in linked open data.
*
* There is a bean in the context that holds the current threshold role levels
* for displaying, modifying, or publishing restricted properties.
*
* Create this bean after the Jena model is in place in the context.
*
* Add PropertyRestrictionListener to your EditProcessObject if you are editing
* a property, to ensure that the bean stays current.
*/
public class PropertyRestrictionPolicyHelper {
private static final Log log = LogFactory
.getLog(PropertyRestrictionPolicyHelper.class);
private static final Collection<String> PROHIBITED_NAMESPACES = Arrays
.asList(new String[] { VitroVocabulary.vitroURI, "" });
private static final Collection<String> PERMITTED_EXCEPTIONS = Arrays
.asList(new String[] {
VitroVocabulary.MONIKER,
VitroVocabulary.MODTIME,
VitroVocabulary.IND_MAIN_IMAGE,
VitroVocabulary.LINK,
VitroVocabulary.PRIMARY_LINK,
VitroVocabulary.ADDITIONAL_LINK,
VitroVocabulary.LINK_ANCHOR,
VitroVocabulary.LINK_URL });
/**
* The bean is attached to the ServletContext using this attribute name.
*/
private static final String ATTRIBUTE_NAME = PropertyRestrictionPolicyHelper.class
.getName();
// ----------------------------------------------------------------------
// static methods
// ----------------------------------------------------------------------
public static PropertyRestrictionPolicyHelper getBean(ServletContext ctx) {
Object attribute = ctx.getAttribute(ATTRIBUTE_NAME);
if (!(attribute instanceof PropertyRestrictionPolicyHelper)) {
throw new IllegalStateException(
"PropertyRestrictionPolicyHelper has not been initialized.");
}
return (PropertyRestrictionPolicyHelper) attribute;
}
private static void removeBean(ServletContext ctx) {
ctx.removeAttribute(ATTRIBUTE_NAME);
}
public static void setBean(ServletContext ctx,
PropertyRestrictionPolicyHelper bean) {
if (bean == null) {
throw new NullPointerException("bean may not be null.");
}
ctx.setAttribute(ATTRIBUTE_NAME, bean);
}
/**
* Initialize the bean with the standard prohibitions and exceptions, and
* with the thresholds obtained from the model.
*/
public static PropertyRestrictionPolicyHelper createBean(OntModel model,
Model displayModel) {
Map<FullPropertyKey, RoleLevel> displayThresholdMap =
new HashMap<FullPropertyKey, RoleLevel>();
Map<FullPropertyKey, RoleLevel> modifyThresholdMap =
new HashMap<FullPropertyKey, RoleLevel>();
Map<FullPropertyKey, RoleLevel> publishThresholdMap =
new HashMap<FullPropertyKey, RoleLevel>();
OntModel union = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM,
ModelFactory.createUnion(displayModel, model));
populateThresholdMap(union, displayThresholdMap,
VitroVocabulary.HIDDEN_FROM_DISPLAY_BELOW_ROLE_LEVEL_ANNOT);
populateThresholdMap(union, modifyThresholdMap,
VitroVocabulary.PROHIBITED_FROM_UPDATE_BELOW_ROLE_LEVEL_ANNOT);
populateThresholdMap(union, publishThresholdMap,
VitroVocabulary.HIDDEN_FROM_PUBLISH_BELOW_ROLE_LEVEL_ANNOT);
PropertyRestrictionPolicyHelper bean = new PropertyRestrictionPolicyHelper(
PROHIBITED_NAMESPACES, PERMITTED_EXCEPTIONS,
displayThresholdMap, modifyThresholdMap, publishThresholdMap);
return bean;
}
private RoleLevel getModifyThreshold(Property property) {
return getThreshold(property, modifyThresholdMap);
}
private RoleLevel getThreshold(Property property,
Map<FullPropertyKey, RoleLevel> thresholdMap) {
if (property.getURI() == null) {
return RoleLevel.NOBODY;
}
RoleLevel roleLevel = thresholdMap.get(new FullPropertyKey(property));
if (roleLevel == null) {
roleLevel = thresholdMap
.get(new FullPropertyKey(property.getURI()));
}
return roleLevel;
}
/**
* Find all the resources that possess this property, and map the resource
* URI to the required RoleLevel.
*/
private static void populateThresholdMap(OntModel model,
Map<FullPropertyKey, RoleLevel> map, String propertyUri) {
model.enterCriticalSection(Lock.READ);
try {
com.hp.hpl.jena.rdf.model.Property property = model.getProperty(propertyUri);
StmtIterator stmts = model.listStatements((Resource) null,
property, (Resource) null);
try {
while (stmts.hasNext()) {
Statement stmt = stmts.next();
Resource subject = stmt.getSubject();
RDFNode objectNode = stmt.getObject();
if ((subject == null) || (!(objectNode instanceof Resource))) {
continue;
}
Resource object = (Resource) objectNode;
RoleLevel role = RoleLevel.getRoleByUri(object.getURI());
map.put(new FullPropertyKey(subject.getURI()), role);
}
} finally {
stmts.close();
}
List<ObjectProperty> fauxOps = ApplicationConfigurationOntologyUtils
.getAdditionalFauxSubproperties(null, null, model, model);
for (ObjectProperty faux : fauxOps) {
RoleLevel role = null;
if(VitroVocabulary.PROHIBITED_FROM_UPDATE_BELOW_ROLE_LEVEL_ANNOT
.equals(propertyUri)) {
role = faux.getProhibitedFromUpdateBelowRoleLevel();
} else if (VitroVocabulary.HIDDEN_FROM_DISPLAY_BELOW_ROLE_LEVEL_ANNOT
.equals(propertyUri)) {
role = faux.getHiddenFromDisplayBelowRoleLevel();
} else if (VitroVocabulary.HIDDEN_FROM_PUBLISH_BELOW_ROLE_LEVEL_ANNOT
.equals(propertyUri)) {
role = faux.getHiddenFromPublishBelowRoleLevel();
}
if (role != null) {
FullPropertyKey key = new FullPropertyKey(faux);
map.put(key, role);
log.debug("Putting key: " + key + " ==> L:" + role);
}
}
} finally {
model.leaveCriticalSection();
}
}
// ----------------------------------------------------------------------
// the bean
// ----------------------------------------------------------------------
/**
* URIs in these namespaces can't be modified, unless they are listed in the
* exceptions.
*/
private final Collection<String> modifyProhibitedNamespaces;
/**
* These URIs can be modified, even if they are in the prohibited
* namespaces.
*/
private final Collection<String> modifyExceptionsAllowedUris;
/**
* These URIs can be displayed only if the user's role is at least as high
* as the threshold role.
*/
private final Map<FullPropertyKey, RoleLevel> displayThresholdMap;
/**
* These URIs can be modified only if the user's role is at least as high as
* the threshold role.
*/
private final Map<FullPropertyKey, RoleLevel> modifyThresholdMap;
/**
* These URIs can be published only if the user's role is at least as high as
* the threshold role.
*/
private final Map<FullPropertyKey, RoleLevel> publishThresholdMap;
/**
* Store unmodifiable versions of the inputs.
*
* Protected access: the bean should only be created by the static methods,
* or by unit tests.
*/
protected PropertyRestrictionPolicyHelper(
Collection<String> modifyProhibitedNamespaces,
Collection<String> modifyExceptionsAllowedUris,
Map<FullPropertyKey, RoleLevel> displayThresholdMap,
Map<FullPropertyKey, RoleLevel> modifyThresholdMap,
Map<FullPropertyKey, RoleLevel> publishThresholdMap) {
this.modifyProhibitedNamespaces = unmodifiable(modifyProhibitedNamespaces);
this.modifyExceptionsAllowedUris = unmodifiable(modifyExceptionsAllowedUris);
this.displayThresholdMap = displayThresholdMap;
this.modifyThresholdMap = modifyThresholdMap;
this.publishThresholdMap = publishThresholdMap;
// TODO: why are these no longer unmodifiable? Brian changed during the
// TODO: ISF integration.
// this.displayThresholdMap = unmodifiable(displayThresholdMap);
// this.modifyThresholdMap = unmodifiable(modifyThresholdMap);
if (log.isDebugEnabled()) {
log.debug("prohibited: " + this.modifyProhibitedNamespaces);
log.debug("exceptions: " + this.modifyExceptionsAllowedUris);
log.debug("display thresholds: " + this.displayThresholdMap);
log.debug("modify thresholds: " + this.modifyThresholdMap);
log.debug("publish thresholds: " + this.publishThresholdMap);
}
}
private Collection<String> unmodifiable(Collection<String> raw) {
if (raw == null) {
return Collections.emptyList();
} else {
return Collections.unmodifiableCollection(new HashSet<String>(raw));
}
}
@SuppressWarnings("unused")
private Map<String, RoleLevel> unmodifiable(Map<String, RoleLevel> raw) {
if (raw == null) {
return Collections.emptyMap();
} else {
return Collections.unmodifiableMap(new HashMap<String, RoleLevel>(
raw));
}
}
/**
* Any resource can be displayed.
*
* (Someday we may want to implement display restrictions based on VClass.)
*/
@SuppressWarnings("unused")
public boolean canDisplayResource(String resourceUri, RoleLevel userRole) {
if (resourceUri == null) {
log.debug("can't display resource: resourceUri was null");
return false;
}
log.debug("can display resource '" + resourceUri + "'");
return true;
}
/**
* A resource cannot be modified if its namespace is in the prohibited list
* (but some exceptions are allowed).
*
* (Someday we may want to implement modify restrictions based on VClass.)
*/
@SuppressWarnings("unused")
public boolean canModifyResource(String resourceUri, RoleLevel userRole) {
if (resourceUri == null) {
log.debug("can't modify resource: resourceUri was null");
return false;
}
if (modifyProhibitedNamespaces.contains(namespace(resourceUri))) {
if (modifyExceptionsAllowedUris.contains(resourceUri)) {
log.debug("'" + resourceUri + "' is a permitted exception");
} else {
log.debug("can't modify resource '" + resourceUri
+ "': prohibited namespace: '" + namespace(resourceUri)
+ "'");
return false;
}
}
log.debug("can modify resource '" + resourceUri + "'");
return true;
}
/**
* Any resource can be published.
*
* (Someday we may want to implement publish restrictions based on VClass.)
*/
@SuppressWarnings("unused")
public boolean canPublishResource(String resourceUri, RoleLevel userRole) {
if (resourceUri == null) {
log.debug("can't publish resource: resourceUri was null");
return false;
}
log.debug("can publish resource '" + resourceUri + "'");
return true;
}
/**
* If display of a predicate is restricted, the user's role must be at least
* as high as the restriction level.
*/
public boolean canDisplayPredicate(Property predicate, RoleLevel userRole) {
if (predicate == null) {
log.debug("can't display predicate: predicate was null");
return false;
}
RoleLevel displayThreshold = getThreshold(predicate, displayThresholdMap);
if (isAuthorized(userRole, displayThreshold)) {
log.debug("can display predicate: '" + predicate.getURI() + "', domain="
+ predicate.getDomainVClassURI() + ", range="
+ predicate.getRangeVClassURI() + ", userRole="
+ userRole + ", thresholdRole=" + displayThreshold);
return true;
}
log.debug("can't display predicate: '" + predicate.getURI() + "', domain="
+ predicate.getDomainVClassURI() + ", range="
+ predicate.getRangeVClassURI() + ", userRole="
+ userRole + ", thresholdRole=" + displayThreshold);
return false;
}
/**
* A predicate cannot be modified if its namespace is in the prohibited list
* (some exceptions are allowed).
*
* If modification of a predicate is restricted, the user's role must be at
* least as high as the restriction level.
*/
public boolean canModifyPredicate(Property predicate, RoleLevel userRole) {
if (predicate == null || predicate.getURI() == null) {
log.debug("can't modify predicate: predicate was null");
return false;
}
if (modifyProhibitedNamespaces.contains(namespace(predicate.getURI()))) {
if (modifyExceptionsAllowedUris.contains(predicate.getURI())) {
log.debug("'" + predicate.getURI() + "' is a permitted exception");
} else {
log.debug("can't modify resource '" + predicate.getURI()
+ "': prohibited namespace: '"
+ namespace(predicate.getURI()) + "'");
return false;
}
}
RoleLevel modifyThreshold = getModifyThreshold(predicate);
if (isAuthorized(userRole, modifyThreshold)) {
log.debug("can modify predicate: '" + predicate.getURI() + "', domain="
+ predicate.getDomainVClassURI() + ", range="
+ predicate.getRangeVClassURI() + ", userRole="
+ userRole + ", thresholdRole=" + modifyThreshold);
return true;
}
log.debug("can't modify predicate: '" + predicate.getURI() + "', domain="
+ predicate.getDomainVClassURI() + ", range="
+ predicate.getRangeVClassURI() + ", userRole="
+ userRole + ", thresholdRole=" + modifyThreshold);
return false;
}
/**
* If publishing of a predicate is restricted, the user's role must be at least
* as high as the restriction level.
*/
public boolean canPublishPredicate(Property predicate, RoleLevel userRole) {
if (predicate == null) {
log.debug("can't publish predicate: predicate was null");
return false;
}
RoleLevel publishThreshold = getThreshold(predicate, publishThresholdMap);
if (isAuthorized(userRole, publishThreshold)) {
log.debug("can publish predicate: '" + predicate.getURI() + "', domain="
+ predicate.getDomainVClassURI() + ", range="
+ predicate.getRangeVClassURI() + ", userRole="
+ userRole + ", thresholdRole=" + publishThreshold);
return true;
}
log.debug("can't publish predicate: '" + predicate.getURI() + "', domain="
+ predicate.getDomainVClassURI() + ", range="
+ predicate.getRangeVClassURI() + ", userRole="
+ userRole + ", thresholdRole=" + publishThreshold);
return false;
}
private boolean isAuthorized(RoleLevel userRole, RoleLevel thresholdRole) {
if (userRole == null) {
return false;
}
if (thresholdRole == null) {
return true;
}
return userRole.compareTo(thresholdRole) >= 0;
}
private String namespace(String uri) {
return uri.substring(0, Util.splitNamespace(uri));
}
// ----------------------------------------------------------------------
// Setup class
// ----------------------------------------------------------------------
/**
* Create the bean at startup and remove it at shutdown.
*/
public static class Setup implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext();
StartupStatus ss = StartupStatus.getBean(ctx);
try {
OntModel model = ModelAccess.on(ctx).getOntModel();
if (model == null) {
throw new NullPointerException(
"jenaOntModel has not been initialized.");
}
Model displayModel = ModelAccess.on(ctx).getOntModel(DISPLAY);
if (displayModel == null) {
throw new NullPointerException(
"display model has not been initialized.");
}
PropertyRestrictionPolicyHelper bean = PropertyRestrictionPolicyHelper
.createBean(model, displayModel);
PropertyRestrictionPolicyHelper.setBean(ctx, bean);
} catch (Exception e) {
ss.fatal(this, "could not set up PropertyRestrictionPolicyHelper", e);
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
removeBean(sce.getServletContext());
}
}
}

View file

@ -9,6 +9,12 @@ import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
* user's role level.
*/
public interface RoleRestrictedProperty {
String getDomainVClassURI();
String getRangeVClassURI();
String getURI();
RoleLevel getHiddenFromDisplayBelowRoleLevel();
RoleLevel getProhibitedFromUpdateBelowRoleLevel();

View file

@ -8,7 +8,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.auth.policy.BasicPolicyDecision;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionBean;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
@ -31,13 +31,13 @@ public abstract class AbstractRelationshipPolicy implements PolicyIface {
}
protected boolean canModifyResource(String uri) {
return PropertyRestrictionPolicyHelper.getBean(ctx).canModifyResource(
uri, RoleLevel.SELF);
return PropertyRestrictionBean.getBean().canModifyResource(uri,
RoleLevel.SELF);
}
protected boolean canModifyPredicate(Property predicate) {
return PropertyRestrictionPolicyHelper.getBean(ctx).canModifyPredicate(
predicate, RoleLevel.SELF);
return PropertyRestrictionBean.getBean().canModifyPredicate(predicate,
RoleLevel.SELF);
}
protected PolicyDecision cantModifyResource(String uri) {

View file

@ -233,4 +233,18 @@ public class FauxProperty extends BaseResourceBean implements ResourceBean,
+ ", customEntryForm=" + customEntryForm + ", customListView="
+ customListView + "]";
}
// ----------------------------------------------------------------------
// Satisfy the RoleRestrictedProperty interface.
// ----------------------------------------------------------------------
@Override
public String getDomainVClassURI() {
return getDomainURI();
}
@Override
public String getRangeVClassURI() {
return getRangeURI();
}
}

View file

@ -34,9 +34,9 @@ import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.edit.utils.RoleLevelOptionsSetup;
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.DatatypeDao;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.dao.OntologyDao;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
public class DatapropRetryController extends BaseEditController {
@ -124,7 +124,7 @@ public class DatapropRetryController extends BaseEditController {
//set up any listeners
List changeListenerList = new ArrayList();
changeListenerList.add(new PropertyRestrictionListener(getServletContext()));
changeListenerList.add(new PropertyRestrictionListener());
epo.setChangeListenerList(changeListenerList);

View file

@ -211,7 +211,7 @@ public class FauxPropertyRetryController extends BaseEditController {
private void setListeners() {
epo.setChangeListenerList(Collections
.singletonList(new PropertyRestrictionListener(ctx)));
.singletonList(new PropertyRestrictionListener()));
}
private void setForwarders() {

View file

@ -33,9 +33,9 @@ import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.edit.utils.RoleLevelOptionsSetup;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.OntologyDao;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
public class PropertyRetryController extends BaseEditController {
@ -115,7 +115,7 @@ public class PropertyRetryController extends BaseEditController {
//set up any listeners
List<ChangeListener> changeListenerList = new ArrayList<>();
changeListenerList.add(new PropertyRestrictionListener(getServletContext()));
changeListenerList.add(new PropertyRestrictionListener());
epo.setChangeListenerList(changeListenerList);
//make a postinsert pageforwarder that will send us to a new class's fetch screen

View file

@ -7,6 +7,7 @@ import java.util.Objects;
import com.hp.hpl.jena.vocabulary.OWL;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.RoleRestrictedProperty;
import edu.cornell.mannlib.vitro.webapp.beans.Property;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
@ -72,9 +73,12 @@ public interface PropertyDao {
this(OWL_THING, uri, OWL_THING);
}
public FullPropertyKey(Property prop) {
this(prop.getDomainVClassURI(), prop.getURI(), prop
.getRangeVClassURI());
public FullPropertyKey(Property p) {
this(p.getDomainVClassURI(), p.getURI(), p.getRangeVClassURI());
}
public FullPropertyKey(RoleRestrictedProperty p) {
this(p.getDomainVClassURI(), p.getURI(), p.getRangeVClassURI());
}
public FullPropertyKey(String domainUri, String propertyUri,

View file

@ -42,6 +42,7 @@ import com.hp.hpl.jena.vocabulary.OWL;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.RoleRestrictedProperty;
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
@ -1137,7 +1138,7 @@ public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectProp
}
qexec.close();
}
FullPropertyKey key = new FullPropertyKey(op);
FullPropertyKey key = new FullPropertyKey((RoleRestrictedProperty)op);
String customListViewConfigFileName = customListViewConfigFileMap.get(key);
if (customListViewConfigFileName == null) {
log.debug("no list view found for " + key);

View file

@ -274,7 +274,7 @@ public class GroupedPropertyList extends BaseTemplateModel {
}
private boolean redundant(ObjectProperty op, ObjectProperty op2) {
return new FullPropertyKey(op).equals(new FullPropertyKey(op2));
return new FullPropertyKey((Property)op).equals(new FullPropertyKey((Property)op2));
}
private void addObjectPropertyToPropertyList(String propertyUri, String domainUri, String rangeUri,