diff --git a/webapp/config/web.xml b/webapp/config/web.xml index 8a084f985..773c9a1bc 100644 --- a/webapp/config/web.xml +++ b/webapp/config/web.xml @@ -169,21 +169,6 @@ --> - - edu.cornell.mannlib.vitro.webapp.auth.policy.setup.EditorEditingPolicySetup - - - - - edu.cornell.mannlib.vitro.webapp.auth.policy.setup.CuratorEditingPolicySetup - - - - - edu.cornell.mannlib.vitro.webapp.auth.policy.setup.DbAdminEditingPolicySetup - - - edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerSetup diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/EditRestrictedDataByRoleLevelPolicy.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/EditRestrictedDataByRoleLevelPolicy.java new file mode 100644 index 000000000..53c41fe91 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/EditRestrictedDataByRoleLevelPolicy.java @@ -0,0 +1,143 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.auth.policy; + +import javax.servlet.ServletContext; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle; +import edu.cornell.mannlib.vitro.webapp.auth.identifier.common.HasRoleLevel; +import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper; +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; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AbstractDataPropertyAction; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AbstractObjectPropertyAction; +import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel; + +/** + * Permit adding, editing, or deleting of various data based on the user's Role + * level and the restrictions in the ontology. + * + * This policy only authorizes users who are Editors, Curators or DBAs. + * Self-editors and users who are not logged in must look elsewhere for + * authorization. + */ +public class EditRestrictedDataByRoleLevelPolicy implements PolicyIface { + private static final Log log = LogFactory + .getLog(EditRestrictedDataByRoleLevelPolicy.class); + + private final ServletContext ctx; + + public EditRestrictedDataByRoleLevelPolicy(ServletContext ctx) { + this.ctx = ctx; + } + + /** + * If the requested action is to edit a property statement, we might + * authorize it based on their role level. + */ + @Override + public PolicyDecision isAuthorized(IdentifierBundle whoToAuth, + RequestedAction whatToAuth) { + if (whoToAuth == null) { + return defaultDecision("whomToAuth was null"); + } + if (whatToAuth == null) { + return defaultDecision("whatToAuth was null"); + } + + RoleLevel userRole = HasRoleLevel.getUsersRoleLevel(whoToAuth); + if (!userRoleIsHighEnough(userRole)) { + return defaultDecision("insufficient role level: " + userRole); + } + + PolicyDecision result; + if (whatToAuth instanceof AbstractDataPropertyAction) { + result = isAuthorized((AbstractDataPropertyAction) whatToAuth, + userRole); + } else if (whatToAuth instanceof AbstractObjectPropertyAction) { + result = isAuthorized((AbstractObjectPropertyAction) whatToAuth, + userRole); + } else { + result = defaultDecision("Unrecognized action"); + } + + log.debug("whoToAuth: " + whoToAuth); + log.debug("decision for '" + whatToAuth + "' is " + result); + return result; + } + + /** + * We only consider Editors, Curators and DBAs. + */ + private boolean userRoleIsHighEnough(RoleLevel userRole) { + return (userRole == RoleLevel.EDITOR) + || (userRole == RoleLevel.CURATOR) + || (userRole == RoleLevel.DB_ADMIN); + } + + /** + * The user may add, edit, or delete this data property if they are allowed + * to modify its subject and its predicate. + */ + private PolicyDecision isAuthorized(AbstractDataPropertyAction action, + RoleLevel userRole) { + String subjectUri = action.getSubjectUri(); + String predicateUri = action.getPredicateUri(); + if (canModifyResource(subjectUri, userRole) + && canModifyPredicate(predicateUri, userRole)) { + return authorized("user may modify DataPropertyStatement " + + subjectUri + " ==> " + predicateUri); + } else { + return defaultDecision("user may not modify DataPropertyStatement " + + subjectUri + " ==> " + predicateUri); + } + } + + /** + * The user may add, edit, or delete this data property if they are allowed + * to modify its subject, its predicate, and its object. + */ + private PolicyDecision isAuthorized(AbstractObjectPropertyAction action, + RoleLevel userRole) { + String subjectUri = action.getUriOfSubject(); + String predicateUri = action.getUriOfPredicate(); + String objectUri = action.getUriOfObject(); + if (canModifyResource(subjectUri, userRole) + && canModifyPredicate(predicateUri, userRole) + && canModifyResource(objectUri, userRole)) { + return authorized("user may modify ObjectPropertyStatement " + + subjectUri + " ==> " + predicateUri + " ==> " + objectUri); + } else { + return defaultDecision("user may not modify ObjectPropertyStatement " + + subjectUri + " ==> " + predicateUri + " ==> " + objectUri); + } + } + + /** If the user is explicitly authorized, return this. */ + private PolicyDecision authorized(String message) { + String className = this.getClass().getSimpleName(); + return new BasicPolicyDecision(Authorization.AUTHORIZED, className + + ": " + message); + } + + /** If the user isn't explicitly authorized, return this. */ + private PolicyDecision defaultDecision(String message) { + return new BasicPolicyDecision(Authorization.INCONCLUSIVE, message); + } + + private boolean canModifyResource(String uri, RoleLevel userRole) { + return PropertyRestrictionPolicyHelper.getBean(ctx).canModifyResource( + uri, userRole); + } + + private boolean canModifyPredicate(String uri, RoleLevel userRole) { + return PropertyRestrictionPolicyHelper.getBean(ctx).canModifyPredicate( + uri, userRole); + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/setup/CommonPolicyFamilySetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/setup/CommonPolicyFamilySetup.java index 2fca2f1ee..8735456ff 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/setup/CommonPolicyFamilySetup.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/setup/CommonPolicyFamilySetup.java @@ -13,6 +13,7 @@ import edu.cornell.mannlib.vitro.webapp.auth.identifier.ActiveIdentifierBundleFa import edu.cornell.mannlib.vitro.webapp.auth.identifier.common.CommonIdentifierBundleFactory; import edu.cornell.mannlib.vitro.webapp.auth.policy.DisplayRestrictedDataByRoleLevelPolicy; import edu.cornell.mannlib.vitro.webapp.auth.policy.DisplayRestrictedDataToSelfPolicy; +import edu.cornell.mannlib.vitro.webapp.auth.policy.EditRestrictedDataByRoleLevelPolicy; import edu.cornell.mannlib.vitro.webapp.auth.policy.ServletPolicyList; import edu.cornell.mannlib.vitro.webapp.auth.policy.UseRestrictedPagesByRoleLevelPolicy; import edu.cornell.mannlib.vitro.webapp.servlet.setup.AbortStartup; @@ -37,11 +38,14 @@ public class CommonPolicyFamilySetup implements ServletContextListener { new DisplayRestrictedDataByRoleLevelPolicy(ctx)); ServletPolicyList.addPolicy(ctx, new DisplayRestrictedDataToSelfPolicy(ctx)); + ServletPolicyList.addPolicy(ctx, + new EditRestrictedDataByRoleLevelPolicy(ctx)); ServletPolicyList.addPolicy(ctx, new UseRestrictedPagesByRoleLevelPolicy()); // This factory creates Identifiers for all of the above policies. - CommonIdentifierBundleFactory factory = new CommonIdentifierBundleFactory(ctx); + CommonIdentifierBundleFactory factory = new CommonIdentifierBundleFactory( + ctx); ActiveIdentifierBundleFactories.addFactory(sce, factory); } catch (Exception e) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/DatapropRetryController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/DatapropRetryController.java index 360c86b6e..ac926aa61 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/DatapropRetryController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/DatapropRetryController.java @@ -25,6 +25,7 @@ import edu.cornell.mannlib.vedit.forwarder.impl.UrlForwarder; import edu.cornell.mannlib.vedit.util.FormUtils; import edu.cornell.mannlib.vedit.validator.impl.IntValidator; import edu.cornell.mannlib.vedit.validator.impl.XMLNameValidator; +import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionListener; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditOntology; import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; @@ -121,7 +122,7 @@ public class DatapropRetryController extends BaseEditController { //set up any listeners List changeListenerList = new ArrayList(); - //changeListenerList.add(new PropertyRestrictionListener(getServletContext())); + changeListenerList.add(new PropertyRestrictionListener(getServletContext())); epo.setChangeListenerList(changeListenerList); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyRetryController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyRetryController.java index 8dd545df4..f039f9e90 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyRetryController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyRetryController.java @@ -28,6 +28,7 @@ import edu.cornell.mannlib.vedit.forwarder.PageForwarder; import edu.cornell.mannlib.vedit.forwarder.impl.UrlForwarder; import edu.cornell.mannlib.vedit.util.FormUtils; import edu.cornell.mannlib.vedit.validator.impl.XMLNameValidator; +import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionListener; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditOntology; import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; @@ -117,8 +118,7 @@ public class PropertyRetryController extends BaseEditController { //set up any listeners List changeListenerList = new ArrayList(); - //changeListenerList.add(new HiddenFromDisplayListener(getServletContext())); - //changeListenerList.add(new PropertyRestrictionListener(getServletContext())); + changeListenerList.add(new PropertyRestrictionListener(getServletContext())); epo.setChangeListenerList(changeListenerList); //make a postinsert pageforwarder that will send us to a new class's fetch screen