a31849685150c3a7ec2b38be3be0a2e3f2bb0cf7
[utils] / security / src / main / java / org / wamblee / security / authorization / UrlAuthorizationRule.java
1 /*
2  * Copyright 2005 the original author or authors.
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.wamblee.security.authorization;
18
19 import static org.wamblee.security.authorization.AuthorizationResult.DENIED;
20 import static org.wamblee.security.authorization.AuthorizationResult.GRANTED;
21 import static org.wamblee.security.authorization.AuthorizationResult.UNDECIDED;
22 import static org.wamblee.security.authorization.AuthorizationResult.UNSUPPORTED_RESOURCE;
23
24 import org.apache.log4j.Logger;
25 import org.wamblee.persistence.AbstractPersistent;
26 import org.wamblee.usermgt.User;
27
28 /**
29  * Utility base class for implementation of authentication rules based on the 
30  * <ul>
31  * <li> The path of the resource. To obtain the path of a resource, subclasses
32  *      must implement {@link #getResourcePath(Object)}. 
33  *      Whether a path is appropriate is determined by a 
34  *      {@link org.wamblee.security.authorization.PathCondition}. 
35  * </li>
36  * <li> The user identity with which the resource is accessed. 
37  *      Whether a user is appropriate is determined by
38  *      a {@link org.wamblee.security.authorization.UserCondition}. 
39  * </li>
40  * <li> The operation that is requested. 
41  *      Whether the operation is appropriate is determined by a 
42  *      {@link org.wamblee.security.authorization.OperationCondition}. 
43  * </li>
44  * </ul>
45  * 
46  * In case all three conditions match, the condition returns the configured
47  * result passed at construction (GRANTED or DENIED). If the resource is not
48  * of the specified type, the result is UNSUPPORTED_RESOURCE, otherwise, the
49  * result is UNDECIDED. 
50  */
51 public abstract class UrlAuthorizationRule extends AbstractPersistent implements AuthorizationRule {
52     
53     private static final Logger LOGGER = Logger.getLogger(UrlAuthorizationRule.class);
54
55     /**
56      * Result that the rule will return in case there is a match. 
57      */
58     private AuthorizationResult result;
59
60     /**
61      * A condition which specifies which users the rule is for. 
62      */
63     private UserCondition userCondition; 
64
65     /**
66      * Path the rule applies for. 
67      */
68     private PathCondition pathCondition;
69
70     /**
71      * Resource class that the rule applies for. 
72      */
73     private Class resourceClass;
74     
75     /**
76      * Operation that this rule is for. 
77      */
78     private OperationCondition operationCondition; 
79
80     /**
81      * Constructs an authorization rule. 
82      * IF the group and path match, then the provided result will be returned. 
83      * @param aResult Result of the authorization when the path and group match. 
84      * @param aUserCondition Condition to match users.  
85      * @param aPathCondition Condition to match paths with.  
86      * @param aResourceClass Supported resource class this is for.
87      * @param aOperationCondition Condition to match the operation with.  
88      */
89     protected UrlAuthorizationRule(AuthorizationResult aResult, UserCondition aUserCondition,
90             PathCondition aPathCondition, Class aResourceClass, OperationCondition aOperationCondition) {
91         if ( !aResult.equals(GRANTED) && !aResult.equals(DENIED)) {
92             throw new IllegalArgumentException("Only GRANTED or DENIED may be used: " + aResult);
93         }
94         result = aResult;
95         userCondition = aUserCondition; 
96         pathCondition = aPathCondition;
97         resourceClass = aResourceClass;
98         operationCondition = aOperationCondition; 
99     }
100     
101     /**
102      * For OR mapping. 
103      *
104      */
105     protected UrlAuthorizationRule(Class aResourceClass) { 
106         result = null; 
107         userCondition = null; 
108         pathCondition = null; 
109         resourceClass = aResourceClass; 
110         operationCondition = null; 
111     }
112     
113     /**
114      * For OR mapping. 
115      *
116      */
117     protected UrlAuthorizationRule() { 
118         result = null; 
119         userCondition = null; 
120         pathCondition = null; 
121         resourceClass = null; 
122         operationCondition = null; 
123     }
124
125
126     /*
127      * (non-Javadoc)
128      * 
129      * @see org.wamblee.security.authorization.AuthorizationRule#getSupportedTypes()
130      */
131     public Class[] getSupportedTypes() {
132         return new Class[] { resourceClass };
133     }
134
135     /*
136      * (non-Javadoc)
137      * 
138      * @see org.wamblee.security.authorization.AuthorizationRule#isAllowed(java.lang.Object,
139      *      org.wamblee.security.authorization.Operation)
140      */
141     public AuthorizationResult isAllowed(Object aResource, Operation anOperation, User aUser) {
142         if ( ! resourceClass.isInstance(aResource)) { 
143             return UNSUPPORTED_RESOURCE; 
144         }
145         String path = getResourcePath(aResource);
146         return isAllowed(path, anOperation, aUser); 
147     }
148     
149     /**
150      * Determines if the operation is allowed on the resource. 
151      * @param aPath Path of the resource. 
152      * @param aOperation Operation to be done. 
153      * @param aUser Currently logged in user or null if no user is logged in. 
154      * @return Authorization result, 
155      */
156     protected AuthorizationResult isAllowed(String aPath, Operation aOperation, User aUser) {
157         if ( ! pathCondition.matches(aPath) ) {
158             return UNDECIDED;
159         }
160         if ( !operationCondition.matches(aOperation) ) {
161             return UNDECIDED; 
162         }
163         if ( !userCondition.matches(aUser)) {
164             return UNDECIDED;
165         }
166         return result; 
167     }
168
169     /**
170      * Gets the path of the resource. 
171      * @param aResource Resource, guaranteed to be an instance of 
172      * {@link #resourceClass}. 
173      * @return Path of the resource. 
174      */
175     protected abstract String getResourcePath(Object aResource);
176     
177     /* (non-Javadoc)
178      * @see java.lang.Object#toString()
179      */
180     @Override
181     public String toString() {
182         return "UrlAUthorizationRule(result = " + result + 
183            ", pathCondition = " + pathCondition + 
184            ", userCondition = " + userCondition +   
185            ", resourceClass = " + resourceClass + ")";  
186     }
187     
188     /**
189      * Gets the authorization result for OR mapping. 
190      * @return Result. 
191      */
192     protected String getAuthorizationResultString() {
193         if ( result == null ) { 
194             return null; 
195         }
196         return result.toString(); 
197     }
198     
199     /**
200      * Sets the authorization result, for OR mapping. 
201      * @param aResult Result. 
202      */
203     protected void setAuthorizationResultString(String aResult) {
204         result = AuthorizationResult.valueOf(aResult);
205     }
206     
207     protected String getResourceClassName() {
208         if ( resourceClass == null ) { 
209             return "";
210         }
211         return resourceClass.getName(); 
212     }
213     
214     protected void setResourceClassName(String aResourceClass) { 
215         try {
216             resourceClass = Class.forName(aResourceClass);
217         } catch (ClassNotFoundException e) {
218            LOGGER.error("Cannot find resource class '" + aResourceClass + "'", e); 
219            throw new IllegalArgumentException(e.getMessage(), e);
220         }
221     }
222
223     /**
224      * @return Returns the operationCondition.
225      */
226     public OperationCondition getOperationCondition() {
227         return operationCondition;
228     }
229
230     /**
231      * @param aOperationCondition The operationCondition to set.
232      */
233     protected void setOperationCondition(OperationCondition aOperationCondition) {
234         operationCondition = aOperationCondition;
235     }
236
237     /**
238      * @return Returns the pathCondition.
239      */
240     public PathCondition getPathCondition() {
241         return pathCondition;
242     }
243
244     /**
245      * @param aPathCondition The pathCondition to set.
246      */
247     protected void setPathCondition(PathCondition aPathCondition) {
248         pathCondition = aPathCondition;
249     }
250
251     /**
252      * @return Returns the userCondition.
253      */
254     public UserCondition getUserCondition() {
255         return userCondition;
256     }
257
258     /**
259      * @param aUserCondition The userCondition to set.
260      */
261     protected void setUserCondition(UserCondition aUserCondition) {
262         userCondition = aUserCondition;
263     }
264 }