]> source.dussan.org Git - archiva.git/blob
868df6cda851732c9ae3780b4b7b475d74fcf9df
[archiva.git] /
1 package org.apache.archiva.redback.rbac.ldap;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import com.google.common.base.Function;
23 import com.google.common.collect.Lists;
24 import org.apache.archiva.redback.common.ldap.MappingException;
25 import org.apache.archiva.redback.common.ldap.connection.LdapConnection;
26 import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory;
27 import org.apache.archiva.redback.common.ldap.connection.LdapException;
28 import org.apache.archiva.redback.common.ldap.role.LdapRoleMapper;
29 import org.apache.archiva.redback.components.cache.Cache;
30 import org.apache.archiva.redback.configuration.UserConfiguration;
31 import org.apache.archiva.redback.configuration.UserConfigurationKeys;
32 import org.apache.archiva.redback.rbac.AbstractRBACManager;
33 import org.apache.archiva.redback.rbac.AbstractRole;
34 import org.apache.archiva.redback.rbac.Operation;
35 import org.apache.archiva.redback.rbac.Permission;
36 import org.apache.archiva.redback.rbac.RBACManager;
37 import org.apache.archiva.redback.rbac.RBACManagerListener;
38 import org.apache.archiva.redback.rbac.RBACObjectAssertions;
39 import org.apache.archiva.redback.rbac.RbacManagerException;
40 import org.apache.archiva.redback.rbac.RbacObjectInvalidException;
41 import org.apache.archiva.redback.rbac.RbacObjectNotFoundException;
42 import org.apache.archiva.redback.rbac.RbacPermanentException;
43 import org.apache.archiva.redback.rbac.Resource;
44 import org.apache.archiva.redback.rbac.Role;
45 import org.apache.archiva.redback.rbac.UserAssignment;
46 import org.apache.archiva.redback.users.User;
47 import org.apache.archiva.redback.users.UserManager;
48 import org.apache.archiva.redback.users.UserManagerException;
49 import org.apache.archiva.redback.users.ldap.ctl.LdapController;
50 import org.apache.archiva.redback.users.ldap.ctl.LdapControllerException;
51 import org.apache.commons.lang.StringUtils;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54 import org.springframework.stereotype.Service;
55
56 import javax.annotation.PostConstruct;
57 import javax.inject.Inject;
58 import javax.inject.Named;
59 import javax.naming.NamingException;
60 import javax.naming.directory.DirContext;
61 import java.util.ArrayList;
62 import java.util.Collection;
63 import java.util.Collections;
64 import java.util.HashSet;
65 import java.util.List;
66 import java.util.Map;
67 import java.util.Set;
68
69 /**
70  * LdapRbacManager will read datas from ldap for mapping groups to role.
71  * Write operations will delegate to cached implementation.
72  *
73  * @author Olivier Lamy
74  */
75 @Service( "rbacManager#ldap" )
76 public class LdapRbacManager
77     extends AbstractRBACManager
78     implements RBACManager, RBACManagerListener
79 {
80
81     private Logger log = LoggerFactory.getLogger( getClass() );
82
83     @Inject
84     @Named( value = "rbacManager#cached" )
85     private RBACManager rbacImpl;
86
87     @Inject
88     @Named( value = "ldapRoleMapper#default" )
89     private LdapRoleMapper ldapRoleMapper;
90
91     @Inject
92     @Named( value = "userConfiguration#default" )
93     private UserConfiguration userConf;
94
95     @Inject
96     @Named( value = "userManager#ldap" )
97     private UserManager userManager;
98
99     @Inject
100     private LdapConnectionFactory ldapConnectionFactory;
101
102     @Inject
103     private LdapController ldapController;
104
105     @Inject
106     @Named( value = "cache#ldapRoles" )
107     private Cache<String, Role> rolesCache;
108
109     @Inject
110     @Named( value = "cache#userAssignments" )
111     private Cache<String, UserAssignment> userAssignmentsCache;
112
113     private boolean writableLdap = false;
114
115     @PostConstruct
116     public void initialize()
117     {
118         this.writableLdap = userConf.getBoolean( UserConfigurationKeys.LDAP_WRITABLE, this.writableLdap );
119     }
120
121
122     public void addChildRole( Role role, Role childRole )
123         throws RbacObjectInvalidException, RbacManagerException
124     {
125         this.rbacImpl.addChildRole( role, childRole );
126     }
127
128     public void addListener( RBACManagerListener listener )
129     {
130         super.addListener( listener );
131         this.rbacImpl.addListener( listener );
132     }
133
134     public Operation createOperation( String name )
135         throws RbacManagerException
136     {
137         return this.rbacImpl.createOperation( name );
138     }
139
140     public Permission createPermission( String name )
141         throws RbacManagerException
142     {
143         return this.rbacImpl.createPermission( name );
144     }
145
146     public Permission createPermission( String name, String operationName, String resourceIdentifier )
147         throws RbacManagerException
148     {
149         return this.rbacImpl.createPermission( name, operationName, resourceIdentifier );
150     }
151
152     public Resource createResource( String identifier )
153         throws RbacManagerException
154     {
155         return this.rbacImpl.createResource( identifier );
156     }
157
158     public Role createRole( String name )
159     {
160         return this.rbacImpl.createRole( name );
161     }
162
163     public UserAssignment createUserAssignment( String username )
164         throws RbacManagerException
165     {
166         // TODO ldap cannot or isWritable ldap ?
167         return this.rbacImpl.createUserAssignment( username );
168     }
169
170     public void eraseDatabase()
171     {
172         if ( writableLdap )
173         {
174             LdapConnection ldapConnection = null;
175             DirContext context = null;
176             try
177             {
178                 ldapConnection = ldapConnectionFactory.getConnection();
179                 context = ldapConnection.getDirContext();
180                 ldapRoleMapper.removeAllRoles( context );
181             }
182             catch ( MappingException e )
183             {
184                 log.warn( "skip error removing all roles {}", e.getMessage() );
185             }
186             catch ( LdapException e )
187             {
188                 log.warn( "skip error removing all roles {}", e.getMessage() );
189             }
190             finally
191             {
192                 closeContext( context );
193                 closeLdapConnection( ldapConnection );
194             }
195         }
196         this.rolesCache.clear();
197         this.userAssignmentsCache.clear();
198         this.rbacImpl.eraseDatabase();
199     }
200
201     /**
202      * @see org.apache.archiva.redback.rbac.RBACManager#getAllAssignableRoles()
203      */
204     public List<Role> getAllAssignableRoles()
205         throws RbacManagerException
206     {
207         try
208         {
209             Collection<Collection<String>> roleNames = ldapRoleMapper.getLdapGroupMappings().values();
210
211             Set<Role> roles = new HashSet<Role>();
212
213             for ( Collection<String> names : roleNames )
214             {
215                 for ( String name : names )
216                 {
217                     roles.add( new RoleImpl( name ) );
218                 }
219             }
220
221             return new ArrayList<Role>( roles );
222         }
223         catch ( MappingException e )
224         {
225             throw new RbacManagerException( e.getMessage(), e );
226         }
227     }
228
229     public List<Operation> getAllOperations()
230         throws RbacManagerException
231     {
232         return this.rbacImpl.getAllOperations();
233     }
234
235     public List<Permission> getAllPermissions()
236         throws RbacManagerException
237     {
238         return this.rbacImpl.getAllPermissions();
239     }
240
241     public List<Resource> getAllResources()
242         throws RbacManagerException
243     {
244         return this.rbacImpl.getAllResources();
245     }
246
247     public List<Role> getAllRoles()
248         throws RbacManagerException
249     {
250         LdapConnection ldapConnection = null;
251         DirContext context = null;
252         try
253         {
254             ldapConnection = ldapConnectionFactory.getConnection();
255             context = ldapConnection.getDirContext();
256
257             List<String> groups = ldapRoleMapper.getAllGroups( context );
258             return mapToRoles( groups );
259         }
260         catch ( MappingException e )
261         {
262             throw new RbacManagerException( e.getMessage(), e );
263         }
264         catch ( LdapException e )
265         {
266             throw new RbacManagerException( e.getMessage(), e );
267         }
268         finally
269         {
270             closeContext( context );
271             closeLdapConnection( ldapConnection );
272         }
273         //return this.rbacImpl.getAllRoles();
274     }
275
276
277     public List<UserAssignment> getAllUserAssignments()
278         throws RbacManagerException
279     {
280         LdapConnection ldapConnection = null;
281         DirContext context = null;
282         try
283         {
284             ldapConnection = ldapConnectionFactory.getConnection();
285             context = ldapConnection.getDirContext();
286             Map<String, Collection<String>> usersWithRoles = ldapController.findUsersWithRoles( context );
287             List<UserAssignment> userAssignments = new ArrayList<UserAssignment>( usersWithRoles.size() );
288
289             for ( Map.Entry<String, Collection<String>> entry : usersWithRoles.entrySet() )
290             {
291                 UserAssignment userAssignment = new UserAssignmentImpl( entry.getKey(), entry.getValue() );
292                 userAssignments.add( userAssignment );
293                 userAssignmentsCache.put( userAssignment.getPrincipal(), userAssignment );
294             }
295
296             return userAssignments;
297         }
298         catch ( LdapControllerException e )
299         {
300             throw new RbacManagerException( e.getMessage(), e );
301         }
302         catch ( LdapException e )
303         {
304             throw new RbacManagerException( e.getMessage(), e );
305         }
306         finally
307         {
308             closeContext( context );
309             closeLdapConnection( ldapConnection );
310         }
311     }
312
313     protected void closeLdapConnection( LdapConnection ldapConnection )
314     {
315         if ( ldapConnection != null )
316         {
317             ldapConnection.close();
318         }
319     }
320
321     protected void closeContext( DirContext context )
322     {
323         if ( context != null )
324         {
325             try
326             {
327                 context.close();
328             }
329             catch ( NamingException e )
330             {
331                 log.warn( "skip issue closing context: {}", e.getMessage() );
332             }
333         }
334     }
335
336     /**
337      * public Map<String, List<Permission>> getAssignedPermissionMap( String username )
338      * throws RbacManagerException
339      * {
340      * return this.rbacImpl.getAssignedPermissionMap( username );
341      * }*
342      */
343
344     /*public Set<Permission> getAssignedPermissions( String username )
345         throws RbacObjectNotFoundException, RbacManagerException
346     {
347         // TODO here !!
348         return this.rbacImpl.getAssignedPermissions( username );
349     }*/
350     private List<Role> mapToRoles( List<String> groups )
351         throws MappingException, RbacManagerException
352     {
353         if ( groups == null || groups.isEmpty() )
354         {
355             return Collections.emptyList();
356         }
357
358         List<Role> roles = new ArrayList<Role>( groups.size() );
359         Map<String, Collection<String>> mappedGroups = ldapRoleMapper.getLdapGroupMappings();
360         for ( String group : groups )
361         {
362             Collection<String> roleNames = mappedGroups.get( group );
363             if ( roleNames != null )
364             {
365                 for ( String roleName : roleNames )
366                 {
367                     Role role = this.rbacImpl.getRole( roleName );
368                     role = ( role == null ) ? new RoleImpl( roleName ) : role;
369                     if ( role != null )
370                     {
371                         rolesCache.put( role.getName(), role );
372                         roles.add( role );
373                     }
374                 }
375             }
376             else if ( this.ldapRoleMapper.isUseDefaultRoleName() )
377             {
378                 Role role = null;
379                 try
380                 {
381                     role = this.rbacImpl.getRole( group );
382                 }
383                 catch ( RbacObjectNotFoundException e )
384                 {
385                     // if it's mapped role to a group it doesn't exist in jdo
386                 }
387                 role = ( role == null ) ? new RoleImpl( group ) : role;
388                 if ( role != null )
389                 {
390                     rolesCache.put( role.getName(), role );
391                     roles.add( role );
392                 }
393
394             }
395         }
396         return roles;
397
398     }
399
400     protected List<String> getRealRoles()
401         throws RbacManagerException
402     {
403         List<Role> roles = this.rbacImpl.getAllRoles();
404         List<String> roleNames = new ArrayList<String>( roles.size() );
405         for ( Role role : roles )
406         {
407             roleNames.add( role.getName() );
408         }
409         return roleNames;
410     }
411
412     public Collection<Role> getAssignedRoles( String username )
413         throws RbacManagerException
414     {
415
416         LdapConnection ldapConnection = null;
417         DirContext context = null;
418
419         try
420         {
421
422             ldapConnection = ldapConnectionFactory.getConnection();
423             context = ldapConnection.getDirContext();
424             List<String> roleNames = ldapRoleMapper.getRoles( username, context, getRealRoles() );
425
426             if ( roleNames.isEmpty() )
427             {
428                 return Collections.emptyList();
429             }
430
431             List<Role> roles = new ArrayList<Role>( roleNames.size() );
432
433             for ( String name : roleNames )
434             {
435                 roles.add( this.rbacImpl.getRole( name ) );// new RoleImpl( name ) );
436             }
437
438             return roles;
439         }
440         catch ( MappingException e )
441         {
442             throw new RbacManagerException( e.getMessage(), e );
443         }
444         catch ( LdapException e )
445         {
446             throw new RbacManagerException( e.getMessage(), e );
447         }
448     }
449
450     public Collection<Role> getAssignedRoles( UserAssignment userAssignment )
451         throws RbacManagerException
452     {
453         return getAssignedRoles( userAssignment.getPrincipal() );
454     }
455
456     public Map<String, Role> getChildRoles( Role role )
457         throws RbacManagerException
458     {
459         return this.rbacImpl.getChildRoles( role );
460     }
461
462     public Map<String, Role> getParentRoles( Role role )
463         throws RbacManagerException
464     {
465         return this.rbacImpl.getParentRoles( role );
466     }
467
468     /**
469      public Collection<Role> getEffectivelyAssignedRoles( String username )
470      throws RbacManagerException
471      {
472      // TODO here !!
473      return this.rbacImpl.getEffectivelyAssignedRoles( username );
474      }**/
475
476     /**
477      * public Collection<Role> getEffectivelyUnassignedRoles( String username )
478      * throws RbacManagerException
479      * {
480      * // TODO here !!
481      * return this.rbacImpl.getEffectivelyUnassignedRoles( username );
482      * }*
483      */
484
485     public Set<Role> getEffectiveRoles( Role role )
486         throws RbacManagerException
487     {
488         return this.rbacImpl.getEffectiveRoles( role );
489     }
490
491     public Resource getGlobalResource()
492         throws RbacManagerException
493     {
494         return this.rbacImpl.getGlobalResource();
495     }
496
497     public Operation getOperation( String operationName )
498         throws RbacManagerException
499     {
500         return this.rbacImpl.getOperation( operationName );
501     }
502
503     public Permission getPermission( String permissionName )
504         throws RbacManagerException
505     {
506         return this.rbacImpl.getPermission( permissionName );
507     }
508
509     public Resource getResource( String resourceIdentifier )
510         throws RbacManagerException
511     {
512         return this.rbacImpl.getResource( resourceIdentifier );
513     }
514
515     public Role getRole( String roleName )
516         throws RbacManagerException
517     {
518
519         Role role = rolesCache.get( roleName );
520         if ( role != null )
521         {
522             return role;
523         }
524         LdapConnection ldapConnection = null;
525         DirContext context = null;
526         //verify it's a ldap group
527         try
528         {
529             ldapConnection = ldapConnectionFactory.getConnection();
530             context = ldapConnection.getDirContext();
531             if ( !ldapRoleMapper.hasRole( context, roleName ) )
532             {
533                 return null;
534             }
535         }
536         catch ( MappingException e )
537         {
538             throw new RbacManagerException( e.getMessage(), e );
539         }
540         catch ( LdapException e )
541         {
542             throw new RbacManagerException( e.getMessage(), e );
543         }
544         role = this.rbacImpl.getRole( roleName );
545         role = ( role == null ) ? new RoleImpl( roleName ) : role;
546
547         rolesCache.put( roleName, role );
548
549         return role;
550     }
551
552     public Map<String, Role> getRoles( Collection<String> roleNames )
553         throws RbacManagerException
554     {
555         return this.rbacImpl.getRoles( roleNames );
556     }
557
558     public Collection<Role> getUnassignedRoles( String username )
559         throws RbacManagerException
560     {
561         LdapConnection ldapConnection = null;
562
563         DirContext context = null;
564
565         try
566         {
567
568             ldapConnection = ldapConnectionFactory.getConnection();
569
570             context = ldapConnection.getDirContext();
571
572             List<String> allRoles = ldapRoleMapper.getAllRoles( context );
573             final List<String> userRoles = ldapRoleMapper.getRoles( username, context, getRealRoles() );
574
575             List<Role> unassignedRoles = new ArrayList<Role>();
576
577             for ( String roleName : allRoles )
578             {
579                 if ( !userRoles.contains( roleName ) )
580                 {
581                     unassignedRoles.add( rbacImpl.getRole( roleName ) );
582                 }
583             }
584             return unassignedRoles;
585         }
586         catch ( MappingException e )
587         {
588             throw new RbacManagerException( e.getMessage(), e );
589         }
590         catch ( LdapException e )
591         {
592             throw new RbacManagerException( e.getMessage(), e );
593         }
594         finally
595         {
596             closeContext( context );
597             closeLdapConnection( ldapConnection );
598         }
599     }
600
601     public UserAssignment getUserAssignment( String username )
602         throws RbacManagerException
603     {
604         UserAssignment ua = userAssignmentsCache.get( username );
605         if ( ua != null )
606         {
607             return ua;
608         }
609         LdapConnection ldapConnection = null;
610         DirContext context = null;
611         try
612         {
613             ldapConnection = ldapConnectionFactory.getConnection();
614             context = ldapConnection.getDirContext();
615             List<String> roles = ldapRoleMapper.getRoles( username, context, getRealRoles() );
616
617             ua = new UserAssignmentImpl( username, roles );
618
619             userAssignmentsCache.put( username, ua );
620
621             return ua;
622         }
623         catch ( MappingException e )
624         {
625             throw new RbacManagerException( e.getMessage(), e );
626         }
627         catch ( LdapException e )
628         {
629             throw new RbacManagerException( e.getMessage(), e );
630         }
631         finally
632         {
633             closeContext( context );
634             closeLdapConnection( ldapConnection );
635         }
636
637         //return this.rbacImpl.getUserAssignment( username );
638     }
639
640     public List<UserAssignment> getUserAssignmentsForRoles( Collection<String> roleNames )
641         throws RbacManagerException
642     {
643         // TODO from ldap
644         return this.rbacImpl.getUserAssignmentsForRoles( roleNames );
645     }
646
647     public boolean operationExists( Operation operation )
648     {
649         return this.rbacImpl.operationExists( operation );
650     }
651
652     public boolean operationExists( String name )
653     {
654         return this.rbacImpl.operationExists( name );
655     }
656
657     public boolean permissionExists( Permission permission )
658     {
659         return this.rbacImpl.permissionExists( permission );
660     }
661
662     public boolean permissionExists( String name )
663     {
664         return this.rbacImpl.permissionExists( name );
665     }
666
667     public void rbacInit( boolean freshdb )
668     {
669         if ( rbacImpl instanceof RBACManagerListener )
670         {
671             ( (RBACManagerListener) this.rbacImpl ).rbacInit( freshdb );
672         }
673     }
674
675     public void rbacPermissionRemoved( Permission permission )
676     {
677         if ( rbacImpl instanceof RBACManagerListener )
678         {
679             ( (RBACManagerListener) this.rbacImpl ).rbacPermissionRemoved( permission );
680         }
681
682     }
683
684     public void rbacPermissionSaved( Permission permission )
685     {
686         if ( rbacImpl instanceof RBACManagerListener )
687         {
688             ( (RBACManagerListener) this.rbacImpl ).rbacPermissionSaved( permission );
689         }
690
691     }
692
693     public void rbacRoleRemoved( Role role )
694     {
695         if ( rbacImpl instanceof RBACManagerListener )
696         {
697             ( (RBACManagerListener) this.rbacImpl ).rbacRoleRemoved( role );
698         }
699
700     }
701
702     public void rbacRoleSaved( Role role )
703     {
704         if ( rbacImpl instanceof RBACManagerListener )
705         {
706             ( (RBACManagerListener) this.rbacImpl ).rbacRoleSaved( role );
707         }
708
709     }
710
711     public void rbacUserAssignmentRemoved( UserAssignment userAssignment )
712     {
713         if ( rbacImpl instanceof RBACManagerListener )
714         {
715             ( (RBACManagerListener) this.rbacImpl ).rbacUserAssignmentRemoved( userAssignment );
716         }
717
718     }
719
720     public void rbacUserAssignmentSaved( UserAssignment userAssignment )
721     {
722         if ( rbacImpl instanceof RBACManagerListener )
723         {
724             ( (RBACManagerListener) this.rbacImpl ).rbacUserAssignmentSaved( userAssignment );
725         }
726
727     }
728
729     public void removeListener( RBACManagerListener listener )
730     {
731         this.rbacImpl.removeListener( listener );
732     }
733
734     public void removeOperation( Operation operation )
735         throws RbacManagerException
736     {
737         this.rbacImpl.removeOperation( operation );
738     }
739
740     public void removeOperation( String operationName )
741         throws RbacManagerException
742     {
743         this.rbacImpl.removeOperation( operationName );
744     }
745
746     public void removePermission( Permission permission )
747         throws RbacManagerException
748     {
749         this.rbacImpl.removePermission( permission );
750     }
751
752     public void removePermission( String permissionName )
753         throws RbacManagerException
754     {
755         this.rbacImpl.removePermission( permissionName );
756     }
757
758     public void removeResource( Resource resource )
759         throws RbacManagerException
760     {
761         this.rbacImpl.removeResource( resource );
762     }
763
764     public void removeResource( String resourceIdentifier )
765         throws RbacManagerException
766     {
767         this.rbacImpl.removeResource( resourceIdentifier );
768     }
769
770     public void removeRole( Role role )
771         throws RbacManagerException
772     {
773         RBACObjectAssertions.assertValid( role );
774
775         if ( role.isPermanent() )
776         {
777             throw new RbacPermanentException( "Unable to delete permanent role [" + role.getName() + "]" );
778         }
779         rolesCache.remove( role.getName() );
780         if ( writableLdap )
781         {
782             LdapConnection ldapConnection = null;
783             DirContext context = null;
784             try
785             {
786                 ldapConnection = ldapConnectionFactory.getConnection();
787                 context = ldapConnection.getDirContext();
788                 ldapRoleMapper.removeRole( role.getName(), context );
789             }
790             catch ( MappingException e )
791             {
792                 throw new RbacManagerException( e.getMessage(), e );
793             }
794             catch ( LdapException e )
795             {
796                 throw new RbacManagerException( e.getMessage(), e );
797             }
798             fireRbacRoleRemoved( role );
799         }
800     }
801
802     public void removeRole( String roleName )
803         throws RbacManagerException
804     {
805         if ( roleName == null )
806         {
807             return;
808         }
809         removeRole( new RoleImpl( roleName ) );
810     }
811
812     public void removeUserAssignment( String username )
813         throws RbacManagerException
814     {
815         // TODO ldap cannot or isWritable ldap ?
816         userAssignmentsCache.remove( username );
817         this.rbacImpl.removeUserAssignment( username );
818     }
819
820     public void removeUserAssignment( UserAssignment userAssignment )
821         throws RbacManagerException
822     {
823         if ( userAssignment != null )
824         {
825             userAssignmentsCache.remove( userAssignment.getPrincipal() );
826         }
827         // TODO ldap cannot or isWritable ldap ?
828         this.rbacImpl.removeUserAssignment( userAssignment );
829     }
830
831     public boolean resourceExists( Resource resource )
832     {
833         return this.rbacImpl.resourceExists( resource );
834     }
835
836     public boolean resourceExists( String identifier )
837     {
838         return this.rbacImpl.resourceExists( identifier );
839     }
840
841     @Override
842     public boolean roleExists( Role role )
843         throws RbacManagerException
844     {
845         if ( role == null )
846         {
847             return false;
848         }
849         return roleExists( role.getName() );
850     }
851
852     @Override
853     public boolean roleExists( String name )
854         throws RbacManagerException
855     {
856         if ( StringUtils.isEmpty( name ) )
857         {
858             return false;
859         }
860         if ( rolesCache.get( name ) != null )
861         {
862             return true;
863         }
864         LdapConnection ldapConnection = null;
865         DirContext context = null;
866         try
867         {
868             ldapConnection = ldapConnectionFactory.getConnection();
869             context = ldapConnection.getDirContext();
870             if ( rolesCache.hasKey( name ) )
871             {
872                 return true;
873             }
874             return ldapRoleMapper.hasRole( context, name );
875         }
876         catch ( MappingException e )
877         {
878             throw new RbacManagerException( e.getMessage(), e );
879         }
880         catch ( LdapException e )
881         {
882             throw new RbacManagerException( e.getMessage(), e );
883         }
884         finally
885         {
886             closeContext( context );
887             closeLdapConnection( ldapConnection );
888         }
889     }
890
891     public Operation saveOperation( Operation operation )
892         throws RbacManagerException
893     {
894         return this.rbacImpl.saveOperation( operation );
895     }
896
897     public Permission savePermission( Permission permission )
898         throws RbacManagerException
899     {
900         return this.rbacImpl.savePermission( permission );
901     }
902
903     public Resource saveResource( Resource resource )
904         throws RbacManagerException
905     {
906         return this.rbacImpl.saveResource( resource );
907     }
908
909     public synchronized Role saveRole( Role role )
910         throws RbacManagerException
911     {
912         if ( writableLdap )
913         {
914             LdapConnection ldapConnection = null;
915             DirContext context = null;
916             try
917             {
918                 ldapConnection = ldapConnectionFactory.getConnection();
919                 context = ldapConnection.getDirContext();
920                 ldapRoleMapper.saveRole( role.getName(), context );
921
922                 if ( !role.getChildRoleNames().isEmpty() )
923                 {
924                     for ( String roleName : role.getChildRoleNames() )
925                     {
926                         ldapRoleMapper.saveRole( roleName, context );
927                     }
928                 }
929                 fireRbacRoleSaved( role );
930             }
931             catch ( MappingException e )
932             {
933                 throw new RbacManagerException( e.getMessage(), e );
934             }
935             catch ( LdapException e )
936             {
937                 throw new RbacManagerException( e.getMessage(), e );
938             }
939         }
940         role = this.rbacImpl.saveRole( role );
941         rolesCache.put( role.getName(), role );
942
943         return role;
944         //return new RoleImpl( role.getName(), role.getPermissions() );
945     }
946
947     public synchronized void saveRoles( Collection<Role> roles )
948         throws RbacManagerException
949     {
950         if ( writableLdap )
951         {
952             LdapConnection ldapConnection = null;
953             DirContext context = null;
954             try
955             {
956
957                 ldapConnection = ldapConnectionFactory.getConnection();
958                 context = ldapConnection.getDirContext();
959                 for ( Role role : roles )
960                 {
961                     ldapRoleMapper.saveRole( role.getName(), context );
962                     fireRbacRoleSaved( role );
963                 }
964             }
965             catch ( MappingException e )
966             {
967                 throw new RbacManagerException( e.getMessage(), e );
968             }
969             catch ( LdapException e )
970             {
971                 throw new RbacManagerException( e.getMessage(), e );
972             }
973         }
974         this.rbacImpl.saveRoles( roles );
975
976     }
977
978     public UserAssignment saveUserAssignment( UserAssignment userAssignment )
979         throws RbacManagerException
980     {
981         LdapConnection ldapConnection = null;
982         DirContext context = null;
983         try
984         {
985             if ( !userManager.userExists( userAssignment.getPrincipal() ) )
986             {
987                 User user = userManager.createUser( userAssignment.getPrincipal(), null, null );
988                 userManager.addUser( user );
989             }
990             ldapConnection = ldapConnectionFactory.getConnection();
991             context = ldapConnection.getDirContext();
992             List<String> allRoles = ldapRoleMapper.getAllRoles( context );
993
994             List<String> currentUserRoles =
995                 ldapRoleMapper.getRoles( userAssignment.getPrincipal(), context, getRealRoles() );
996
997             for ( String role : userAssignment.getRoleNames() )
998             {
999                 if ( !currentUserRoles.contains( role ) && writableLdap )
1000                 {
1001                     // role exists in ldap ?
1002                     if ( !allRoles.contains( role ) )
1003                     {
1004                         ldapRoleMapper.saveRole( role, context );
1005                         allRoles.add( role );
1006                     }
1007                     ldapRoleMapper.saveUserRole( role, userAssignment.getPrincipal(), context );
1008                     currentUserRoles.add( role );
1009                 }
1010             }
1011
1012             for ( String role : currentUserRoles )
1013             {
1014                 if ( !userAssignment.getRoleNames().contains( role ) && writableLdap )
1015                 {
1016                     ldapRoleMapper.removeUserRole( role, userAssignment.getPrincipal(), context );
1017                 }
1018             }
1019
1020             userAssignmentsCache.put( userAssignment.getPrincipal(), userAssignment );
1021             return userAssignment;
1022         }
1023         catch ( UserManagerException e )
1024         {
1025             throw new RbacManagerException( e.getMessage(), e );
1026         }
1027         catch ( MappingException e )
1028         {
1029             throw new RbacManagerException( e.getMessage(), e );
1030         }
1031         catch ( LdapException e )
1032         {
1033             throw new RbacManagerException( e.getMessage(), e );
1034         }
1035         finally
1036         {
1037             closeContext( context );
1038             closeLdapConnection( ldapConnection );
1039         }
1040     }
1041
1042     public boolean userAssignmentExists( String principal )
1043     {
1044         if ( userAssignmentsCache.hasKey( principal ) )
1045         {
1046             return true;
1047         }
1048         LdapConnection ldapConnection = null;
1049         DirContext context = null;
1050         try
1051         {
1052             ldapConnection = ldapConnectionFactory.getConnection();
1053             context = ldapConnection.getDirContext();
1054             List<String> roles = ldapRoleMapper.getRoles( principal, context, getRealRoles() );
1055             if ( roles == null || roles.isEmpty() )
1056             {
1057                 return false;
1058             }
1059             return true;
1060         }
1061         catch ( RbacManagerException e )
1062         {
1063             log.warn( "fail to call userAssignmentExists: {}", e.getMessage() );
1064         }
1065         catch ( LdapException e )
1066         {
1067             log.warn( "fail to call userAssignmentExists: {}", e.getMessage() );
1068         }
1069         catch ( MappingException e )
1070         {
1071             log.warn( "fail to call userAssignmentExists: {}", e.getMessage() );
1072         }
1073         finally
1074         {
1075             closeContext( context );
1076             closeLdapConnection( ldapConnection );
1077         }
1078         return false;
1079     }
1080
1081     public boolean userAssignmentExists( UserAssignment assignment )
1082     {
1083         if ( assignment == null )
1084         {
1085             return false;
1086         }
1087         return this.userAssignmentExists( assignment.getPrincipal() );
1088     }
1089
1090     public RBACManager getRbacImpl()
1091     {
1092         return rbacImpl;
1093     }
1094
1095     public void setRbacImpl( RBACManager rbacImpl )
1096     {
1097         this.rbacImpl = rbacImpl;
1098     }
1099
1100     public boolean isWritableLdap()
1101     {
1102         return writableLdap;
1103     }
1104
1105     public void setWritableLdap( boolean writableLdap )
1106     {
1107         this.writableLdap = writableLdap;
1108     }
1109
1110     public LdapRoleMapper getLdapRoleMapper()
1111     {
1112         return ldapRoleMapper;
1113     }
1114
1115     public void setLdapRoleMapper( LdapRoleMapper ldapRoleMapper )
1116     {
1117         this.ldapRoleMapper = ldapRoleMapper;
1118     }
1119
1120     private static class RoleImpl
1121         extends AbstractRole
1122     {
1123         private String name;
1124
1125         private String description;
1126
1127         private List<Permission> permissions = new ArrayList<Permission>();
1128
1129         private List<String> childRoleNames = new ArrayList<String>();
1130
1131         private RoleImpl( String name )
1132         {
1133             this.name = name;
1134         }
1135
1136         private RoleImpl( String name, List<Permission> permissions )
1137         {
1138             this.name = name;
1139             this.permissions = permissions;
1140         }
1141
1142         public void addPermission( Permission permission )
1143         {
1144             this.permissions.add( permission );
1145         }
1146
1147         public void addChildRoleName( String name )
1148         {
1149             this.childRoleNames.add( name );
1150         }
1151
1152         public List<String> getChildRoleNames()
1153         {
1154             return this.childRoleNames;
1155         }
1156
1157         public String getDescription()
1158         {
1159             return this.description;
1160         }
1161
1162         public String getName()
1163         {
1164             return this.name;
1165         }
1166
1167         public List<Permission> getPermissions()
1168         {
1169             return this.permissions;
1170         }
1171
1172         public boolean isAssignable()
1173         {
1174             return true;
1175         }
1176
1177         public void removePermission( Permission permission )
1178         {
1179             this.permissions.remove( permission );
1180         }
1181
1182         public void setAssignable( boolean assignable )
1183         {
1184             // no op
1185         }
1186
1187         public void setChildRoleNames( List<String> names )
1188         {
1189             this.childRoleNames = names;
1190         }
1191
1192         public void setDescription( String description )
1193         {
1194             this.description = description;
1195         }
1196
1197         public void setName( String name )
1198         {
1199             this.name = name;
1200         }
1201
1202         public void setPermissions( List<Permission> permissions )
1203         {
1204             this.permissions = permissions;
1205         }
1206
1207         public boolean isPermanent()
1208         {
1209             return true;
1210         }
1211
1212         public void setPermanent( boolean permanent )
1213         {
1214             // no op
1215         }
1216
1217         @Override
1218         public String toString()
1219         {
1220             final StringBuilder sb = new StringBuilder();
1221             sb.append( "RoleImpl" );
1222             sb.append( "{name='" ).append( name ).append( '\'' );
1223             sb.append( '}' );
1224             return sb.toString();
1225         }
1226
1227         @Override
1228         public boolean equals( Object o )
1229         {
1230             if ( this == o )
1231             {
1232                 return true;
1233             }
1234             if ( o == null || getClass() != o.getClass() )
1235             {
1236                 return false;
1237             }
1238
1239             RoleImpl role = (RoleImpl) o;
1240
1241             if ( name != null ? !name.equals( role.name ) : role.name != null )
1242             {
1243                 return false;
1244             }
1245
1246             return true;
1247         }
1248
1249         @Override
1250         public int hashCode()
1251         {
1252             return name != null ? name.hashCode() : 0;
1253         }
1254     }
1255
1256     private static class UserAssignmentImpl
1257         implements UserAssignment
1258     {
1259         private String username;
1260
1261         private List<String> roleNames;
1262
1263         private boolean permanent;
1264
1265         private UserAssignmentImpl( String username, Collection<String> roleNames )
1266         {
1267             this.username = username;
1268
1269             if ( roleNames == null )
1270             {
1271                 this.roleNames = new ArrayList<String>();
1272             }
1273             else
1274             {
1275                 this.roleNames = new ArrayList<String>( roleNames );
1276             }
1277         }
1278
1279         public String getPrincipal()
1280         {
1281             return this.username;
1282         }
1283
1284         public List<String> getRoleNames()
1285         {
1286             return this.roleNames;
1287         }
1288
1289         public void addRoleName( Role role )
1290         {
1291             if ( role == null )
1292             {
1293                 return;
1294             }
1295             this.roleNames.add( role.getName() );
1296         }
1297
1298         public void addRoleName( String roleName )
1299         {
1300             if ( roleName == null )
1301             {
1302                 return;
1303             }
1304             this.roleNames.add( roleName );
1305         }
1306
1307         public void removeRoleName( Role role )
1308         {
1309             if ( role == null )
1310             {
1311                 return;
1312             }
1313             this.roleNames.remove( role.getName() );
1314         }
1315
1316         public void removeRoleName( String roleName )
1317         {
1318             if ( roleName == null )
1319             {
1320                 return;
1321             }
1322             this.roleNames.remove( roleName );
1323         }
1324
1325         public void setPrincipal( String principal )
1326         {
1327             this.username = principal;
1328         }
1329
1330         public void setRoleNames( List<String> roles )
1331         {
1332             this.roleNames = roles;
1333         }
1334
1335         public boolean isPermanent()
1336         {
1337             return this.permanent;
1338         }
1339
1340         public void setPermanent( boolean permanent )
1341         {
1342             this.permanent = permanent;
1343         }
1344
1345         @Override
1346         public String toString()
1347         {
1348             final StringBuilder sb = new StringBuilder();
1349             sb.append( "UserAssignmentImpl" );
1350             sb.append( "{username='" ).append( username ).append( '\'' );
1351             sb.append( ", roleNames=" ).append( roleNames );
1352             sb.append( ", permanent=" ).append( permanent );
1353             sb.append( '}' );
1354             return sb.toString();
1355         }
1356     }
1357 }