KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > security > permissions > impl > acegi > ACLEntryVoter


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.repo.security.permissions.impl.acegi;
18
19 import java.lang.reflect.Method JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.StringTokenizer JavaDoc;
24
25 import net.sf.acegisecurity.Authentication;
26 import net.sf.acegisecurity.ConfigAttribute;
27 import net.sf.acegisecurity.ConfigAttributeDefinition;
28 import net.sf.acegisecurity.vote.AccessDecisionVoter;
29
30 import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
31 import org.alfresco.service.cmr.repository.ChildAssociationRef;
32 import org.alfresco.service.cmr.repository.NodeRef;
33 import org.alfresco.service.cmr.repository.NodeService;
34 import org.alfresco.service.cmr.repository.StoreRef;
35 import org.alfresco.service.cmr.security.AccessStatus;
36 import org.alfresco.service.cmr.security.AuthenticationService;
37 import org.alfresco.service.cmr.security.AuthorityService;
38 import org.alfresco.service.cmr.security.PermissionService;
39 import org.alfresco.service.namespace.NamespacePrefixResolver;
40 import org.alfresco.service.namespace.QName;
41 import org.aopalliance.intercept.MethodInvocation;
42 import org.apache.commons.logging.Log;
43 import org.apache.commons.logging.LogFactory;
44 import org.springframework.beans.factory.InitializingBean;
45
46 /**
47  *
48  * @author andyh
49  */

50
51 public class ACLEntryVoter implements AccessDecisionVoter, InitializingBean
52 {
53     private static Log log = LogFactory.getLog(ACLEntryVoter.class);
54
55     private static final String JavaDoc ACL_NODE = "ACL_NODE";
56
57     private static final String JavaDoc ACL_PARENT = "ACL_PARENT";
58
59     private static final String JavaDoc ACL_ALLOW = "ACL_ALLOW";
60
61     private static final String JavaDoc ACL_METHOD = "ACL_METHOD";
62
63     private PermissionService permissionService;
64
65     private NamespacePrefixResolver nspr;
66
67     private NodeService nodeService;
68
69     private AuthenticationService authenticationService;
70
71     private AuthorityService authorityService;
72
73     public ACLEntryVoter()
74     {
75         super();
76     }
77
78     // ~ Methods
79
// ================================================================
80

81     public void setPermissionService(PermissionService permissionService)
82     {
83         this.permissionService = permissionService;
84     }
85
86     public PermissionService getPermissionService()
87     {
88         return permissionService;
89     }
90
91     public NamespacePrefixResolver getNamespacePrefixResolver()
92     {
93         return nspr;
94     }
95
96     public void setNamespacePrefixResolver(NamespacePrefixResolver nspr)
97     {
98         this.nspr = nspr;
99     }
100
101     public NodeService getNodeService()
102     {
103         return nodeService;
104     }
105
106     public void setNodeService(NodeService nodeService)
107     {
108         this.nodeService = nodeService;
109     }
110
111     public AuthenticationService getAuthenticationService()
112     {
113         return authenticationService;
114     }
115
116     public void setAuthenticationService(AuthenticationService authenticationService)
117     {
118         this.authenticationService = authenticationService;
119     }
120
121     public void setAuthorityService(AuthorityService authorityService)
122     {
123         this.authorityService = authorityService;
124     }
125
126     public void afterPropertiesSet() throws Exception JavaDoc
127     {
128         if (permissionService == null)
129         {
130             throw new IllegalArgumentException JavaDoc("There must be a permission service");
131         }
132         if (nspr == null)
133         {
134             throw new IllegalArgumentException JavaDoc("There must be a namespace service");
135         }
136         if (nodeService == null)
137         {
138             throw new IllegalArgumentException JavaDoc("There must be a node service");
139         }
140         if (authenticationService == null)
141         {
142             throw new IllegalArgumentException JavaDoc("There must be an authentication service");
143         }
144         if (authorityService == null)
145         {
146             throw new IllegalArgumentException JavaDoc("There must be an authority service");
147         }
148
149     }
150
151     public boolean supports(ConfigAttribute attribute)
152     {
153         if ((attribute.getAttribute() != null)
154                 && (attribute.getAttribute().startsWith(ACL_NODE)
155                         || attribute.getAttribute().startsWith(ACL_PARENT)
156                         || attribute.getAttribute().startsWith(ACL_ALLOW) || attribute.getAttribute().startsWith(
157                         ACL_METHOD)))
158         {
159             return true;
160         }
161         else
162         {
163             return false;
164         }
165     }
166
167     /**
168      * This implementation supports only <code>MethodSecurityInterceptor</code>,
169      * because it queries the presented <code>MethodInvocation</code>.
170      *
171      * @param clazz
172      * the secure object
173      *
174      * @return <code>true</code> if the secure object is
175      * <code>MethodInvocation</code>, <code>false</code> otherwise
176      */

177     public boolean supports(Class JavaDoc clazz)
178     {
179         return (MethodInvocation.class.isAssignableFrom(clazz));
180     }
181
182     public int vote(Authentication authentication, Object JavaDoc object, ConfigAttributeDefinition config)
183     {
184         if (log.isDebugEnabled())
185         {
186             MethodInvocation mi = (MethodInvocation) object;
187             log.debug("Method: " + mi.getMethod().toString());
188         }
189         if (authenticationService.isCurrentUserTheSystemUser())
190         {
191             if (log.isDebugEnabled())
192             {
193                 log.debug("Access granted for the system user");
194             }
195             return AccessDecisionVoter.ACCESS_GRANTED;
196         }
197
198         List JavaDoc<ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config);
199
200         if (supportedDefinitions.size() == 0)
201         {
202             return AccessDecisionVoter.ACCESS_GRANTED;
203         }
204
205         MethodInvocation invocation = (MethodInvocation) object;
206
207         Method JavaDoc method = invocation.getMethod();
208         Class JavaDoc[] params = method.getParameterTypes();
209
210         for (ConfigAttributeDefintion cad : supportedDefinitions)
211         {
212             NodeRef testNodeRef = null;
213
214             if (cad.typeString.equals(ACL_ALLOW))
215             {
216                 return AccessDecisionVoter.ACCESS_GRANTED;
217             }
218             else if (cad.typeString.equals(ACL_METHOD))
219             {
220                 if (authenticationService.getCurrentUserName().equals(cad.authority))
221                 {
222                     return AccessDecisionVoter.ACCESS_GRANTED;
223                 }
224                 else
225                 {
226                     return authorityService.getAuthorities().contains(cad.authority) ? AccessDecisionVoter.ACCESS_GRANTED
227                             : AccessDecisionVoter.ACCESS_DENIED;
228                 }
229             }
230             else if (cad.parameter >= invocation.getArguments().length)
231             {
232                 continue;
233             }
234             else if (cad.typeString.equals(ACL_NODE))
235             {
236                 if (StoreRef.class.isAssignableFrom(params[cad.parameter]))
237                 {
238                     if (invocation.getArguments()[cad.parameter] != null)
239                     {
240                         if (log.isDebugEnabled())
241                         {
242                             log.debug("\tPermission test against the store - using permissions on the root node");
243                         }
244                         StoreRef storeRef = (StoreRef) invocation.getArguments()[cad.parameter];
245                         if (nodeService.exists(storeRef))
246                         {
247                             testNodeRef = nodeService.getRootNode(storeRef);
248                         }
249                     }
250                 }
251                 else if (NodeRef.class.isAssignableFrom(params[cad.parameter]))
252                 {
253                     testNodeRef = (NodeRef) invocation.getArguments()[cad.parameter];
254                     if (log.isDebugEnabled())
255                     {
256                         log.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
257                     }
258                 }
259                 else if (ChildAssociationRef.class.isAssignableFrom(params[cad.parameter]))
260                 {
261                     if (invocation.getArguments()[cad.parameter] != null)
262                     {
263                         testNodeRef = ((ChildAssociationRef) invocation.getArguments()[cad.parameter]).getChildRef();
264                         if (log.isDebugEnabled())
265                         {
266                             log.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
267                         }
268                     }
269                 }
270                 else
271                 {
272                     throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
273                 }
274             }
275             else if (cad.typeString.equals(ACL_PARENT))
276             {
277                 // There is no point having parent permissions for store
278
// refs
279
if (NodeRef.class.isAssignableFrom(params[cad.parameter]))
280                 {
281                     NodeRef child = (NodeRef) invocation.getArguments()[cad.parameter];
282                     if (child != null)
283                     {
284                         testNodeRef = nodeService.getPrimaryParent(child).getParentRef();
285                         if (log.isDebugEnabled())
286                         {
287                             log.debug("\tPermission test for parent on node " + nodeService.getPath(testNodeRef));
288                         }
289                     }
290                 }
291                 else if (ChildAssociationRef.class.isAssignableFrom(params[cad.parameter]))
292                 {
293                     if (invocation.getArguments()[cad.parameter] != null)
294                     {
295                         testNodeRef = ((ChildAssociationRef) invocation.getArguments()[cad.parameter]).getParentRef();
296                         if (log.isDebugEnabled())
297                         {
298                             log.debug("\tPermission test for parent on child assoc ref for node "
299                                     + nodeService.getPath(testNodeRef));
300                         }
301                     }
302
303                 }
304                 else
305                 {
306                     throw new ACLEntryVoterException("The specified parameter is not a ChildAssociationRef");
307                 }
308             }
309
310             if (testNodeRef != null)
311             {
312                 if (log.isDebugEnabled())
313                 {
314                     log.debug("\t\tNode ref is not null");
315                 }
316                 if (permissionService.hasPermission(testNodeRef, cad.required.toString()) == AccessStatus.DENIED)
317                 {
318                     if (log.isDebugEnabled())
319                     {
320                         log.debug("\t\tPermission is denied");
321                         Thread.dumpStack();
322                     }
323                     return AccessDecisionVoter.ACCESS_DENIED;
324                 }
325             }
326         }
327
328         return AccessDecisionVoter.ACCESS_GRANTED;
329     }
330
331     private List JavaDoc<ConfigAttributeDefintion> extractSupportedDefinitions(ConfigAttributeDefinition config)
332     {
333         List JavaDoc<ConfigAttributeDefintion> definitions = new ArrayList JavaDoc<ConfigAttributeDefintion>();
334         Iterator JavaDoc iter = config.getConfigAttributes();
335
336         while (iter.hasNext())
337         {
338             ConfigAttribute attr = (ConfigAttribute) iter.next();
339
340             if (this.supports(attr))
341             {
342                 definitions.add(new ConfigAttributeDefintion(attr));
343             }
344
345         }
346         return definitions;
347     }
348
349     private class ConfigAttributeDefintion
350     {
351         String JavaDoc typeString;
352
353         SimplePermissionReference required;
354
355         int parameter;
356
357         String JavaDoc authority;
358
359         ConfigAttributeDefintion(ConfigAttribute attr)
360         {
361             StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(attr.getAttribute(), ".", false);
362             if (st.countTokens() < 1)
363             {
364                 throw new ACLEntryVoterException("There must be at least one token in a config attribute");
365             }
366             typeString = st.nextToken();
367
368             if (!(typeString.equals(ACL_NODE) || typeString.equals(ACL_PARENT) || typeString.equals(ACL_ALLOW) || typeString
369                     .equals(ACL_METHOD)))
370             {
371                 throw new ACLEntryVoterException("Invalid type: must be ACL_NODE, ACL_PARENT or ACL_ALLOW");
372             }
373
374             if (typeString.equals(ACL_NODE) || typeString.equals(ACL_PARENT))
375             {
376                 if (st.countTokens() != 3)
377                 {
378                     throw new ACLEntryVoterException("There must be four . separated tokens in each config attribute");
379                 }
380                 String JavaDoc numberString = st.nextToken();
381                 String JavaDoc qNameString = st.nextToken();
382                 String JavaDoc permissionString = st.nextToken();
383
384                 parameter = Integer.parseInt(numberString);
385
386                 QName qName = QName.createQName(qNameString, nspr);
387
388                 required = new SimplePermissionReference(qName, permissionString);
389             }
390             else if (typeString.equals(ACL_METHOD))
391             {
392                 if (st.countTokens() != 1)
393                 {
394                     throw new ACLEntryVoterException(
395                             "There must be two . separated tokens in each group or role config attribute");
396                 }
397                 authority = st.nextToken();
398             }
399
400         }
401     }
402 }
403
Popular Tags