diff --git a/webapp/config/tlds/VitroUtils.tld b/webapp/config/tlds/VitroUtils.tld
index 562c9c0de..401185a7f 100644
--- a/webapp/config/tlds/VitroUtils.tld
+++ b/webapp/config/tlds/VitroUtils.tld
@@ -49,4 +49,33 @@
+
+ requiresAuthorizationFor
+ Confirm that the user is authorized for the actions that this page requires.
+
+ Confirm that the user is authorized to perform all of the RequestedActions that
+ this page requires. A check is done for each such action, to see whether the
+ current policy will authorize that action for the current user. If any of the
+ actions is not authorized, the user will be redirected to the appropriate page.
+
+ If the user is not authorized because he is not logged in, he will be directed
+ to the login page, with the current request stored as a post-login destination.
+
+ If the user is logged in but without sufficient authorization, he will be
+ directed to the home page, which will display an "insufficient authorization"
+ message.
+
+ The requested actions are specified as a comma delimited list of names (with
+ optional spaces). These names must match against the map of classes in
+ JspPolicyHelper, or an error will be logged and the authorization will fail.
+
+ edu.cornell.mannlib.vitro.webapp.web.jsptags.RequiresAuthorizationFor
+ empty
+
+ actions
+ true
+ true
+
+
+
\ No newline at end of file
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper.java
new file mode 100644
index 000000000..5cc7a94b1
--- /dev/null
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper.java
@@ -0,0 +1,211 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.auth.policy;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Constructor;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+
+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.RequestIdentifiers;
+import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper.RequiresAuthorizationFor.NoAction;
+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.controller.VitroHttpServlet;
+
+/**
+ * A collection of static methods to help determine whether requested actions
+ * are authorized by current policy.
+ */
+public class PolicyHelper {
+ private static final Log log = LogFactory.getLog(PolicyHelper.class);
+
+ /**
+ * A subclass of VitroHttpServlet may be annotated to say what actions
+ * should be checked for authorization before permitting the user to view
+ * the page that the servlet would create.
+ *
+ * Any RequestedAction can be specified, but the most common use will be to
+ * specify implementations of UsePagesRequestedAction.
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.TYPE)
+ public static @interface RequiresAuthorizationFor {
+ static class NoAction extends RequestedAction {
+ /* no fields */
+ }
+
+ Class extends RequestedAction>[] value() default NoAction.class;
+ }
+
+ /**
+ * Does this servlet require authorization?
+ */
+ public static boolean isRestrictedPage(VitroHttpServlet servlet) {
+ Class extends VitroHttpServlet> servletClass = servlet.getClass();
+ return !getRequiredAuthorizationsForServlet(servletClass).isEmpty();
+ }
+
+ /**
+ * What RequestedActions does this servlet require authorization for?
+ */
+ public static Set getRequiredAuthorizationsForServlet(
+ Class extends VitroHttpServlet> clazz) {
+ Set result = new HashSet();
+
+ RequiresAuthorizationFor annotation = clazz
+ .getAnnotation(RequiresAuthorizationFor.class);
+
+ if (annotation != null) {
+ for (Class extends RequestedAction> actionClass : annotation
+ .value()) {
+ if (NoAction.class != actionClass) {
+ RequestedAction action = instantiateAction(actionClass);
+ if (action != null) {
+ result.add(action);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Are the actions that this servlet requires authorized for the current
+ * user by the current policies?
+ */
+ public static boolean areRequiredAuthorizationsSatisfied(
+ HttpServletRequest req, VitroHttpServlet servlet) {
+ Class extends VitroHttpServlet> servletClass = servlet.getClass();
+ return areRequiredAuthorizationsSatisfied(req,
+ getRequiredAuthorizationsForServlet(servletClass));
+ }
+
+ /**
+ * Are these action classes authorized for the current user by the current
+ * policies?
+ */
+ public static boolean areRequiredAuthorizationsSatisfied(
+ HttpServletRequest req,
+ Class extends RequestedAction>... actionClasses) {
+ List> classList = Arrays
+ .asList(actionClasses);
+
+ Set actions = instantiateActions(classList);
+ if (actions == null) {
+ log.debug("not authorized: failed to instantiate actions");
+ 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
+ * policies?
+ */
+ @SuppressWarnings("unchecked")
+ public static boolean isAuthorized(HttpServletRequest req,
+ Class extends RequestedAction> actionClass) {
+ return areRequiredAuthorizationsSatisfied(req, actionClass);
+ }
+
+ /**
+ * Is this action authorized for these IDs by this policy?
+ */
+ private static boolean isAuthorized(PolicyIface policy,
+ IdentifierBundle ids, RequestedAction action) {
+ PolicyDecision decision = policy.isAuthorized(ids, action);
+ log.debug("decision for '" + action.getClass().getName() + "' was: "
+ + decision);
+ return (decision == null)
+ || (decision.getAuthorized() != Authorization.AUTHORIZED);
+ }
+
+ /**
+ * Instantiate actions from their classes. If any one of the classes cannot
+ * be instantiated, return null.
+ */
+ private static Set instantiateActions(
+ Collection> actionClasses) {
+ Set actions = new HashSet();
+ for (Class extends RequestedAction> actionClass : actionClasses) {
+ RequestedAction action = instantiateAction(actionClass);
+ if (action == null) {
+ return null;
+ } else {
+ actions.add(action);
+ }
+ }
+ return actions;
+ }
+
+ /**
+ * Get an instance of the RequestedAction, from its class. If the class
+ * cannot be instantiated, return null.
+ */
+ 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;
+ }
+ }
+
+ /**
+ * No need to instantiate this helper class - all methods are static.
+ */
+ private PolicyHelper() {
+ // nothing to do.
+ }
+
+}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/UseRestrictedPagesByRoleLevelPolicy.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/UseRestrictedPagesByRoleLevelPolicy.java
new file mode 100644
index 000000000..fea9d3788
--- /dev/null
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/UseRestrictedPagesByRoleLevelPolicy.java
@@ -0,0 +1,92 @@
+/* $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.HasRoleLevel;
+import edu.cornell.mannlib.vitro.webapp.auth.identifier.Identifier;
+import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
+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.usepages.UseAdvancedDataToolsPages;
+import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
+
+/**
+ * Check the users role level to determine whether they are allowed to use
+ * restricted pages.
+ */
+public class UseRestrictedPagesByRoleLevelPolicy implements PolicyIface {
+ private static final Log log = LogFactory
+ .getLog(UseRestrictedPagesByRoleLevelPolicy.class);
+
+ @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 = getUsersRoleLevel(whoToAuth);
+
+ PolicyDecision result;
+ if (whatToAuth instanceof UseAdvancedDataToolsPages) {
+ result = isAuthorized(whatToAuth, RoleLevel.DB_ADMIN, userRole);
+ } else {
+ result = defaultDecision("Unrecognized action");
+ }
+
+ log.debug("decision for '" + whatToAuth + "' is " + result);
+ return result;
+ }
+
+ private PolicyDecision isAuthorized(RequestedAction whatToAuth,
+ RoleLevel requiredRole, RoleLevel currentRole) {
+ if (isRoleAtLeast(requiredRole, currentRole)) {
+ return authorized("User may view page: " + whatToAuth
+ + ", requiredRole=" + requiredRole + ", currentRole="
+ + currentRole);
+ } else {
+ return defaultDecision("User may not view page: " + whatToAuth
+ + ", requiredRole=" + requiredRole + ", currentRole="
+ + currentRole);
+ }
+ }
+
+ private boolean isRoleAtLeast(RoleLevel required, RoleLevel current) {
+ return (current.compareTo(required) >= 0);
+ }
+
+ /** 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);
+ }
+
+ /**
+ * The user is nobody unless they have a HasRoleLevel identifier.
+ */
+ private RoleLevel getUsersRoleLevel(IdentifierBundle whoToAuth) {
+ RoleLevel userRole = RoleLevel.PUBLIC;
+ for (Identifier id : whoToAuth) {
+ if (id instanceof HasRoleLevel) {
+ userRole = ((HasRoleLevel) id).getRoleLevel();
+ }
+ }
+ return 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 ff6eee6e4..94f0623f3 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
@@ -14,6 +14,7 @@ import edu.cornell.mannlib.vitro.webapp.auth.identifier.CommonIdentifierBundleFa
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.ServletPolicyList;
+import edu.cornell.mannlib.vitro.webapp.auth.policy.UseRestrictedPagesByRoleLevelPolicy;
import edu.cornell.mannlib.vitro.webapp.servlet.setup.AbortStartup;
/**
@@ -36,6 +37,8 @@ public class CommonPolicyFamilySetup implements ServletContextListener {
new DisplayRestrictedDataByRoleLevelPolicy(ctx));
ServletPolicyList.addPolicy(ctx,
new DisplayRestrictedDataToSelfPolicy(ctx));
+ ServletPolicyList.addPolicy(ctx,
+ new UseRestrictedPagesByRoleLevelPolicy());
// This factory creates Identifiers for all of the above policies.
CommonIdentifierBundleFactory factory = new CommonIdentifierBundleFactory();
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/ifaces/RequestedAction.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/ifaces/RequestedAction.java
index f2616104c..b22a3e5c6 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/ifaces/RequestedAction.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/ifaces/RequestedAction.java
@@ -12,4 +12,8 @@ public abstract class RequestedAction {
return RequestActionConstants.actionNamespace + this.getClass().getName();
}
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/usepages/UseAdvancedDataToolsPages.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/usepages/UseAdvancedDataToolsPages.java
new file mode 100644
index 000000000..221585671
--- /dev/null
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/usepages/UseAdvancedDataToolsPages.java
@@ -0,0 +1,11 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages;
+
+import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
+
+/** Should we allow the user to use the pages for Advanced Data Tools? */
+public class UseAdvancedDataToolsPages extends RequestedAction implements
+ UsePagesRequestedAction {
+ // no fields
+}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/usepages/UsePagesRequestedAction.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/usepages/UsePagesRequestedAction.java
new file mode 100644
index 000000000..313cdbc60
--- /dev/null
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/usepages/UsePagesRequestedAction.java
@@ -0,0 +1,8 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages;
+
+/** Denotes a request to use a particular page or group of pages. */
+public interface UsePagesRequestedAction {
+ /** marker interface */
+}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/VitroHttpServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/VitroHttpServlet.java
index e5fc45116..a94b19d5c 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/VitroHttpServlet.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/VitroHttpServlet.java
@@ -23,6 +23,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
+import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage;
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.LogoutRedirector;
@@ -44,6 +45,38 @@ public class VitroHttpServlet extends HttpServlet {
public final static String TTL_MIMETYPE = "text/turtle"; // unofficial and
// unregistered
+ /**
+ * Check that any required authorizations are satisfied before processing
+ * the request.
+ */
+ @Override
+ public final void service(ServletRequest req, ServletResponse resp)
+ throws ServletException, IOException {
+ if ((req instanceof HttpServletRequest)
+ && (resp instanceof HttpServletResponse)) {
+ HttpServletRequest hreq = (HttpServletRequest) req;
+ HttpServletResponse hresp = (HttpServletResponse) resp;
+
+ if (log.isTraceEnabled()) {
+ dumpRequestHeaders(hreq);
+ }
+
+ if (PolicyHelper.isRestrictedPage(this)) {
+ LogoutRedirector.recordRestrictedPageUri(hreq);
+ }
+
+ if (!PolicyHelper.areRequiredAuthorizationsSatisfied(hreq, this)) {
+ if (LoginStatusBean.getBean(hreq).isLoggedIn()) {
+ redirectToInsufficientAuthorizationPage(hreq, hresp);
+ } else {
+ redirectToLoginPage(hreq, hresp);
+ }
+ }
+ }
+
+ super.service(req, resp);
+ }
+
/**
* Show this to the user if they are logged in, but still not authorized to
* view the page.
@@ -87,6 +120,8 @@ public class VitroHttpServlet extends HttpServlet {
/**
* If not logged in, redirect them to the login page.
+ *
+ * TODO this goes away as it is replace by annotations.
*/
public static boolean checkLoginStatus(HttpServletRequest request,
HttpServletResponse response) {
@@ -104,6 +139,8 @@ public class VitroHttpServlet extends HttpServlet {
/**
* If not logged in at the required level, redirect them to the appropriate
* page.
+ *
+ * TODO this goes away as it is replace by annotations.
*/
public static boolean checkLoginStatus(HttpServletRequest request,
HttpServletResponse response, int minimumLevel) {
@@ -183,24 +220,17 @@ public class VitroHttpServlet extends HttpServlet {
* If logging is set to the TRACE level, dump the HTTP headers on the
* request.
*/
- @SuppressWarnings("unchecked")
- @Override
- public void service(ServletRequest req, ServletResponse resp)
- throws ServletException, IOException {
- if (log.isTraceEnabled()) {
- HttpServletRequest request = (HttpServletRequest) req;
- Enumeration names = request.getHeaderNames();
- log.trace("----------------------request:"
- + request.getRequestURL());
- while (names.hasMoreElements()) {
- String name = names.nextElement();
- if (!BORING_HEADERS.contains(name)) {
- log.trace(name + "=" + request.getHeader(name));
- }
+ private void dumpRequestHeaders(HttpServletRequest req) {
+ @SuppressWarnings("unchecked")
+ Enumeration names = req.getHeaderNames();
+
+ log.trace("----------------------request:" + req.getRequestURL());
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ if (!BORING_HEADERS.contains(name)) {
+ log.trace(name + "=" + req.getHeader(name));
}
}
-
- super.service(req, resp);
}
/** Don't dump the contents of these headers, even if log.trace is enabled. */
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/ConfirmLoginStatus.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/ConfirmLoginStatus.java
index 699ff3fc0..1a83cff66 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/ConfirmLoginStatus.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/ConfirmLoginStatus.java
@@ -16,13 +16,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.authenticate.LogoutRedirector
import edu.cornell.mannlib.vitro.webapp.filters.VitroRequestPrep;
/**
- * JSP tag to generate the HTML of links for edit, delete or add of a Property.
- *
- * Maybe we should have a mode where it just sets a var to a map with "href" =
- * "edit/editDatapropDispatch.jsp?subjectUri=..." and "type" = "delete"
- *
- * @author bdc34
- *
+ * TODO This should go away as it is replaced by vitro:requiresAuthorizationFor
*/
public class ConfirmLoginStatus extends BodyTagSupport {
private static final Log log = LogFactory.getLog(ConfirmLoginStatus.class);
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/RequiresAuthorizationFor.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/RequiresAuthorizationFor.java
new file mode 100644
index 000000000..9fc8d7a84
--- /dev/null
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/RequiresAuthorizationFor.java
@@ -0,0 +1,125 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.web.jsptags;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.BodyTagSupport;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
+import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
+import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
+import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.UseAdvancedDataToolsPages;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
+
+/**
+ * Confirm that the user is authorized to perform each of the RequestedActions.
+ *
+ * The user specifies the actions as a comma delimited list of names (with
+ * optional spaces). These names are matched against the map of recognized
+ * names. If no match is found, an error is logged and the authorization fails.
+ */
+public class RequiresAuthorizationFor extends BodyTagSupport {
+ private static final Log log = LogFactory
+ .getLog(RequiresAuthorizationFor.class);
+
+ /**
+ * These are the only action names that we recognize.
+ */
+ private static final Map actionMap = new HashMap();
+ static {
+ actionMap.put("UseAdvancedDataToolsPages",
+ new UseAdvancedDataToolsPages());
+ }
+
+ String actionNames = "";
+
+ public void setActions(String actionNames) {
+ this.actionNames = actionNames;
+ }
+
+ /**
+ * This is all of it. If they are authorized, continue. Otherwise, redirect.
+ */
+ @Override
+ public int doEndTag() throws JspException {
+ if (isAuthorized()) {
+ return EVAL_PAGE;
+ } else if (isLoggedIn()) {
+ return showInsufficientAuthorizationMessage();
+ } else {
+ return redirectToLoginPage();
+ }
+ }
+
+ /**
+ * They are authorized if we recognize the actions they ask for, and they
+ * are authorized for those actions.
+ */
+ private boolean isAuthorized() {
+ Collection actions = parseActionNames();
+ if (actions == null) {
+ return false;
+ }
+ return PolicyHelper.areRequiredAuthorizationsSatisfied(getRequest(),
+ actions);
+ }
+
+ /**
+ * Parse the string and pull the corresponding actions from the map. If we
+ * can't do that, complain and return null.
+ */
+ private Collection parseActionNames() {
+ Set actions = new HashSet();
+
+ for (String part : actionNames.split("[\\s],[\\s]")) {
+ String key = part.trim();
+ if (key.isEmpty()) {
+ continue;
+ }
+
+ if (actionMap.containsKey(key)) {
+ log.debug("checking authorization for '" + key + "'");
+ actions.add(actionMap.get(key));
+ } else {
+ log.error("JSP requested authorization for unknown action: '"
+ + key + "'");
+ return null;
+ }
+ }
+ return actions;
+ }
+
+ private boolean isLoggedIn() {
+ return LoginStatusBean.getBean(getRequest()).isLoggedIn();
+ }
+
+ private int showInsufficientAuthorizationMessage() {
+ VitroHttpServlet.redirectToInsufficientAuthorizationPage(getRequest(),
+ getResponse());
+ return SKIP_PAGE;
+ }
+
+ private int redirectToLoginPage() throws JspException {
+ VitroHttpServlet.redirectToLoginPage(getRequest(), getResponse());
+ return SKIP_PAGE;
+ }
+
+ private HttpServletRequest getRequest() {
+ return ((HttpServletRequest) pageContext.getRequest());
+ }
+
+ private HttpServletResponse getResponse() {
+ return (HttpServletResponse) pageContext.getResponse();
+ }
+}