c2834935a473d3967228cad0379e02fc582468b1
[utils] / security / impl / src / main / java / org / wamblee / security / authorization / UrlAuthorizationRule.java
1 /*
2  * Copyright 2005-2010 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 package org.wamblee.security.authorization;
17
18 import static org.wamblee.security.authorization.AuthorizationResult.*;
19
20 import javax.persistence.Access;
21 import javax.persistence.AccessType;
22 import javax.persistence.CascadeType;
23 import javax.persistence.Column;
24 import javax.persistence.Entity;
25 import javax.persistence.JoinColumn;
26 import javax.persistence.ManyToOne;
27 import javax.persistence.Transient;
28
29 import org.apache.log4j.Logger;
30 import org.wamblee.usermgt.User;
31
32 /**
33  * Utility base class for implementation of authentication rules based on the
34  * <ul>
35  * <li>The path of the resource. To obtain the path of a resource, subclasses
36  * must implement {@link #getResourcePath(Object)}. Whether a path is
37  * appropriate is determined by a
38  * {@link org.wamblee.security.authorization.PathCondition}.</li>
39  * <li>The user identity with which the resource is accessed. Whether a user is
40  * appropriate is determined by a
41  * {@link org.wamblee.security.authorization.UserCondition}.</li>
42  * <li>The operation that is requested. Whether the operation is appropriate is
43  * determined by a {@link org.wamblee.security.authorization.OperationCondition}
44  * .</li>
45  * </ul>
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 of
48  * the specified type, the result is UNSUPPORTED_RESOURCE, otherwise, the result
49  * is UNDECIDED.
50  */
51 @Entity
52 @Access(AccessType.PROPERTY)
53 public abstract class UrlAuthorizationRule extends AuthorizationRule {
54     private static final Logger LOGGER = Logger
55         .getLogger(UrlAuthorizationRule.class);
56
57     /**
58      * Result that the rule will return in case there is a match.
59      */
60     private AuthorizationResult result;
61
62     /**
63      * A condition which specifies which users the rule is for.
64      */
65     private UserCondition userCondition;
66
67     /**
68      * Path the rule applies for.
69      */
70     private PathCondition pathCondition;
71
72     /**
73      * Resource class that the rule applies for.
74      */
75     private Class resourceClass;
76
77     /**
78      * Operation that this rule is for.
79      */
80     private OperationCondition operationCondition;
81
82     /**
83      * Constructs an authorization rule. IF the group and path match, then the
84      * provided result will be returned.
85      * 
86      * @param aResult
87      *            Result of the authorization when the path and group match.
88      * @param aUserCondition
89      *            Condition to match users.
90      * @param aPathCondition
91      *            Condition to match paths with.
92      * @param aResourceClass
93      *            Supported resource class this is for.
94      * @param aOperationCondition
95      *            Condition to match the operation with.
96      */
97     protected UrlAuthorizationRule(AuthorizationResult aResult,
98         UserCondition aUserCondition, PathCondition aPathCondition,
99         Class aResourceClass, OperationCondition aOperationCondition) {
100         if (!aResult.equals(GRANTED) && !aResult.equals(DENIED)) {
101             throw new IllegalArgumentException(
102                 "Only GRANTED or DENIED may be used: " + aResult);
103         }
104
105         result = aResult;
106         userCondition = aUserCondition;
107         pathCondition = aPathCondition;
108         resourceClass = aResourceClass;
109         operationCondition = aOperationCondition;
110     }
111
112     /**
113      * For OR mapping.
114      * 
115      */
116     protected UrlAuthorizationRule(Class aResourceClass) {
117         result = null;
118         userCondition = null;
119         pathCondition = null;
120         resourceClass = aResourceClass;
121         operationCondition = null;
122     }
123
124     /**
125      * For OR mapping.
126      * 
127      */
128     protected UrlAuthorizationRule() {
129         result = null;
130         userCondition = null;
131         pathCondition = null;
132         resourceClass = null;
133         operationCondition = null;
134     }
135
136     /*
137      * (non-Javadoc)
138      * 
139      * @see
140      * org.wamblee.security.authorization.AuthorizationRule#getSupportedTypes()
141      */
142     @Transient
143     public Class[] getSupportedTypes() {
144         return new Class[] { resourceClass };
145     }
146
147     /*
148      * (non-Javadoc)
149      * 
150      * @see
151      * org.wamblee.security.authorization.AuthorizationRule#isAllowed(java.lang
152      * .Object, org.wamblee.security.authorization.Operation)
153      */
154     public AuthorizationResult isAllowed(Object aResource,
155         Operation aOperation, User aUser) {
156         if (!resourceClass.isInstance(aResource)) {
157             return UNSUPPORTED_RESOURCE;
158         }
159
160         String path = getResourcePath(aResource);
161
162         return isAllowed(path, aOperation, aUser);
163     }
164
165     /**
166      * Determines if the operation is allowed on the resource.
167      * 
168      * @param aPath
169      *            Path of the resource.
170      * @param aOperation
171      *            Operation to be done.
172      * @param aUser
173      *            Currently logged in user or null if no user is logged in.
174      * 
175      * @return Authorization result,
176      */
177     protected AuthorizationResult isAllowed(String aPath, Operation aOperation,
178         User aUser) {
179         if (!pathCondition.matches(aPath)) {
180             return UNDECIDED;
181         }
182
183         if (!operationCondition.matches(aOperation)) {
184             return UNDECIDED;
185         }
186
187         if (!userCondition.matches(aUser)) {
188             return UNDECIDED;
189         }
190
191         return result;
192     }
193
194     /**
195      * Gets the path of the resource.
196      * 
197      * @param aResource
198      *            Resource, guaranteed to be an instance of
199      *            {@link #resourceClass}.
200      * 
201      * @return Path of the resource.
202      */
203     protected abstract String getResourcePath(Object aResource);
204
205     /*
206      * (non-Javadoc)
207      * 
208      * @see java.lang.Object#toString()
209      */
210     @Override
211     public String toString() {
212         return "UrlAUthorizationRule(result = " + result +
213             ", pathCondition = " + pathCondition + ", userCondition = " +
214             userCondition + ", resourceClass = " + resourceClass + ")";
215     }
216
217     /**
218      * Gets the authorization result for OR mapping.
219      * 
220      * @return Result.
221      */
222     @Column(name = "AUTH_RESULT", nullable = false)
223     protected String getAuthorizationResultString() {
224         if (result == null) {
225             return null;
226         }
227
228         return result.toString();
229     }
230
231     /**
232      * Sets the authorization result, for OR mapping.
233      * 
234      * @param aResult
235      *            Result.
236      */
237     protected void setAuthorizationResultString(String aResult) {
238         result = AuthorizationResult.valueOf(aResult);
239     }
240
241     @Column(name = "RES_CLASSNAME", nullable = false)
242     protected String getResourceClassName() {
243         if (resourceClass == null) {
244             return "";
245         }
246
247         return resourceClass.getName();
248     }
249
250     protected void setResourceClassName(String aResourceClass) {
251         try {
252             resourceClass = Class.forName(aResourceClass);
253         } catch (ClassNotFoundException e) {
254             LOGGER.error("Cannot find resource class '" + aResourceClass + "'",
255                 e);
256             throw new IllegalArgumentException(e.getMessage(), e);
257         }
258     }
259
260     /**
261      * 
262      * @return Returns the operationCondition.
263      */
264     @ManyToOne(cascade = CascadeType.ALL)
265     @JoinColumn(name = "OPER_COND_PK")
266     public OperationCondition getOperationCondition() {
267         return operationCondition;
268     }
269
270     /**
271      * 
272      * @param aOperationCondition
273      *            The operationCondition to set.
274      */
275     protected void setOperationCondition(OperationCondition aOperationCondition) {
276         operationCondition = aOperationCondition;
277     }
278
279     /**
280      * 
281      * @return Returns the pathCondition.
282      */
283     @ManyToOne(cascade = CascadeType.ALL)
284     @JoinColumn(name = "PATH_COND_PK")
285     public PathCondition getPathCondition() {
286         return pathCondition;
287     }
288
289     /**
290      * 
291      * @param aPathCondition
292      *            The pathCondition to set.
293      */
294     protected void setPathCondition(PathCondition aPathCondition) {
295         pathCondition = aPathCondition;
296     }
297
298     /**
299      * 
300      * @return Returns the userCondition.
301      */
302     @ManyToOne(cascade = CascadeType.ALL)
303     @JoinColumn(name = "USER_COND_PK")
304     public UserCondition getUserCondition() {
305         return userCondition;
306     }
307
308     /**
309      * 
310      * @param aUserCondition
311      *            The userCondition to set.
312      */
313     protected void setUserCondition(UserCondition aUserCondition) {
314         userCondition = aUserCondition;
315     }
316 }