KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > slide > security > JahiaWebdavSecurity


1 /*
2  * $Header$
3  * $Revision: 13418 $
4  * $Date: 2006-03-06 14:37:37 +0100 (Mon, 06 Mar 2006) $
5  *
6  * ====================================================================
7  *
8  * Copyright 1999-2002 The Apache Software Foundation
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */

23
24 package org.apache.slide.security;
25
26 import java.lang.reflect.Constructor JavaDoc;
27 import java.lang.reflect.InvocationTargetException JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.Collections JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.HashSet JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.Set JavaDoc;
37 import java.util.Vector JavaDoc;
38 import org.apache.slide.common.Namespace;
39 import org.apache.slide.common.NamespaceConfig;
40 import org.apache.slide.common.ServiceAccessException;
41 import org.apache.slide.common.SlideException;
42 import org.apache.slide.common.SlideToken;
43 import org.apache.slide.common.SlideTokenWrapper;
44 import org.apache.slide.common.Uri;
45 import org.apache.slide.content.NodeProperty;
46 import org.apache.slide.content.NodeRevisionDescriptor;
47 import org.apache.slide.content.NodeRevisionNumber;
48 import org.apache.slide.content.RevisionDescriptorNotFoundException;
49 import org.apache.slide.store.Store;
50 import org.apache.slide.structure.ActionNode;
51 import org.apache.slide.structure.LinkNode;
52 import org.apache.slide.structure.ObjectAlreadyExistsException;
53 import org.apache.slide.structure.ObjectNode;
54 import org.apache.slide.structure.ObjectNotFoundException;
55 import org.apache.slide.structure.SubjectNode;
56 import org.apache.slide.util.Configuration;
57 import org.apache.slide.util.XMLValue;
58 import org.apache.slide.util.logger.Logger;
59 import org.jdom.JDOMException;
60 import org.jahia.services.webdav.stores.UserLinkNode;
61 import org.jahia.services.webdav.stores.JahiaGroupNode;
62 import org.jahia.services.usermanager.JahiaGroupManagerService;
63 import org.jahia.services.usermanager.JahiaUserManagerService;
64 import org.jahia.services.usermanager.JahiaGroup;
65 import org.jahia.services.usermanager.JahiaUser;
66 import org.jahia.services.sites.JahiaSite;
67 import org.jahia.registries.ServicesRegistry;
68 import org.jahia.exceptions.JahiaException;
69
70 /**
71  * Security helper.
72  *
73  * @author <a HREF="mailto:remm@apache.org">Remy Maucherat</a>
74  * @version $Revision: 13418 $
75  */

76 public class JahiaWebdavSecurity extends SecurityImpl {
77
78     private static final String JavaDoc LOG_CHANNEL = SecurityImpl.class.getName();
79
80     private static final String JavaDoc actions[] = {"/actions/read","/actions/write","/actions/manage"};
81
82     /**
83      * Constructor.
84      */

85     public JahiaWebdavSecurity() {}
86
87     /**
88      * Constructor.
89      *
90      * @param namespace Namespace
91      * @param namespaceConfig Namespace configuration
92      */

93     public JahiaWebdavSecurity(Namespace namespace, NamespaceConfig namespaceConfig) {
94         init(namespace, namespaceConfig);
95     }
96
97     public void init(Namespace namespace, NamespaceConfig namespaceConfig) {
98         super.init(namespace, namespaceConfig);
99         loadActionsCache(namespace, namespaceConfig);
100     }
101
102     // ----------------------------------------------------- Instance Variables
103

104     /**
105      * Cached all actions exsiting at namespace initialization
106      * and their aggregated actions
107      */

108     private Map JavaDoc actionAggregation; // actionNode -> Set-of-aggregated-nodes (direct aggregates)
109
private Map JavaDoc actionAggregationClosure; // actionNode -> Set-of-aggregated-nodes (transitive closure)
110

111     // ------------------------------------------------------- Security Methods
112

113
114     /**
115      * Set a new set of permissions on an object.
116      *
117      * @param token Credentials token
118      * @param object Object on which permission is granted
119      * @exception ServiceAccessException SearchIndexer access error
120      * @exception ObjectNotFoundException Specified object was not found
121      * in the SearchIndexer
122      * @exception AccessDeniedException Insufficent credentials
123      */

124     public void setPermissions(SlideToken token, String JavaDoc object,
125                                Enumeration JavaDoc permissions)
126         throws ServiceAccessException, ObjectNotFoundException,
127         AccessDeniedException {
128
129         Uri objectUri = namespace.getUri(token, object);
130         ObjectNode objectNode = objectUri.getStore().retrieveObject(objectUri);
131
132         checkCredentials(token, objectNode,
133                          namespaceConfig.getGrantPermissionAction());
134         checkCredentials(token, objectNode,
135                          namespaceConfig.getRevokePermissionAction());
136
137         objectUri.getStore().revokePermissions(objectUri);
138
139         while (permissions.hasMoreElements()) {
140             NodePermission permission =
141                 (NodePermission) permissions.nextElement();
142             mapRoles(permission);
143             objectUri.getStore().grantPermission(objectUri, permission);
144         }
145
146     }
147
148
149     /**
150      * Grants a new permission.
151      *
152      * @param token Credentials token
153      * @param object Object on which permission is granted
154      * @param subject The subject to whom the permission is granted.
155      * @param action The action which the subject can perform
156      * @exception ServiceAccessException SearchIndexer access error
157      * @exception ObjectNotFoundException Specified object was not found
158      * in the SearchIndexer
159      * @exception AccessDeniedException Insufficent credentials
160      */

161     public void grantPermission(SlideToken token, ObjectNode object,
162                                 SubjectNode subject, ActionNode action)
163         throws ServiceAccessException, ObjectNotFoundException,
164         AccessDeniedException {
165         grantPermission(token, object, subject, action, true);
166     }
167
168
169     /**
170      * Grants a new permission.
171      *
172      * @param token Credentials token
173      * @param object Object on which permission is granted
174      * @param subject Subject who can perform the action
175      * @param action Action which can be performed
176      * @param inheritable Create an inheritable permission
177      * @exception ServiceAccessException SearchIndexer access error
178      * @exception ObjectNotFoundException Specified object was not found
179      * in the SearchIndexer
180      * @exception AccessDeniedException Insufficent credentials
181      */

182     public void grantPermission(SlideToken token, ObjectNode object,
183                                 SubjectNode subject, ActionNode action,
184                                 boolean inheritable)
185         throws ServiceAccessException, ObjectNotFoundException,
186         AccessDeniedException {
187         NodePermission permission = new NodePermission(object, subject, action,
188                                                        inheritable);
189         grantPermission(token, permission);
190     }
191
192
193     /**
194      * Grants a new permission.
195      *
196      * @param token Credentials token
197      * @param permission New permission
198      * @exception ServiceAccessException SearchIndexer access error
199      * @exception ObjectNotFoundException Specified object was not found
200      * in the SearchIndexer
201      * @exception AccessDeniedException Insufficent credentials
202      */

203     public void grantPermission(SlideToken token,
204                                 NodePermission permission)
205         throws ServiceAccessException, ObjectNotFoundException,
206         AccessDeniedException {
207         Uri objectUri = namespace.getUri(token, permission.getObjectUri());
208         ObjectNode object = objectUri.getStore()
209             .retrieveObject(objectUri);
210
211         checkCredentials(token, object,
212                          namespaceConfig.getGrantPermissionAction());
213
214         mapRoles(permission);
215
216         // Checking if the permission is already present
217
Enumeration JavaDoc permissions = enumeratePermissions(token, object);
218         boolean alreadyPresent = false;
219         while (permissions.hasMoreElements()) {
220             NodePermission currentPermission = (NodePermission) permissions.nextElement();
221             if ((currentPermission.objectUri.equals(permission.getObjectUri()))
222                 && (currentPermission.subjectUri.equals(permission.getSubjectUri()))
223                 && (currentPermission.actionUri.equals(permission.getActionUri()))) {
224                 if (currentPermission.negative == permission.negative) {
225                     alreadyPresent = true;
226                 } else {
227                     objectUri.getStore().revokePermission(objectUri, currentPermission);
228                 }
229                 break;
230             }
231         }
232
233         if (!alreadyPresent) {
234             objectUri.getStore().grantPermission(objectUri, permission);
235         }
236     }
237
238
239
240     /**
241      * Deny a new permission.
242      *
243      * @param token Credentials token
244      * @param object Object on which permission is denied
245      * @param subject The subject to whom a action is denied
246      * @param action The action which is denied
247      * @exception ServiceAccessException SearchIndexer access error
248      * @exception ObjectNotFoundException Specified object was not found
249      * in the SearchIndexer
250      * @exception AccessDeniedException Insufficent credentials
251      */

252     public void denyPermission(SlideToken token, ObjectNode object,
253                                SubjectNode subject, ActionNode action)
254         throws ServiceAccessException, ObjectNotFoundException,
255         AccessDeniedException {
256         denyPermission(token, object, subject, action, true);
257     }
258
259
260     /**
261      * Deny a new permission.
262      *
263      * @param token Credentials token
264      * @param object Object on which permission is granted
265      * @param subject Subject who can perform the action
266      * @param action Action which can be performed
267      * @param inheritable Create an inheritable permission
268      * @exception ServiceAccessException SearchIndexer access error
269      * @exception ObjectNotFoundException Specified object was not found
270      * in the SearchIndexer
271      * @exception AccessDeniedException Insufficent credentials
272      */

273     public void denyPermission(SlideToken token, ObjectNode object,
274                                SubjectNode subject, ActionNode action,
275                                boolean inheritable)
276         throws ServiceAccessException, ObjectNotFoundException,
277         AccessDeniedException {
278         NodePermission permission = new NodePermission(object, subject, action,
279                                                        inheritable, true);
280         denyPermission(token, permission);
281     }
282
283
284     /**
285      * Deny a new permission.
286      *
287      * @param token Credentials token
288      * @param permission New permission
289      * @exception ServiceAccessException SearchIndexer access error
290      * @exception ObjectNotFoundException Specified object was not found
291      * in the SearchIndexer
292      * @exception AccessDeniedException Insufficent credentials
293      */

294     public void denyPermission(SlideToken token,
295                                NodePermission permission)
296         throws ServiceAccessException, ObjectNotFoundException,
297         AccessDeniedException {
298         // Make sure the permission we're about to set is indeed a negative
299
// permission
300
if (!permission.isNegative())
301             permission.setNegative(true);
302         grantPermission(token, permission);
303     }
304
305
306     /**
307      * Revokes a permission.
308      *
309      * @param token Credentials token
310      * @param object Object on which permission is revoked
311      * @param subject Subject who can perform the action
312      * @param action Action which can be performed
313      * @exception ServiceAccessException SearchIndexer access error
314      * @exception ObjectNotFoundException Specified object was not found
315      * in the SearchIndexer
316      * @exception AccessDeniedException Insufficent credentials
317      */

318     public void revokePermission(SlideToken token, ObjectNode object,
319                                  SubjectNode subject, ActionNode action)
320         throws ServiceAccessException, ObjectNotFoundException,
321         AccessDeniedException {
322         //Domain.info("Revoke permission on " + object.getUri());
323
checkCredentials(token, object, namespaceConfig
324                              .getRevokePermissionAction());
325         NodePermission permission = new NodePermission(object, subject,
326                                                        action);
327
328         mapRoles(permission);
329
330         Uri objectUri = namespace.getUri(token, object.getUri());
331         objectUri.getStore()
332             .revokePermission(objectUri, permission);
333     }
334
335
336
337     /**
338      * Revokes a permission.
339      *
340      * @param token Credentials token
341      * @param permission Permission to be removed
342      * @exception ServiceAccessException SearchIndexer access error
343      * @exception ObjectNotFoundException Specified object was not found
344      * in the SearchIndexer
345      * @exception AccessDeniedException Insufficent credentials
346      */

347     public void revokePermission(SlideToken token, NodePermission permission)
348         throws ServiceAccessException, ObjectNotFoundException,
349         AccessDeniedException {
350
351         Uri objectUri = namespace.getUri(token, permission.getObjectUri());
352         ObjectNode object = objectUri.getStore().retrieveObject(objectUri);
353
354         mapRoles(permission);
355
356         checkCredentials(token, object,
357                          namespaceConfig.getRevokePermissionAction());
358         objectUri.getStore().revokePermission(objectUri, permission);
359     }
360
361
362     /**
363      * Check if the credentials given grants permission to perform
364      * the specified action on the specified subject.
365      *
366      * @param token Credentials token
367      * @param object Object on which the action is performed
368      * @param action Action performed
369      * @exception ServiceAccessException SearchIndexer access error
370      * @exception AccessDeniedException The credentials does not grant
371      * the permission to perform the specified action
372      */

373     public void checkCredentials(SlideToken token, ObjectNode object,
374                                  ActionNode action)
375         throws ServiceAccessException, AccessDeniedException {
376
377         if (!token.isForceSecurity()) {
378             return;
379         }
380         else if (token.isForceStoreEnlistment()) {
381             token = new SlideTokenWrapper(token); // read only access
382
}
383
384         try {
385             if (Configuration.useIntegratedSecurity()) {
386                 // check if permission has already been checked
387
Boolean JavaDoc permission = token.checkPermissionCache(object, action);
388
389                 if (permission == null) {
390                     // if not checked before, check now
391
try {
392                         Uri objectUri = namespace.getUri(token, object.getUri());
393                         ObjectNode realObject = objectUri.getStore()
394                             .retrieveObject(objectUri);
395                         checkPermission(token, realObject, action);
396                         token.cachePermission(object, action, true);
397                     } catch (AccessDeniedException ade) {
398                         token.cachePermission(object, action, false);
399                         ade.fillInStackTrace();
400                         throw ade;
401                     }
402                 }
403                 else {
404                     if (!(permission.booleanValue())) {
405                         throw new AccessDeniedException
406                             (object.getUri(),
407                              getPrincipal(token).getPath().toString(),
408                              action.getUri());
409                     }
410                 }
411             }
412         } catch (ObjectNotFoundException e) {
413             String JavaDoc subjectUri = "*** Could not determine principal ***";
414             try {
415                 subjectUri = getPrincipal(token).getPath().toString();
416             } catch (Exception JavaDoc x) {}
417             throw new AccessDeniedException
418                 (object.getUri(),
419                  subjectUri,
420                  action.getUri());
421         }
422     }
423
424
425     /**
426      * Check whether or not an actor can perform the specified activity
427      * on a collection.
428      *
429      * @param object Object on which access is tested
430      * @param subject Subject who seeks to perform the action
431      * @param action Action which is to be performed
432      * @exception ServiceAccessException SearchIndexer access error
433      * @exception ObjectNotFoundException Specified object was not found
434      * in the SearchIndexer
435      * @exception AccessDeniedException Insufficent credentials
436      */

437     public void checkPermission(ObjectNode object, SubjectNode subject,
438                                 ActionNode action)
439         throws ServiceAccessException, AccessDeniedException,
440         ObjectNotFoundException {
441
442         if (!hasPermission(object, subject, action)) {
443             throw new AccessDeniedException(object.getUri(), subject.getUri(),
444                                             action.getUri());
445         }
446
447     }
448
449     /**
450      * Check whether or not an actor (principal) can perform the specified activity
451      * on the specified resource.
452      *
453      * @param token a SlideToken
454      * @param object Object on which access is tested
455      * @param action Action which is to be performed
456      *
457      * @throws ServiceAccessException
458      * @throws AccessDeniedException
459      * @throws ObjectNotFoundException
460      */

461     public void checkPermission(SlideToken token, ObjectNode object, ActionNode action) throws ServiceAccessException, AccessDeniedException, ObjectNotFoundException {
462
463         if (!hasPermission(token, object, action)) {
464             throw new AccessDeniedException(object.getUri(), getPrincipal(token).getUri(),
465                                             action.getUri());
466         }
467     }
468
469
470     /**
471      * Check whether or not an actor can perform the specified activity
472      * on a collection.
473      *
474      * @param object Object on which access is tested
475      * @param subject Subject who seeks to perform the action
476      * @param action Action which is to be performed
477      * @return true if the action can be performed
478      * @exception ServiceAccessException SearchIndexer access error
479      * @exception ObjectNotFoundException Specified object was not found
480      * in the SearchIndexer
481      */

482     public boolean hasPermission(ObjectNode object, SubjectNode subject,
483                                  ActionNode action)
484             throws ServiceAccessException, ObjectNotFoundException {
485         return hasPermission(object,subject,action, null);
486     }
487
488     /**
489      * Check whether or not an actor can perform the specified activity
490      * on a collection.
491      *
492      * @param object Object on which access is tested
493      * @param subject Subject who seeks to perform the action
494      * @param action Action which is to be performed
495      * @return true if the action can be performed
496      * @exception ServiceAccessException SearchIndexer access error
497      * @exception ObjectNotFoundException Specified object was not found
498      * in the SearchIndexer
499      */

500     private boolean hasPermission(ObjectNode object, SubjectNode subject,
501                                   ActionNode action, SlideToken token)
502             throws ServiceAccessException, ObjectNotFoundException {
503
504         // no check for default action (server intitialization)
505
if (action == ActionNode.DEFAULT) {
506             return true;
507         }
508
509         boolean granted = false;
510         boolean denied = false;
511         boolean rootObjectReached = false;
512
513
514         if (hasRole(subject, "root")) {
515             return true;
516         }
517
518         ObjectNode courObject = object;
519
520         Uri subjectUri = namespace.getUri(token, subject.getUri());
521         Uri actionUri = namespace.getUri(token, action.getUri());
522
523         // check if allready granded
524

525         Vector JavaDoc deniedSubjects = new Vector JavaDoc();
526
527         JahiaSite s = null;
528         try {
529             s = ServicesRegistry.getInstance().getJahiaSitesService().getSiteByKey(namespace.getName());
530         } catch (JahiaException e) {
531             throw new ServiceAccessException(null,e);
532         }
533         String JavaDoc[] strings = subjectUri.toString().split("/");
534         String JavaDoc uname;
535         if (strings.length < 3) {
536             uname = JahiaUserManagerService.GUEST_USERNAME;
537         } else {
538             uname = strings[2];
539         }
540         JahiaUser u = ServicesRegistry.getInstance().getJahiaUserManagerService().lookupUser(s.getID(), uname);
541
542         while (!granted && !rootObjectReached) {
543
544             Uri courUri = namespace.getUri(token, courObject.getUri());
545             Enumeration JavaDoc permissions = null;
546             try {
547                 permissions = courUri.getStore()
548                         .enumeratePermissions(courUri);
549             } catch (ServiceAccessException e) {
550                 Uri parentUri = courUri.getParentUri();
551
552                 if (parentUri != null) {
553                     courObject = parentUri.getStore()
554                         .retrieveObject(parentUri);
555                 } else {
556                     rootObjectReached = true;
557                 }
558
559                 continue;
560             }
561
562
563             while (!granted && permissions.hasMoreElements()) {
564
565                 NodePermission permission =
566                         (NodePermission) permissions.nextElement();
567                 String JavaDoc permissionSubject = permission.getSubjectUri();
568
569                 if (!deniedSubjects.contains(permissionSubject)) {
570                     if (permissionSubject == SubjectNode.SELF_URI) {
571
572                         boolean check;
573                         check = object.getUri().equals(subjectUri.toString());
574                         if (permission.isInheritable()) {
575                             String JavaDoc subjectUriString = subjectUri.toString();
576                             if(!subjectUriString.endsWith("/"))
577                                 subjectUriString = subjectUriString + "/";
578
579                             check |= object.getUri().startsWith(subjectUriString);
580                         }
581
582                         // Self permission
583
granted = (!permission.isNegative())
584                                 && (check)
585                                 && (actionUri.toString()
586                                 .startsWith(permission.getActionUri()));
587                         denied = (permission.isNegative())
588                                 && (check)
589                                 && (actionUri.toString()
590                                 .startsWith(permission.getActionUri()));
591
592                     } else if (permission.isInheritable()
593                             || permission.getObjectUri().equals(object.getUri())) {
594
595                         if (permissionSubject.startsWith("/")) {
596
597                             // Node permission
598

599                             String JavaDoc permSubj = permission.getSubjectUri();
600                             if(!permSubj.endsWith("/"))
601                                 permSubj = permSubj + "/";
602                             boolean match = subjectUri.toString().
603                                     equals(permission.getSubjectUri()) ||
604                                     subjectUri.toString().startsWith(permSubj);
605                             match &= actionUri.toString().
606                                     startsWith(permission.getActionUri());
607
608                             granted = (!permission.isNegative()) && match;
609                             denied = permission.isNegative() && match;
610
611                         } else if (permissionSubject.startsWith("+")) {
612
613                             // Permission group which needs to be expanded
614
Uri permissionSubjectUri =
615                                     namespace.getUri(token, permissionSubject.substring(1));
616                             ObjectNode group =
617                                     permissionSubjectUri.getStore().retrieveObject
618                                     (permissionSubjectUri);
619                             // if the node is a GroupNode, expand it out to
620
// normal permissions
621
if (group instanceof JahiaGroupNode ) {
622                                 JahiaGroup g = ServicesRegistry.getInstance().getJahiaGroupManagerService().lookupGroup(s.getID(), group.toString().split("/")[2]);
623                                 boolean match = g.isMember(u);
624
625                                 match &= actionUri.toString().
626                                         startsWith(permission.getActionUri());
627
628                                 granted = (!permission.isNegative()) &&
629                                         match;
630                                 denied = permission.isNegative() && match;
631                             }
632                         } else {
633
634                             // Role permission
635
granted = (!permission.isNegative())
636                                     && (hasRole(subject, permissionSubject))
637                                     && (actionUri.toString()
638                                     .startsWith(permission.getActionUri()));
639                             denied = (permission.isNegative())
640                                     && (hasRole(subject, permissionSubject))
641                                     && (actionUri.toString()
642                                     .startsWith(permission.getActionUri()));
643
644                         }
645                     }
646
647
648                     if (denied) deniedSubjects.add(permissionSubject);
649                 }
650             }
651
652             Uri parentUri = courUri.getParentUri();
653
654             if (parentUri != null) {
655                 courObject = parentUri.getStore()
656                     .retrieveObject(parentUri);
657             } else {
658                 rootObjectReached = true;
659             }
660         }
661
662
663         // GIVE PRIORITY TO POSITIVE PERMSSIONS (Jahia compliance)
664
if (granted) {
665             return true;
666         }
667
668         return false;
669     }
670
671     /**
672      * Check whether or not an actor (principal) can perform the specified activity
673      * on the specified resource.
674      *
675      * @param token a SlideToken
676      * @param object Object on which access is tested
677      * @param action Action which is to be performed
678      *
679      * @return true if the action can be performed
680      *
681      * @throws ServiceAccessException
682      * @throws ObjectNotFoundException
683      */

684     public boolean hasPermission(SlideToken token, ObjectNode object, ActionNode action) throws ServiceAccessException, ObjectNotFoundException {
685         Boolean JavaDoc cachedPermission = token.checkPermissionCache(object, action);
686         if (cachedPermission != null) {
687             return cachedPermission.booleanValue();
688         }
689         else {
690             return hasPermission(object, (SubjectNode)getPrincipal(token), action, token);
691         }
692     }
693
694
695     /**
696      * Enumerates permissions on an object.
697      *
698      * @param token Credentials token
699      * @param object Object on which permission is granted
700      * @exception ServiceAccessException SearchIndexer access error
701      * @exception ObjectNotFoundException Specified object was not found
702      * in the SearchIndexer
703      * @exception AccessDeniedException Insufficent credentials
704      */

705     public Enumeration JavaDoc enumeratePermissions(SlideToken token,
706                                             ObjectNode object)
707         throws ServiceAccessException, ObjectNotFoundException,
708         AccessDeniedException {
709
710         return enumeratePermissions(token, object, false);
711     }
712
713
714     /**
715      * Enumerates permissions on an object.
716      *
717      * @param token Credentials token
718      * @param object Object on which permission is granted
719      * @exception ServiceAccessException SearchIndexer access error
720      * @exception ObjectNotFoundException Specified object was not found
721      * in the SearchIndexer
722      * @exception AccessDeniedException Insufficent credentials
723      */

724     public Enumeration JavaDoc enumeratePermissions(SlideToken token,
725                                             ObjectNode object,
726                                             boolean includeInherited)
727         throws ServiceAccessException, ObjectNotFoundException {
728         return enumeratePermissions(token, object.getUri(), includeInherited);
729     }
730
731
732     /**
733      * Enumerates permissions on an object.
734      *
735      * @param token Credentials token
736      * @param object Object on which permission is granted
737      * @exception ServiceAccessException SearchIndexer access error
738      * @exception ObjectNotFoundException Specified object was not found
739      * in the SearchIndexer
740      * @exception AccessDeniedException Insufficent credentials
741      */

742     public Enumeration JavaDoc enumeratePermissions(SlideToken token,
743                                             String JavaDoc object)
744         throws ServiceAccessException, ObjectNotFoundException,
745         AccessDeniedException {
746
747         return enumeratePermissions(token, object, false);
748     }
749
750
751     /**
752      * Enumerates permissions on an object.
753      *
754      * @param token Credentials token
755      * @param object Object on which permission is granted
756      * @exception ServiceAccessException SearchIndexer access error
757      * @exception ObjectNotFoundException Specified object was not found
758      * in the SearchIndexer
759      * @exception AccessDeniedException Insufficent credentials
760      */

761     public Enumeration JavaDoc enumeratePermissions(SlideToken token,
762                                             String JavaDoc object,
763                                             boolean includeInherited)
764         throws ServiceAccessException, ObjectNotFoundException {
765
766         Uri objectUri = namespace.getUri(token, object);
767         if (!includeInherited) {
768             return objectUri.getStore().enumeratePermissions(objectUri);
769         }
770         else {
771             ObjectNode objectNode = objectUri.getStore().retrieveObject(objectUri);
772             Iterator JavaDoc i = retrieveAclSourceNodes(token, objectNode).iterator();
773             Vector JavaDoc permissions = new Vector JavaDoc();
774             while (i.hasNext()) {
775                 ObjectNode oNode = (ObjectNode)i.next();
776                 Uri oUri = namespace.getUri(token, oNode.getUri());
777                 Enumeration JavaDoc permEnum = oUri.getStore().enumeratePermissions(oUri);
778                 while (permEnum.hasMoreElements()) {
779                     NodePermission perm = (NodePermission)permEnum.nextElement();
780                     if (object.equals(oNode.getUri())) {
781                         permissions.add(perm);
782                     }
783                     else if (perm.isInheritable()) {
784                         perm.setInheritedFrom(oNode.getUri());
785                         permissions.add(perm);
786                     }
787                 }
788             }
789             return permissions.elements();
790         }
791     }
792
793
794     /**
795      * Retrieve the list of object nodes from which to get the ACLs.
796      * The specified object is returned as first element of the list.
797      *
798      * @param token a SlideToken
799      * @param object an ObjectNode
800      *
801      * @return a List of ObjectNode
802      *
803      * @throws ServiceAccessException
804      * @throws ObjectNotFoundException
805      */

806     public List JavaDoc retrieveAclSourceNodes(SlideToken token, ObjectNode object)
807         throws ServiceAccessException, ObjectNotFoundException {
808
809         List JavaDoc result = new ArrayList JavaDoc();
810         if (token.isForceStoreEnlistment()) {
811             // get read-only token
812
token = new SlideTokenWrapper(token);
813         }
814
815         Uri uri;
816         switch (aclInheritanceType) {
817             case NamespaceConfig.ACL_INHERIT_TYPE_NONE:
818                 uri = namespace.getUri(token, object.getUri());
819                 result.add( uri.getStore().retrieveObject(uri) );
820                 break;
821             case NamespaceConfig.ACL_INHERIT_TYPE_ROOT:
822                 uri = namespace.getUri(token, object.getUri());
823                 Uri rootUri = namespace.getUri(token, uri.getScope().toString());
824                 result.add( uri.getStore().retrieveObject(uri) );
825                 result.add( rootUri.getStore().retrieveObject(rootUri) );
826                 break;
827             case NamespaceConfig.ACL_INHERIT_TYPE_PATH:
828                 uri = namespace.getUri(token, object.getUri());
829                 Enumeration JavaDoc enumeration = uri.getScopes();
830                 while (enumeration.hasMoreElements()) {
831                     Uri element = namespace.getUri(token, (String JavaDoc)enumeration.nextElement(), false);
832                     ObjectNode objectNode = element.getStore().retrieveObject(element);
833                     result.add(objectNode);
834                 }
835                 break;
836             case NamespaceConfig.ACL_INHERIT_TYPE_FULL:
837                 //TODO
838
break;
839             default:
840                 break;
841         }
842
843         return result;
844     }
845
846     /**
847      * Check whether or not the current user has the specified role.
848      *
849      * @param token Credentials token
850      * @param role Role
851      * @exception ServiceAccessException SearchIndexer access error
852      * @exception ObjectNotFoundException Specified object was not found
853      * in the SearchIndexer
854      */

855     public boolean hasRole(SlideToken token, String JavaDoc role)
856         throws ServiceAccessException, ObjectNotFoundException {
857
858         ObjectNode subject = getPrincipal(token);
859
860         return hasRole(subject, role);
861
862     }
863
864
865     /**
866      * Check whether or not the current user has the specified role.
867      *
868      * @param object Object node
869      * @param role Role
870      * @exception ServiceAccessException SearchIndexer access error
871      * @exception ObjectNotFoundException Specified object was not found
872      * in the SearchIndexer
873      */

874     public boolean hasRole(ObjectNode object, String JavaDoc role)
875         throws ServiceAccessException, ObjectNotFoundException {
876
877         if (role.equals(NamespaceConfig.NOBODY) || role.equals("all"))
878             return true;
879         String JavaDoc associatedRole = namespaceConfig.getRoleMapping(role);
880         if ((associatedRole != null)
881             && (associatedRole.equals(NamespaceConfig.NOBODY) || role.equals("all")))
882             return true;
883
884         Class JavaDoc roleClass = (Class JavaDoc) rolesCache.get(role);
885         if ((roleClass == null) && (associatedRole != null)) {
886             roleClass = (Class JavaDoc) rolesCache.get(associatedRole);
887             if (roleClass == null) {
888                 try {
889                     roleClass = Class.forName(associatedRole);
890                     rolesCache.put(role, roleClass);
891                     rolesCache.put(associatedRole, roleClass);
892                 } catch (ClassNotFoundException JavaDoc ex) {
893                 }
894             }
895         }
896         if (roleClass == null) {
897             try {
898                 roleClass = Class.forName(role);
899                 rolesCache.put(role, roleClass);
900             } catch (ClassNotFoundException JavaDoc e) {
901             }
902         }
903         if (roleClass == null) {
904             return false;
905         }
906
907         if (roleClass.isInstance(object))
908             return true;
909
910         return false;
911
912     }
913
914
915     /**
916      * Return the list of roles the specified node has.
917      *
918      * @param object Object node
919      */

920     public Enumeration JavaDoc getRoles(ObjectNode object) {
921
922         Vector JavaDoc result = new Vector JavaDoc();
923         result.addElement(NamespaceConfig.NOBODY);
924         result.addElement("all");
925
926         Class JavaDoc currentObjectClass = object.getClass();
927
928         while (!currentObjectClass.equals(ObjectNode.class)) {
929
930             Class JavaDoc[] interfaces = currentObjectClass.getInterfaces();
931             for (int i = 0; i < interfaces.length; i++) {
932                 String JavaDoc className = interfaces[i].getName();
933                 String JavaDoc associatedName =
934                     namespaceConfig.getRoleMapping(className);
935                 if (associatedName != null)
936                     result.addElement(associatedName);
937                 else
938                     result.addElement(className);
939             }
940
941             currentObjectClass = currentObjectClass.getSuperclass();
942             if (currentObjectClass == null) {
943                 // Illegal state
944
throw new IllegalStateException JavaDoc("Invalid node");
945             }
946
947         }
948
949         return result.elements();
950
951     }
952
953
954     /**
955      * Return the list of roles the specified token has.
956      *
957      * @param token Credentials token
958      */

959     public Enumeration JavaDoc getRoles(SlideToken token)
960         throws ServiceAccessException, ObjectNotFoundException {
961         return getRoles(getPrincipal(token));
962     }
963
964     public Enumeration JavaDoc getRoles(SlideToken token, SubjectNode subjectNode)
965         throws ServiceAccessException, ObjectNotFoundException {
966         return getRoles(subjectNode);
967     }
968
969     /**
970      * Get the SubjectNode associated with the credentials token.
971      *
972      * @param token a SlideToken
973      * @return an ObjectNode
974      * @throws ServiceAccessException
975      * @throws ObjectNotFoundException
976      */

977     public ObjectNode getPrincipal(SlideToken token)
978         throws ServiceAccessException, ObjectNotFoundException {
979
980         String JavaDoc user =
981             token.getCredentialsToken().getPublicCredentials();
982         if ((user == null) || user.equals("") || user.equals("/")) {
983             return SubjectNode.UNAUTHENTICATED;
984         }
985
986         Uri subjectUri = namespace.getUri
987             (token, namespaceConfig.getUsersPath()+"/"+user);
988
989         try {
990             return subjectUri.getStore().retrieveObject(subjectUri);
991         } catch (ObjectNotFoundException e) {
992             if (!namespaceConfig.isAutoCreateUsers()) {
993                 throw e;
994             }
995             else {
996                 try {
997                     Uri parentUri = subjectUri.getParentUri();
998                     ObjectNode parent =
999                         subjectUri.getStore().retrieveObject(parentUri);
1000                    Enumeration JavaDoc childrenEnum = parent.enumerateChildren();
1001                    Enumeration JavaDoc linksEnum = parent.enumerateLinks();
1002                    Vector JavaDoc children = new Vector JavaDoc();
1003                    while (childrenEnum.hasMoreElements()) {
1004                        children.addElement(childrenEnum.nextElement());
1005                    }
1006                    children.addElement(subjectUri.toString());
1007                    Vector JavaDoc links = new Vector JavaDoc();
1008                    while (linksEnum.hasMoreElements()) {
1009                        links.addElement(linksEnum.nextElement());
1010                    }
1011
1012                    // First, load the object's class
1013
Class JavaDoc objectClass = Class.forName
1014                        (namespaceConfig.getAutoCreateUsersRole());
1015                    Class JavaDoc[] types = { String JavaDoc.class };
1016                    Object JavaDoc[] args = { subjectUri.toString() };
1017                    Constructor JavaDoc constructor =
1018                        objectClass.getConstructor(types);
1019                    ObjectNode object =
1020                        (ObjectNode) constructor.newInstance(args);
1021                    subjectUri.getStore().createObject(subjectUri, object);
1022
1023                    Class JavaDoc[] types2 =
1024                    { String JavaDoc.class, Vector JavaDoc.class, Vector JavaDoc.class };
1025                    Object JavaDoc[] args2 = { parentUri.toString(), children, links };
1026                    constructor = parent.getClass().getConstructor(types2);
1027                    object = (ObjectNode) constructor.newInstance(args2);
1028                    parentUri.getStore().storeObject(parentUri, object);
1029                } catch (ClassNotFoundException JavaDoc ex) {
1030                    // Can't find role implementing class
1031
throw new ObjectNotFoundException(subjectUri);
1032                } catch (NoSuchMethodException JavaDoc ex) {
1033                    // Can't find appropriate constructor
1034
throw new ObjectNotFoundException(subjectUri);
1035                } catch (InstantiationException JavaDoc ex) {
1036                    // Can't instatiate object
1037
throw new ObjectNotFoundException(subjectUri);
1038                } catch (InvocationTargetException JavaDoc ex) {
1039                    // Can't invoke constructor
1040
throw new ObjectNotFoundException(subjectUri);
1041                } catch (IllegalAccessException JavaDoc ex) {
1042                    // Constructor is not public
1043
throw new ObjectNotFoundException(subjectUri);
1044                } catch (ObjectAlreadyExistsException ex) {
1045                    // Should never happen
1046
e.printStackTrace();
1047                    throw new ObjectNotFoundException(subjectUri);
1048                }
1049                return subjectUri.getStore().retrieveObject(subjectUri);
1050            }
1051        }
1052    }
1053
1054    private void loadActionsCache(Namespace namespace, NamespaceConfig namespaceConfig) {
1055        try {
1056            actionAggregation = new HashMap JavaDoc();
1057            actionAggregationClosure = new HashMap JavaDoc();
1058            String JavaDoc actionsPath = namespaceConfig.getActionsPath();
1059            Uri actionsPathUri = namespace.getUri(actionsPath);
1060            ObjectNode actionsPathNode = actionsPathUri.getStore().retrieveObject(actionsPathUri);
1061            Enumeration JavaDoc actions = actionsPathNode.enumerateChildren();
1062            while (actions.hasMoreElements()) {
1063                ActionNode aNode = ActionNode.getActionNode((String JavaDoc)actions.nextElement());
1064                Set JavaDoc directAggregates = getActionAggregates(aNode);
1065                actionAggregation.put(aNode, directAggregates);
1066                Set JavaDoc aClosure = new HashSet JavaDoc();
1067                aClosure.add(aNode);
1068                aClosure.addAll(directAggregates);
1069                actionAggregationClosure.put(aNode, aClosure);
1070            }
1071            Iterator JavaDoc keys = actionAggregationClosure.keySet().iterator();
1072            while (keys.hasNext()) {
1073                ActionNode aNode = (ActionNode)keys.next();
1074                Set JavaDoc aClosure = (Set JavaDoc)actionAggregationClosure.get(aNode);
1075                actionAggregationClosure.put(aNode, buildClosure(aClosure));
1076            }
1077            // log success
1078
if (logger.isEnabled(LOG_CHANNEL, Logger.INFO)) {
1079                logger.log("Action aggregations loaded successfully", LOG_CHANNEL, Logger.INFO);
1080            }
1081            if (logger.isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
1082                logger.log("\n@@@ Actions aggregations", LOG_CHANNEL, Logger.DEBUG);
1083                Iterator JavaDoc i = actionAggregation.entrySet().iterator();
1084                while (i.hasNext()) {
1085                    logger.log(" "+i.next(), LOG_CHANNEL, Logger.DEBUG);
1086                }
1087                logger.log("\n@@@ Action aggregations (transitive closure)", LOG_CHANNEL, Logger.DEBUG);
1088                i = actionAggregationClosure.entrySet().iterator();
1089                while (i.hasNext()) {
1090                    logger.log(" "+i.next(), LOG_CHANNEL, Logger.DEBUG);
1091                }
1092            }
1093        }
1094        catch (Throwable JavaDoc e) {
1095            actionAggregation = null;
1096            actionAggregationClosure = null;
1097        }
1098    }
1099
1100    private Set JavaDoc buildClosure(Set JavaDoc aClosure) {
1101        Set JavaDoc result = new HashSet JavaDoc(aClosure);
1102        int size = 0;
1103        while (result.size() > size) {
1104            size = result.size();
1105            Set JavaDoc newResult = new HashSet JavaDoc();
1106            Iterator JavaDoc i = result.iterator();
1107            while (i.hasNext()) {
1108                newResult.addAll((Set JavaDoc)actionAggregationClosure.get(i.next()));
1109            }
1110            result = newResult;
1111        }
1112        return result;
1113    }
1114
1115    /**
1116     * Get the direct aggregates
1117     *
1118     * @param aNode an ActionNode
1119     * @return set of direct aggregates (ActionNode objects)
1120     * @throws SlideException
1121     * @throws JDOMException
1122     */

1123    private Set JavaDoc getActionAggregates(ActionNode aNode) throws SlideException, JDOMException {
1124        Set JavaDoc result = new HashSet JavaDoc();
1125        Uri aNodeUri = namespace.getUri(aNode.getUri());
1126        NodeRevisionDescriptor aNrd = aNodeUri.getStore().retrieveRevisionDescriptor(aNodeUri, new NodeRevisionNumber());
1127        NodeProperty membersProp = aNrd.getProperty("privilege-member-set");
1128        if (membersProp != null && membersProp.getValue() != null) {
1129            XMLValue membersVal;
1130            if (membersProp.getValue() instanceof XMLValue) {
1131                membersVal = (XMLValue)membersProp.getValue();
1132            }
1133            else {
1134                membersVal = new XMLValue((String JavaDoc)membersProp.getValue());
1135            }
1136            Iterator JavaDoc mUris = membersVal.getHrefStrings().iterator();
1137            while (mUris.hasNext()) {
1138                result.add(ActionNode.getActionNode((String JavaDoc)mUris.next()));
1139            }
1140        }
1141        return result;
1142    }
1143
1144    /**
1145     * Return true, if-and-only-if checkAction matches permAction.
1146     *
1147     * @param checkAction the "current" action
1148     * @param permAction the action to check against
1149     * (from NodePermission or NodeLock)
1150     *
1151     * @return a boolean
1152     *
1153     */

1154    public boolean matchAction(SlideToken token, ActionNode checkAction, ActionNode permAction) throws ServiceAccessException {
1155        if (permAction == ActionNode.ALL) {
1156            return true;
1157        }
1158        else {
1159            if (actionAggregationClosure != null) {
1160                Set JavaDoc permActionSet = (Set JavaDoc)actionAggregationClosure.get(permAction);
1161                if (permActionSet == null) {
1162                    logger.log("Unknown action " + permAction.getUri() , LOG_CHANNEL, Logger.WARNING);
1163                    return false;
1164                } else {
1165                    return permActionSet.contains(checkAction);
1166                }
1167            }
1168            else {
1169                Uri u = namespace.getUri(token, checkAction.getUri());
1170                Store s = u.getStore();
1171                throw new ServiceAccessException(s, "Actions cache not loaded");
1172            }
1173        }
1174    }
1175
1176    /**
1177     * Return true, if-and-only-if checkSubject matches permSubject.
1178     *
1179     * @param token a SlideToken
1180     * @param checkSubject the "current" principal
1181     * @param matchSubject the principal to check against (e.g. user
1182     * or group from NodePermission or NodeLock)
1183     *
1184     * @return a boolean
1185     *
1186     * @throws ServiceAccessException
1187     *
1188     */

1189    public boolean matchPrincipal(SlideToken token, SubjectNode checkSubject, SubjectNode matchSubject) throws ServiceAccessException {
1190        Boolean JavaDoc b = token.checkMatchPrincipalCache(checkSubject, matchSubject);
1191        if (b != null) {
1192            return b.booleanValue();
1193        }
1194        else {
1195            boolean match = matchPrincipal(token, checkSubject, matchSubject, namespaceConfig.getNestedRolesMaxDepth());
1196            token.cacheMatchPrincipal(checkSubject, matchSubject, match);
1197            return match;
1198        }
1199    }
1200
1201    /**
1202     * Return true, if-and-only-if checkSubject matches permSubject.
1203     *
1204     * @param token a SlideToken
1205     * @param checkSubject the "current" principal
1206     * @param matchSubject the principal to check against (e.g. user
1207     * or group from NodePermission or NodeLock)
1208     *
1209     * @return a boolean
1210     *
1211     * @throws ServiceAccessException
1212     *
1213     */

1214    public boolean matchPrincipal(SlideToken token, SubjectNode checkSubject, SubjectNode matchSubject, int level) throws ServiceAccessException {
1215        if (matchSubject.equals(checkSubject)) {
1216            return true;
1217        }
1218        else {
1219            Uri groupUri = namespace.getUri(token, matchSubject.getUri());
1220            try {
1221                NodeRevisionDescriptor nrd =
1222                    groupUri.getStore().retrieveRevisionDescriptor(groupUri, new NodeRevisionNumber());
1223                NodeProperty membersetProp = nrd.getProperty("group-member-set");
1224                if (membersetProp != null && membersetProp.getValue() != null) {
1225                    XMLValue xmlVal = new XMLValue((String JavaDoc)membersetProp.getValue());
1226                    List JavaDoc memberNodes = xmlVal.getHrefNodes();
1227                    if (memberNodes.contains(checkSubject)) {
1228                        return true;
1229                    }
1230                    else if (level > 0) {
1231                        int nextLevel = level - 1;
1232                        boolean match = false;
1233                        Iterator JavaDoc i = memberNodes.iterator();
1234                        while (!match && i.hasNext()) {
1235                            SubjectNode nextMatchNode = (SubjectNode)i.next();
1236                            if (namespaceConfig.isRole(nextMatchNode.getUri())
1237                                || namespaceConfig.isGroup(nextMatchNode.getUri())) {
1238
1239                                match = matchPrincipal(token, checkSubject, nextMatchNode, nextLevel);
1240                            }
1241                        }
1242                        return match;
1243                    }
1244                    else {
1245                        return false;
1246                    }
1247                }
1248                else {
1249                    return false;
1250                }
1251            }
1252            catch (RevisionDescriptorNotFoundException e) {
1253                return false;
1254            }
1255            catch (ServiceAccessException e) {
1256                throw e;
1257            }
1258            catch (JDOMException e) {
1259                e.printStackTrace();
1260                return false;
1261            }
1262        }
1263    }
1264
1265    /**
1266     * Method getActionAggregation
1267     * @return a Map: actionNode -> Set-of-aggregated-nodes (direct aggregates)
1268     */

1269    public Map JavaDoc getActionAggregation() {
1270        return Collections.unmodifiableMap(actionAggregation);
1271    }
1272
1273    private void mapRoles(NodePermission permission) {
1274        String JavaDoc subject = permission.getSubjectUri();
1275        // translate special groups to slide roles
1276
if (("+/groups/"+JahiaGroupManagerService.GUEST_GROUPNAME+"/members").equals(subject)) {
1277            subject = "all";
1278        } else if (("+/groups/"+JahiaGroupManagerService.ADMINISTRATORS_GROUPNAME+"/members").equals(subject)) {
1279            subject = "root";
1280        } else if (("+/groups/"+JahiaGroupManagerService.USERS_GROUPNAME+"/members").equals(subject)) {
1281            subject = "authenticated";
1282        } else if (("/users/"+JahiaUserManagerService.GUEST_USERNAME).equals(subject)) {
1283            subject = "unauthenticated";
1284        }
1285        permission.setSubject(subject);
1286    }
1287
1288}
Popular Tags