NIHVIVO-2492 A better implementation to allow RequiresAuthorizationFor this or that.
This commit is contained in:
parent
75377ae10e
commit
d246b7b9e0
5 changed files with 259 additions and 151 deletions
|
@ -7,8 +7,10 @@ import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -21,6 +23,7 @@ import org.apache.commons.logging.LogFactory;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.RequestIdentifiers;
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.RequestIdentifiers;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper.RequiresAuthorizationFor.NoAction;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper.RequiresAuthorizationFor.NoAction;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper.RequiresAuthorizationFor.Or;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
|
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.PolicyDecision;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
|
||||||
|
@ -41,6 +44,17 @@ public class PolicyHelper {
|
||||||
*
|
*
|
||||||
* Any RequestedAction can be specified, but the most common use will be to
|
* Any RequestedAction can be specified, but the most common use will be to
|
||||||
* specify implementations of UsePagesRequestedAction.
|
* specify implementations of UsePagesRequestedAction.
|
||||||
|
*
|
||||||
|
* Note that a combination of AND and OR relationships can be created
|
||||||
|
* (at-signs converted to #-signs, so Javadoc won't try to actually apply
|
||||||
|
* the annotations):
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* #RequiresAuthorizationFor(This.class)
|
||||||
|
* #RequiresAuthorizationFor({This.class, That.class})
|
||||||
|
* #RequiresAuthorizationFor(value=This.class, or=#Or(That.class))
|
||||||
|
* #RequiresAuthorizationFor(or={#Or(One_A.class, One_B.class), #Or(Two.class)})
|
||||||
|
* </pre>
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
|
@ -49,7 +63,14 @@ public class PolicyHelper {
|
||||||
/* no fields */
|
/* no fields */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public static @interface Or {
|
||||||
|
Class<? extends RequestedAction>[] value() default NoAction.class;
|
||||||
|
}
|
||||||
|
|
||||||
Class<? extends RequestedAction>[] value() default NoAction.class;
|
Class<? extends RequestedAction>[] value() default NoAction.class;
|
||||||
|
|
||||||
|
Or[] or() default @Or();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,7 +78,11 @@ public class PolicyHelper {
|
||||||
*/
|
*/
|
||||||
public static boolean isRestrictedPage(VitroHttpServlet servlet) {
|
public static boolean isRestrictedPage(VitroHttpServlet servlet) {
|
||||||
Class<? extends VitroHttpServlet> servletClass = servlet.getClass();
|
Class<? extends VitroHttpServlet> servletClass = servlet.getClass();
|
||||||
return !getRequiredAuthorizationsForServlet(servletClass).isEmpty();
|
try {
|
||||||
|
return !ActionClauses.forServletClass(servletClass).isEmpty();
|
||||||
|
} catch (PolicyHelperException e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,8 +91,7 @@ public class PolicyHelper {
|
||||||
*/
|
*/
|
||||||
public static boolean areRequiredAuthorizationsSatisfied(
|
public static boolean areRequiredAuthorizationsSatisfied(
|
||||||
HttpServletRequest req, VitroHttpServlet servlet) {
|
HttpServletRequest req, VitroHttpServlet servlet) {
|
||||||
Class<? extends VitroHttpServlet> servletClass = servlet.getClass();
|
return areRequiredAuthorizationsSatisfied(req, servlet.getClass());
|
||||||
return areRequiredAuthorizationsSatisfied(req, servletClass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,8 +101,12 @@ public class PolicyHelper {
|
||||||
public static boolean areRequiredAuthorizationsSatisfied(
|
public static boolean areRequiredAuthorizationsSatisfied(
|
||||||
HttpServletRequest req,
|
HttpServletRequest req,
|
||||||
Class<? extends VitroHttpServlet> servletClass) {
|
Class<? extends VitroHttpServlet> servletClass) {
|
||||||
return areRequiredAuthorizationsSatisfied(req,
|
try {
|
||||||
getRequiredAuthorizationsForServlet(servletClass));
|
return isActionClausesAuthorized(req,
|
||||||
|
ActionClauses.forServletClass(servletClass));
|
||||||
|
} catch (PolicyHelperException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,132 +115,183 @@ public class PolicyHelper {
|
||||||
*/
|
*/
|
||||||
public static boolean areRequiredAuthorizationsSatisfied(
|
public static boolean areRequiredAuthorizationsSatisfied(
|
||||||
HttpServletRequest req,
|
HttpServletRequest req,
|
||||||
Class<? extends RequestedAction>... actionClasses) {
|
Collection<Class<? extends RequestedAction>> actionClasses) {
|
||||||
List<Class<? extends RequestedAction>> classList = Arrays
|
try {
|
||||||
.asList(actionClasses);
|
return isActionClausesAuthorized(req, new ActionClauses(
|
||||||
|
actionClasses));
|
||||||
Set<RequestedAction> actions = instantiateActions(classList);
|
} catch (PolicyHelperException e) {
|
||||||
if (actions == null) {
|
|
||||||
log.debug("not authorized: failed to instantiate actions");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return areRequiredAuthorizationsSatisfied(req, actions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Are these actions authorized for the current user by the current
|
|
||||||
* policies?
|
|
||||||
*/
|
|
||||||
public static boolean areRequiredAuthorizationsSatisfied(
|
|
||||||
HttpServletRequest req,
|
|
||||||
Collection<? extends RequestedAction> actions) {
|
|
||||||
PolicyIface policy = ServletPolicyList.getPolicies(req);
|
|
||||||
IdentifierBundle ids = RequestIdentifiers.getIdBundleForRequest(req);
|
|
||||||
|
|
||||||
for (RequestedAction action : actions) {
|
|
||||||
if (isAuthorized(policy, ids, action)) {
|
|
||||||
log.debug("not authorized");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.debug("authorized");
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this action class authorized for the current user by the current
|
* Is this action class authorized for the current user by the current
|
||||||
* policies?
|
* policies?
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
public static boolean isActionAuthorized(HttpServletRequest req,
|
||||||
public static boolean isAuthorized(HttpServletRequest req,
|
|
||||||
Class<? extends RequestedAction> actionClass) {
|
Class<? extends RequestedAction> actionClass) {
|
||||||
return areRequiredAuthorizationsSatisfied(req, actionClass);
|
try {
|
||||||
|
return isActionClausesAuthorized(req,
|
||||||
|
new ActionClauses(actionClass));
|
||||||
|
} catch (PolicyHelperException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actions must be authorized for the current user by the current policies.
|
||||||
|
* If no actions, no problem.
|
||||||
|
*/
|
||||||
|
private static boolean isActionClausesAuthorized(HttpServletRequest req,
|
||||||
|
ActionClauses actionClauses) {
|
||||||
|
PolicyIface policy = ServletPolicyList.getPolicies(req);
|
||||||
|
IdentifierBundle ids = RequestIdentifiers.getIdBundleForRequest(req);
|
||||||
|
|
||||||
|
return actionClauses.isEmpty()
|
||||||
|
|| isActionClausesAuthorized(policy, ids, actionClauses);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Any clause in an ActionClauses may be authorized. */
|
||||||
|
private static boolean isActionClausesAuthorized(PolicyIface policy,
|
||||||
|
IdentifierBundle ids, ActionClauses actionClauses) {
|
||||||
|
for (Set<RequestedAction> clause : actionClauses.getClauseList()) {
|
||||||
|
if (isClauseAuthorized(policy, ids, clause)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** All actions in a clause must be authorized. */
|
||||||
|
private static boolean isClauseAuthorized(PolicyIface policy,
|
||||||
|
IdentifierBundle ids, Set<RequestedAction> clause) {
|
||||||
|
for (RequestedAction action : clause) {
|
||||||
|
if (!isActionAuthorized(policy, ids, action)) {
|
||||||
|
log.debug("not authorized");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this action authorized for these IDs by this policy?
|
* Is this action authorized for these IDs by this policy?
|
||||||
*/
|
*/
|
||||||
private static boolean isAuthorized(PolicyIface policy,
|
private static boolean isActionAuthorized(PolicyIface policy,
|
||||||
IdentifierBundle ids, RequestedAction action) {
|
IdentifierBundle ids, RequestedAction action) {
|
||||||
PolicyDecision decision = policy.isAuthorized(ids, action);
|
PolicyDecision decision = policy.isAuthorized(ids, action);
|
||||||
log.debug("decision for '" + action.getClass().getName() + "' was: "
|
log.debug("decision for '" + action.getClass().getName() + "' was: "
|
||||||
+ decision);
|
+ decision);
|
||||||
return (decision == null)
|
return (decision != null)
|
||||||
|| (decision.getAuthorized() != Authorization.AUTHORIZED);
|
&& (decision.getAuthorized() == Authorization.AUTHORIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* What RequestedActions does this servlet require authorization for?
|
* This helper class embodies the list of OR and AND relationships for the
|
||||||
|
* required authorizations. A group of AND relationships is a "clause", and
|
||||||
|
* the list of clauses are in an OR relationship.
|
||||||
*
|
*
|
||||||
* Keep this private, since it reveals how the Annotation is implemented. If
|
* Authorization is successful if ALL of the actions in ANY of the clauses
|
||||||
* we change the Annotation to include "or" and "and", then this method
|
* are authorized, or if there are NO clauses.
|
||||||
* becomes meaningless with its current return type.
|
*
|
||||||
|
* If any action can't be instantiated, throw an exception so authorization
|
||||||
|
* will fail.
|
||||||
*/
|
*/
|
||||||
private static Set<RequestedAction> getRequiredAuthorizationsForServlet(
|
private static class ActionClauses {
|
||||||
Class<? extends VitroHttpServlet> clazz) {
|
static ActionClauses forServletClass(
|
||||||
Set<RequestedAction> result = new HashSet<RequestedAction>();
|
Class<? extends VitroHttpServlet> servletClass)
|
||||||
|
throws PolicyHelperException {
|
||||||
|
return new ActionClauses(
|
||||||
|
servletClass.getAnnotation(RequiresAuthorizationFor.class));
|
||||||
|
}
|
||||||
|
|
||||||
RequiresAuthorizationFor annotation = clazz
|
private final List<Set<RequestedAction>> clauseList;
|
||||||
.getAnnotation(RequiresAuthorizationFor.class);
|
|
||||||
|
|
||||||
if (annotation != null) {
|
ActionClauses(RequiresAuthorizationFor annotation)
|
||||||
for (Class<? extends RequestedAction> actionClass : annotation
|
throws PolicyHelperException {
|
||||||
.value()) {
|
List<Set<RequestedAction>> list = new ArrayList<Set<RequestedAction>>();
|
||||||
if (NoAction.class != actionClass) {
|
if (annotation != null) {
|
||||||
RequestedAction action = instantiateAction(actionClass);
|
addClause(list, annotation.value());
|
||||||
if (action != null) {
|
for (Or orAnnotation : annotation.or()) {
|
||||||
result.add(action);
|
addClause(list, orAnnotation.value());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.clauseList = Collections.unmodifiableList(list);
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
ActionClauses(Collection<Class<? extends RequestedAction>> actionClasses)
|
||||||
* Instantiate actions from their classes. If any one of the classes cannot
|
throws PolicyHelperException {
|
||||||
* be instantiated, return null.
|
this.clauseList = Collections
|
||||||
*/
|
.singletonList(buildClause(actionClasses));
|
||||||
private static Set<RequestedAction> instantiateActions(
|
}
|
||||||
Collection<Class<? extends RequestedAction>> actionClasses) {
|
|
||||||
Set<RequestedAction> actions = new HashSet<RequestedAction>();
|
ActionClauses(Class<? extends RequestedAction> actionClass)
|
||||||
for (Class<? extends RequestedAction> actionClass : actionClasses) {
|
throws PolicyHelperException {
|
||||||
RequestedAction action = instantiateAction(actionClass);
|
this.clauseList = Collections.singletonList(Collections
|
||||||
if (action == null) {
|
.singleton(instantiateAction(actionClass)));
|
||||||
return null;
|
}
|
||||||
} else {
|
|
||||||
actions.add(action);
|
private void addClause(List<Set<RequestedAction>> list,
|
||||||
|
Class<? extends RequestedAction>[] actionClasses)
|
||||||
|
throws PolicyHelperException {
|
||||||
|
Set<RequestedAction> clause = buildClause(Arrays
|
||||||
|
.asList(actionClasses));
|
||||||
|
if (!clause.isEmpty()) {
|
||||||
|
list.add(clause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return actions;
|
|
||||||
|
private Set<RequestedAction> buildClause(
|
||||||
|
Collection<Class<? extends RequestedAction>> actionClasses)
|
||||||
|
throws PolicyHelperException {
|
||||||
|
Set<RequestedAction> clause = new HashSet<RequestedAction>();
|
||||||
|
for (Class<? extends RequestedAction> actionClass : actionClasses) {
|
||||||
|
if (!NoAction.class.equals(actionClass)) {
|
||||||
|
clause.add(instantiateAction(actionClass));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableSet(clause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an instance of the RequestedAction, from its class, or throw an
|
||||||
|
* exception.
|
||||||
|
*/
|
||||||
|
private RequestedAction instantiateAction(
|
||||||
|
Class<? extends RequestedAction> actionClass)
|
||||||
|
throws PolicyHelperException {
|
||||||
|
try {
|
||||||
|
Constructor<? extends RequestedAction> constructor = actionClass
|
||||||
|
.getConstructor();
|
||||||
|
RequestedAction instance = constructor.newInstance();
|
||||||
|
return instance;
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
log.error("'" + actionClass.getName()
|
||||||
|
+ "' does not have a no-argument constructor.");
|
||||||
|
throw new PolicyHelperException();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
log.error("The no-argument constructor for '"
|
||||||
|
+ actionClass.getName() + "' is not public.");
|
||||||
|
throw new PolicyHelperException();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to instantiate '" + actionClass.getName()
|
||||||
|
+ "'", e);
|
||||||
|
throw new PolicyHelperException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isEmpty() {
|
||||||
|
return this.clauseList.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Set<RequestedAction>> getClauseList() {
|
||||||
|
return this.clauseList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** We failed to instantiate a RequestedAction */
|
||||||
* Get an instance of the RequestedAction, from its class. If the class
|
private static class PolicyHelperException extends Exception {
|
||||||
* cannot be instantiated, return null.
|
// no members
|
||||||
*/
|
|
||||||
private static RequestedAction instantiateAction(
|
|
||||||
Class<? extends RequestedAction> actionClass) {
|
|
||||||
try {
|
|
||||||
Constructor<? extends RequestedAction> constructor = actionClass
|
|
||||||
.getConstructor();
|
|
||||||
RequestedAction instance = constructor.newInstance();
|
|
||||||
return instance;
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
log.error("'" + actionClass.getName()
|
|
||||||
+ "' does not have a no-argument constructor.");
|
|
||||||
return null;
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
log.error("The no-argument constructor for '"
|
|
||||||
+ actionClass.getName() + "' is not public.");
|
|
||||||
return null;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Failed to instantiate '" + actionClass.getName() + "'",
|
|
||||||
e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -69,8 +69,10 @@ public class VitroHttpServlet extends HttpServlet {
|
||||||
if (!PolicyHelper.areRequiredAuthorizationsSatisfied(hreq, this)) {
|
if (!PolicyHelper.areRequiredAuthorizationsSatisfied(hreq, this)) {
|
||||||
if (LoginStatusBean.getBean(hreq).isLoggedIn()) {
|
if (LoginStatusBean.getBean(hreq).isLoggedIn()) {
|
||||||
redirectToInsufficientAuthorizationPage(hreq, hresp);
|
redirectToInsufficientAuthorizationPage(hreq, hresp);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
redirectToLoginPage(hreq, hresp);
|
redirectToLoginPage(hreq, hresp);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,37 +166,6 @@ public class VitroHttpServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* If none of these actions are authorized by the current policy, redirect
|
|
||||||
* them to the appropriate page.
|
|
||||||
*
|
|
||||||
* Currently the RequiresAuthorizationFor annotation can't handle "or"
|
|
||||||
* situations, so we need to do an explicit call to this method. You should
|
|
||||||
* still use the annotation with no actions, so we know this is a restricted
|
|
||||||
* page when we logout.
|
|
||||||
*/
|
|
||||||
public static boolean checkIfAnyActionsAreAuthorized(
|
|
||||||
HttpServletRequest request, HttpServletResponse response,
|
|
||||||
Class<? extends RequestedAction>... actionClasses) {
|
|
||||||
for (Class<? extends RequestedAction> actionClass : actionClasses) {
|
|
||||||
if (PolicyHelper.isAuthorized(request, actionClass)) {
|
|
||||||
log.trace("Authorized for '" + actionClass.getSimpleName()
|
|
||||||
+ "'");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LoginStatusBean statusBean = LoginStatusBean.getBean(request);
|
|
||||||
if (statusBean.isLoggedIn()) {
|
|
||||||
log.trace("Authorization is insufficient for requested actions");
|
|
||||||
redirectToInsufficientAuthorizationPage(request, response);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
log.trace("Not logged in; not sufficient for requested actions");
|
|
||||||
redirectToLoginPage(request, response);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logged in, but with insufficent authorization. Send them to the home page
|
* Logged in, but with insufficent authorization. Send them to the home page
|
||||||
* with a message. They won't be coming back.
|
* with a message. They won't be coming back.
|
||||||
|
|
|
@ -20,6 +20,7 @@ import com.hp.hpl.jena.shared.Lock;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vedit.controller.BaseEditController;
|
import edu.cornell.mannlib.vedit.controller.BaseEditController;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper.RequiresAuthorizationFor;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper.RequiresAuthorizationFor;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper.RequiresAuthorizationFor.Or;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.UseAdvancedDataToolsPages;
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.UseAdvancedDataToolsPages;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.UseOntologyEditorPages;
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.UseOntologyEditorPages;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
|
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
|
||||||
|
@ -28,17 +29,13 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.JenaModelUtils;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext;
|
import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext;
|
||||||
import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase;
|
import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase;
|
||||||
|
|
||||||
@RequiresAuthorizationFor(/* either-or; see call to checkIfAnyActionsAreAuthorized */)
|
@RequiresAuthorizationFor(or={@Or(UseAdvancedDataToolsPages.class), @Or(UseOntologyEditorPages.class)})
|
||||||
public class JenaExportController extends BaseEditController {
|
public class JenaExportController extends BaseEditController {
|
||||||
|
|
||||||
|
@Override
|
||||||
public void doGet( HttpServletRequest request, HttpServletResponse response ) {
|
public void doGet( HttpServletRequest request, HttpServletResponse response ) {
|
||||||
VitroRequest vreq = new VitroRequest(request);
|
VitroRequest vreq = new VitroRequest(request);
|
||||||
|
|
||||||
if (!checkIfAnyActionsAreAuthorized(vreq, response,
|
|
||||||
UseAdvancedDataToolsPages.class, UseOntologyEditorPages.class)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( vreq.getRequestURL().indexOf("/download/") > -1 ) {
|
if ( vreq.getRequestURL().indexOf("/download/") > -1 ) {
|
||||||
outputRDF( vreq, response );
|
outputRDF( vreq, response );
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.web.jsptags;
|
package edu.cornell.mannlib.vitro.webapp.web.jsptags;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -57,12 +56,12 @@ public class RequiresAuthorizationFor extends BodyTagSupport {
|
||||||
* are authorized for those actions.
|
* are authorized for those actions.
|
||||||
*/
|
*/
|
||||||
private boolean isAuthorized() {
|
private boolean isAuthorized() {
|
||||||
Collection<RequestedAction> actions = instantiateActions();
|
Set<Class<? extends RequestedAction>> classes = instantiateActionClasses();
|
||||||
if (actions == null) {
|
if (classes == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return PolicyHelper.areRequiredAuthorizationsSatisfied(getRequest(),
|
return PolicyHelper.areRequiredAuthorizationsSatisfied(getRequest(),
|
||||||
actions);
|
classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,18 +70,13 @@ public class RequiresAuthorizationFor extends BodyTagSupport {
|
||||||
*
|
*
|
||||||
* If we can't do all of that, complain and return null.
|
* If we can't do all of that, complain and return null.
|
||||||
*/
|
*/
|
||||||
private Set<RequestedAction> instantiateActions() {
|
private Set<Class<? extends RequestedAction>> instantiateActionClasses() {
|
||||||
Set<String> classNames = parseClassNames();
|
Set<String> classNames = parseClassNames();
|
||||||
if (classNames.isEmpty()) {
|
if (classNames.isEmpty()) {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<Class<? extends RequestedAction>> actionClasses = loadClassesAndCheckTypes(classNames);
|
return loadClassesAndCheckTypes(classNames);
|
||||||
if (actionClasses == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return getInstancesFromClasses(actionClasses);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<String> parseClassNames() {
|
private Set<String> parseClassNames() {
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.auth.policy;
|
package edu.cornell.mannlib.vitro.webapp.auth.policy;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -18,6 +19,7 @@ import stubs.javax.servlet.http.HttpSessionStub;
|
||||||
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
|
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper.RequiresAuthorizationFor;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper.RequiresAuthorizationFor;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper.RequiresAuthorizationFor.Or;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
|
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.PolicyDecision;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
|
||||||
|
@ -80,21 +82,70 @@ public class PolicyHelperTest extends AbstractTestClass {
|
||||||
public void twoRequirementsFailOne() {
|
public void twoRequirementsFailOne() {
|
||||||
createPolicy(new Action1());
|
createPolicy(new Action1());
|
||||||
assertExpectedAuthorization("requires Actions 1 and 2",
|
assertExpectedAuthorization("requires Actions 1 and 2",
|
||||||
Action1Action2Servlet.class, false);
|
Action1AndAction2Servlet.class, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void twoRequirementsFailTwo() {
|
public void twoRequirementsFailTwo() {
|
||||||
createPolicy(new Action2());
|
createPolicy(new Action2());
|
||||||
assertExpectedAuthorization("requires Actions 1 and 2",
|
assertExpectedAuthorization("requires Actions 1 and 2",
|
||||||
Action1Action2Servlet.class, false);
|
Action1AndAction2Servlet.class, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void twoRequirementsSucceed() {
|
public void twoRequirementsSucceed() {
|
||||||
createPolicy(new Action2(), new Action1());
|
createPolicy(new Action2(), new Action1());
|
||||||
assertExpectedAuthorization("requires Actions 1 and 2",
|
assertExpectedAuthorization("requires Actions 1 and 2",
|
||||||
Action1Action2Servlet.class, true);
|
Action1AndAction2Servlet.class, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void oneOrTwoFail() {
|
||||||
|
createPolicy();
|
||||||
|
assertExpectedAuthorization("requires Action 1 or 2",
|
||||||
|
Action1OrAction2Servlet.class, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void oneOrTwoSucceedOne() {
|
||||||
|
createPolicy(new Action1());
|
||||||
|
assertExpectedAuthorization("requires Action 1 or 2",
|
||||||
|
Action1OrAction2Servlet.class, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void oneOrTwoSucceedTwo() {
|
||||||
|
createPolicy(new Action2());
|
||||||
|
assertExpectedAuthorization("requires Action 1 or 2",
|
||||||
|
Action1OrAction2Servlet.class, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void oneOrTwoOrThreeFail() {
|
||||||
|
createPolicy();
|
||||||
|
assertExpectedAuthorization("requires Action 1 or 2 or 3",
|
||||||
|
Action1OrAction2OrAction3Servlet.class, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void oneOrTwoOrThreeSucceedOne() {
|
||||||
|
createPolicy(new Action1());
|
||||||
|
assertExpectedAuthorization("requires Action 1 or 2 or 3",
|
||||||
|
Action1OrAction2OrAction3Servlet.class, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void oneOrTwoOrThreeSucceedTwo() {
|
||||||
|
createPolicy(new Action2());
|
||||||
|
assertExpectedAuthorization("requires Action 1 or 2 or 3",
|
||||||
|
Action1OrAction2OrAction3Servlet.class, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void oneOrTwoOrThreeSucceedThree() {
|
||||||
|
createPolicy(new Action3());
|
||||||
|
assertExpectedAuthorization("requires Action 1 or 2 or 3",
|
||||||
|
Action1OrAction2OrAction3Servlet.class, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
@ -124,6 +175,10 @@ public class PolicyHelperTest extends AbstractTestClass {
|
||||||
// actions must be public, with public constructor
|
// actions must be public, with public constructor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Action3 extends RequestedAction {
|
||||||
|
// actions must be public, with public constructor
|
||||||
|
}
|
||||||
|
|
||||||
// no annotation
|
// no annotation
|
||||||
private static class NoAnnotationServlet extends VitroHttpServlet {
|
private static class NoAnnotationServlet extends VitroHttpServlet {
|
||||||
/* no body */
|
/* no body */
|
||||||
|
@ -140,7 +195,19 @@ public class PolicyHelperTest extends AbstractTestClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresAuthorizationFor({ Action1.class, Action2.class })
|
@RequiresAuthorizationFor({ Action1.class, Action2.class })
|
||||||
private static class Action1Action2Servlet extends VitroHttpServlet {
|
private static class Action1AndAction2Servlet extends VitroHttpServlet {
|
||||||
|
/* no body */
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresAuthorizationFor(value = Action1.class, or = @Or(Action2.class))
|
||||||
|
private static class Action1OrAction2Servlet extends VitroHttpServlet {
|
||||||
|
/* no body */
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresAuthorizationFor(value = Action1.class, or = { @Or(Action2.class),
|
||||||
|
@Or(Action3.class) })
|
||||||
|
private static class Action1OrAction2OrAction3Servlet extends
|
||||||
|
VitroHttpServlet {
|
||||||
/* no body */
|
/* no body */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue