NIHVIVO-2492 Second try at the JSP custom tag - it requires the fully-qualified class name, but it behaves in a much more robust way.
This commit is contained in:
parent
6375161d5a
commit
ee81ecfa9b
2 changed files with 68 additions and 37 deletions
|
@ -65,14 +65,14 @@
|
||||||
directed to the home page, which will display an "insufficient authorization"
|
directed to the home page, which will display an "insufficient authorization"
|
||||||
message.
|
message.
|
||||||
|
|
||||||
The requested actions are specified as a comma delimited list of names (with
|
The requested actions are specified as a comma delimited list of class names.
|
||||||
optional spaces). These names must match against the map of classes in
|
These must be RequestedAction classes, each with a no-argument public
|
||||||
JspPolicyHelper, or an error will be logged and the authorization will fail.
|
constructor.
|
||||||
</description>
|
</description>
|
||||||
<tag-class>edu.cornell.mannlib.vitro.webapp.web.jsptags.RequiresAuthorizationFor</tag-class>
|
<tag-class>edu.cornell.mannlib.vitro.webapp.web.jsptags.RequiresAuthorizationFor</tag-class>
|
||||||
<body-content>empty</body-content>
|
<body-content>empty</body-content>
|
||||||
<attribute>
|
<attribute>
|
||||||
<name>actions</name>
|
<name>classNames</name>
|
||||||
<required>true</required>
|
<required>true</required>
|
||||||
<rtexprvalue>true</rtexprvalue>
|
<rtexprvalue>true</rtexprvalue>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
package edu.cornell.mannlib.vitro.webapp.web.jsptags;
|
package edu.cornell.mannlib.vitro.webapp.web.jsptags;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
@ -19,33 +18,24 @@ import org.apache.commons.logging.LogFactory;
|
||||||
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
|
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
|
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.ifaces.RequestedAction;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.UseAdvancedDataToolsPages;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Confirm that the user is authorized to perform each of the RequestedActions.
|
* 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
|
* The user specifies the actions as a comma delimited list of class names (with
|
||||||
* optional spaces). These names are matched against the map of recognized
|
* optional spaces). The classes named must be extensions of RequestedAction
|
||||||
* names. If no match is found, an error is logged and the authorization fails.
|
* (usually implementations of UsePagesRequestedAction), and each class must
|
||||||
|
* have a no-argument public constructor.
|
||||||
*/
|
*/
|
||||||
public class RequiresAuthorizationFor extends BodyTagSupport {
|
public class RequiresAuthorizationFor extends BodyTagSupport {
|
||||||
private static final Log log = LogFactory
|
private static final Log log = LogFactory
|
||||||
.getLog(RequiresAuthorizationFor.class);
|
.getLog(RequiresAuthorizationFor.class);
|
||||||
|
|
||||||
/**
|
String classNamesString = "";
|
||||||
* These are the only action names that we recognize.
|
|
||||||
*/
|
|
||||||
private static final Map<String, RequestedAction> actionMap = new HashMap<String, RequestedAction>();
|
|
||||||
static {
|
|
||||||
actionMap.put("UseAdvancedDataToolsPages",
|
|
||||||
new UseAdvancedDataToolsPages());
|
|
||||||
}
|
|
||||||
|
|
||||||
String actionNames = "";
|
public void setClassNames(String classNamesString) {
|
||||||
|
this.classNamesString = classNamesString;
|
||||||
public void setActions(String actionNames) {
|
|
||||||
this.actionNames = actionNames;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,7 +57,7 @@ public class RequiresAuthorizationFor extends BodyTagSupport {
|
||||||
* are authorized for those actions.
|
* are authorized for those actions.
|
||||||
*/
|
*/
|
||||||
private boolean isAuthorized() {
|
private boolean isAuthorized() {
|
||||||
Collection<RequestedAction> actions = parseActionNames();
|
Collection<RequestedAction> actions = instantiateActions();
|
||||||
if (actions == null) {
|
if (actions == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -76,26 +66,67 @@ public class RequiresAuthorizationFor extends BodyTagSupport {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the string and pull the corresponding actions from the map. If we
|
* Break the string into class names. Confirm that each class is
|
||||||
* can't do that, complain and return null.
|
* RequestedAction or a subclass of it. Create an instance of each class.
|
||||||
|
*
|
||||||
|
* If we can't do all of that, complain and return null.
|
||||||
*/
|
*/
|
||||||
private Collection<RequestedAction> parseActionNames() {
|
private Set<RequestedAction> instantiateActions() {
|
||||||
Set<RequestedAction> actions = new HashSet<RequestedAction>();
|
Set<String> classNames = parseClassNames();
|
||||||
|
if (classNames.isEmpty()) {
|
||||||
for (String part : actionNames.split("[\\s],[\\s]")) {
|
return Collections.emptySet();
|
||||||
String key = part.trim();
|
|
||||||
if (key.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionMap.containsKey(key)) {
|
Set<Class<? extends RequestedAction>> actionClasses = loadClassesAndCheckTypes(classNames);
|
||||||
log.debug("checking authorization for '" + key + "'");
|
if (actionClasses == null) {
|
||||||
actions.add(actionMap.get(key));
|
|
||||||
} else {
|
|
||||||
log.error("JSP requested authorization for unknown action: '"
|
|
||||||
+ key + "'");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return getInstancesFromClasses(actionClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> parseClassNames() {
|
||||||
|
Set<String> names = new HashSet<String>();
|
||||||
|
for (String part : classNamesString.split("[\\s],[\\s]")) {
|
||||||
|
String name = part.trim();
|
||||||
|
if (!name.isEmpty()) {
|
||||||
|
names.add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<Class<? extends RequestedAction>> loadClassesAndCheckTypes(
|
||||||
|
Set<String> classNames) {
|
||||||
|
Set<Class<? extends RequestedAction>> classes = new HashSet<Class<? extends RequestedAction>>();
|
||||||
|
for (String className : classNames) {
|
||||||
|
try {
|
||||||
|
Class<?> clazz = Class.forName(className);
|
||||||
|
classes.add(clazz.asSubclass(RequestedAction.class));
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
log.error("Can't load action class: '" + className + "'");
|
||||||
|
return null;
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
log.error("Action class is not a subclass of RequestedAction: '"
|
||||||
|
+ className + "'");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<RequestedAction> getInstancesFromClasses(
|
||||||
|
Set<Class<? extends RequestedAction>> actionClasses) {
|
||||||
|
Set<RequestedAction> actions = new HashSet<RequestedAction>();
|
||||||
|
for (Class<? extends RequestedAction> actionClass : actionClasses) {
|
||||||
|
try {
|
||||||
|
RequestedAction action = actionClass.newInstance();
|
||||||
|
actions.add(action);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to create an instance of '"
|
||||||
|
+ actionClass.getName()
|
||||||
|
+ "'. Does it have a public zero-argument constructor?");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue