/* * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wamblee.security.authorization; import static org.wamblee.security.authorization.AuthorizationResult.*; import java.util.logging.Level; import java.util.logging.Logger; import javax.persistence.Access; import javax.persistence.AccessType; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Transient; import org.wamblee.security.authentication.UserAdministration; /** * Utility base class for implementation of authentication rules based on the * * In case all three conditions match, the condition returns the configured * result passed at construction (GRANTED or DENIED). If the resource is not of * the specified type, the result is UNSUPPORTED_RESOURCE, otherwise, the result * is UNDECIDED. */ @Entity @Access(AccessType.PROPERTY) public abstract class UrlAuthorizationRule extends AbstractAuthorizationRule { private static final Logger LOGGER = Logger .getLogger(UrlAuthorizationRule.class.getName()); /** * Result that the rule will return in case there is a match. */ private AuthorizationResult result; /** * A condition which specifies which users the rule is for. */ private UserCondition userCondition; /** * Path the rule applies for. */ private PathCondition pathCondition; /** * Resource class that the rule applies for. */ private Class resourceClass; /** * Operation that this rule is for. */ private OperationCondition operationCondition; /** * Constructs an authorization rule. IF the group and path match, then the * provided result will be returned. * * @param aResult * Result of the authorization when the path and group match. * @param aUserCondition * Condition to match users. * @param aPathCondition * Condition to match paths with. * @param aResourceClass * Supported resource class this is for. * @param aOperationCondition * Condition to match the operation with. */ protected UrlAuthorizationRule(AuthorizationResult aResult, UserCondition aUserCondition, PathCondition aPathCondition, Class aResourceClass, OperationCondition aOperationCondition) { if (!aResult.equals(GRANTED) && !aResult.equals(DENIED)) { throw new IllegalArgumentException( "Only GRANTED or DENIED may be used: " + aResult); } result = aResult; userCondition = aUserCondition; pathCondition = aPathCondition; resourceClass = aResourceClass; operationCondition = aOperationCondition; } /** * For OR mapping. * */ protected UrlAuthorizationRule(Class aResourceClass) { result = null; userCondition = null; pathCondition = null; resourceClass = aResourceClass; operationCondition = null; } /** * For OR mapping. * */ protected UrlAuthorizationRule() { result = null; userCondition = null; pathCondition = null; resourceClass = null; operationCondition = null; } /* * (non-Javadoc) * * @see * org.wamblee.security.authorization.AuthorizationRule#getSupportedTypes() */ @Transient public Class[] getSupportedTypes() { return new Class[] { resourceClass }; } /* * (non-Javadoc) * * @see * org.wamblee.security.authorization.AuthorizationRule#isAllowed(java.lang * .Object, org.wamblee.security.authorization.Operation) */ public AuthorizationResult isAllowed(Object aResource, Operation aOperation, String aUser) { if (!resourceClass.isInstance(aResource)) { return UNSUPPORTED_RESOURCE; } String path = getResourcePath(aResource); return isAllowedWithPath(path, aOperation, aUser); } /** * Determines if the operation is allowed on the resource. * * @param aPath * Path of the resource. * @param aOperation * Operation to be done. * @param aUser * Currently logged in user or null if no user is logged in. * * @return Authorization result, */ protected AuthorizationResult isAllowedWithPath(String aPath, Operation aOperation, String aUser) { if (!pathCondition.matches(aPath)) { return UNDECIDED; } if (!operationCondition.matches(aOperation)) { return UNDECIDED; } if (!userCondition.matches(aUser)) { return UNDECIDED; } return result; } /** * Gets the path of the resource. * * @param aResource * Resource, guaranteed to be an instance of * {@link #resourceClass}. * * @return Path of the resource. */ protected abstract String getResourcePath(Object aResource); /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { return "UrlAUthorizationRule(result = " + result + ", pathCondition = " + pathCondition + ", userCondition = " + userCondition + ", resourceClass = " + resourceClass + ")"; } /** * Gets the authorization result for OR mapping. * * @return Result. */ @Column(name = "AUTH_RESULT", nullable = false) protected String getAuthorizationResultString() { if (result == null) { return null; } return result.toString(); } /** * Sets the authorization result, for OR mapping. * * @param aResult * Result. */ protected void setAuthorizationResultString(String aResult) { result = AuthorizationResult.valueOf(aResult); } @Column(name = "RES_CLASSNAME", nullable = false) protected String getResourceClassName() { if (resourceClass == null) { return ""; } return resourceClass.getName(); } protected void setResourceClassName(String aResourceClass) { try { resourceClass = Class.forName(aResourceClass); } catch (ClassNotFoundException e) { LOGGER.log(Level.SEVERE, "Cannot find resource class '" + aResourceClass + "'", e); throw new IllegalArgumentException(e.getMessage(), e); } } /** * * @return Returns the operationCondition. */ @OneToOne(cascade = CascadeType.ALL, targetEntity = AbstractOperationCondition.class, orphanRemoval = true) @JoinColumn(name = "OPER_COND_PK") public OperationCondition getOperationCondition() { return operationCondition; } /** * * @param aOperationCondition * The operationCondition to set. */ protected void setOperationCondition(OperationCondition aOperationCondition) { operationCondition = aOperationCondition; } /** * * @return Returns the pathCondition. */ @OneToOne(cascade = CascadeType.ALL, targetEntity = AbstractPathCondition.class, orphanRemoval = true) @JoinColumn(name = "PATH_COND_PK") public PathCondition getPathCondition() { return pathCondition; } /** * * @param aPathCondition * The pathCondition to set. */ protected void setPathCondition(PathCondition aPathCondition) { pathCondition = aPathCondition; } /** * * @return Returns the userCondition. */ @OneToOne(cascade = CascadeType.ALL, targetEntity = AbstractUserCondition.class, orphanRemoval = true) @JoinColumn(name = "USER_COND_PK") public UserCondition getUserCondition() { return userCondition; } /** * * @param aUserCondition * The userCondition to set. */ protected void setUserCondition(UserCondition aUserCondition) { userCondition = aUserCondition; } @Override public void setUserAdministration(UserAdministration aAdmin) { userCondition.setUserAdmin(aAdmin); } }