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