1 package org.apache.archiva.redback.rbac.ldap;
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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
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;
56 import javax.annotation.PostConstruct;
57 import javax.inject.Inject;
58 import javax.inject.Named;
59 import java.util.ArrayList;
60 import java.util.Collection;
61 import java.util.Collections;
62 import java.util.List;
67 * LdapRbacManager will read datas from ldap for mapping groups to role.
68 * Write operations will delegate to cached implementation.
70 * @author Olivier Lamy
72 @Service( "rbacManager#ldap" )
73 public class LdapRbacManager
74 extends AbstractRBACManager
75 implements RBACManager, RBACManagerListener
78 private Logger log = LoggerFactory.getLogger( getClass() );
81 @Named( value = "rbacManager#cached" )
82 private RBACManager rbacImpl;
85 @Named( value = "ldapRoleMapper#default" )
86 private LdapRoleMapper ldapRoleMapper;
89 @Named( value = "userConfiguration#default" )
90 private UserConfiguration userConf;
93 @Named( value = "userManager#ldap" )
94 private UserManager userManager;
97 private LdapConnectionFactory ldapConnectionFactory;
100 private LdapController ldapController;
102 private boolean writableLdap = false;
105 public void initialize()
107 this.writableLdap = userConf.getBoolean( UserConfigurationKeys.LDAP_WRITABLE, this.writableLdap );
111 public void addChildRole( Role role, Role childRole )
112 throws RbacObjectInvalidException, RbacManagerException
114 this.rbacImpl.addChildRole( role, childRole );
117 public void addListener( RBACManagerListener listener )
119 super.addListener( listener );
120 this.rbacImpl.addListener( listener );
123 public Operation createOperation( String name )
124 throws RbacManagerException
126 return this.rbacImpl.createOperation( name );
129 public Permission createPermission( String name )
130 throws RbacManagerException
132 return this.rbacImpl.createPermission( name );
135 public Permission createPermission( String name, String operationName, String resourceIdentifier )
136 throws RbacManagerException
138 return this.rbacImpl.createPermission( name, operationName, resourceIdentifier );
141 public Resource createResource( String identifier )
142 throws RbacManagerException
144 return this.rbacImpl.createResource( identifier );
147 public Role createRole( String name )
149 return this.rbacImpl.createRole( name );
152 public UserAssignment createUserAssignment( String username )
153 throws RbacManagerException
155 // TODO ldap cannot or isWritable ldap ?
156 return this.rbacImpl.createUserAssignment( username );
159 public void eraseDatabase()
165 ldapRoleMapper.removeAllRoles();
167 catch ( MappingException e )
169 log.warn( "skip error removing all roles {}", e.getMessage() );
172 this.rbacImpl.eraseDatabase();
176 * @see org.apache.archiva.redback.rbac.RBACManager#getAllAssignableRoles()
178 public List<Role> getAllAssignableRoles()
179 throws RbacManagerException
183 Collection<String> roleNames = ldapRoleMapper.getLdapGroupMappings().values();
185 List<Role> roles = new ArrayList<Role>();
187 for ( String name : roleNames )
189 roles.add( new RoleImpl( name ) );
194 catch ( MappingException e )
196 throw new RbacManagerException( e.getMessage(), e );
200 public List<Operation> getAllOperations()
201 throws RbacManagerException
203 return this.rbacImpl.getAllOperations();
206 public List<Permission> getAllPermissions()
207 throws RbacManagerException
209 return this.rbacImpl.getAllPermissions();
212 public List<Resource> getAllResources()
213 throws RbacManagerException
215 return this.rbacImpl.getAllResources();
218 public List<Role> getAllRoles()
219 throws RbacManagerException
223 List<String> groups = ldapRoleMapper.getAllGroups();
224 return mapToRoles( groups );
226 catch ( MappingException e )
228 throw new RbacManagerException( e.getMessage(), e );
230 //return this.rbacImpl.getAllRoles();
233 public List<UserAssignment> getAllUserAssignments()
234 throws RbacManagerException
236 // TODO FROM ldap or from real impl ?
237 //return this.rbacImpl.getAllUserAssignments();
238 LdapConnection ldapConnection = null;
241 ldapConnection = ldapConnectionFactory.getConnection();
242 Map<String, Collection<String>> usersWithRoles =
243 ldapController.findUsersWithRoles( ldapConnection.getDirContext() );
244 List<UserAssignment> userAssignments = new ArrayList<UserAssignment>( usersWithRoles.size() );
246 for ( Map.Entry<String, Collection<String>> entry : usersWithRoles.entrySet() )
248 UserAssignment userAssignment = new UserAssignmentImpl( entry.getKey(), entry.getValue() );
249 userAssignments.add( userAssignment );
252 return userAssignments;
254 catch ( LdapControllerException e )
256 throw new RbacManagerException( e.getMessage(), e );
258 catch ( LdapException e )
260 throw new RbacManagerException( e.getMessage(), e );
264 if ( ldapConnection != null )
266 ldapConnection.close();
272 * public Map<String, List<Permission>> getAssignedPermissionMap( String username )
273 * throws RbacManagerException
275 * return this.rbacImpl.getAssignedPermissionMap( username );
279 /*public Set<Permission> getAssignedPermissions( String username )
280 throws RbacObjectNotFoundException, RbacManagerException
283 return this.rbacImpl.getAssignedPermissions( username );
285 private List<Role> mapToRoles( List<String> groups )
286 throws MappingException, RbacManagerException
288 if ( groups == null || groups.isEmpty() )
290 return Collections.emptyList();
293 List<Role> roles = new ArrayList<Role>( groups.size() );
294 Map<String, String> mappedGroups = ldapRoleMapper.getLdapGroupMappings();
295 for ( String group : groups )
297 String roleName = mappedGroups.get( group );
298 if ( roleName != null )
300 Role role = getRole( roleName );
311 public Collection<Role> getAssignedRoles( String username )
312 throws RbacManagerException
317 List<String> roleNames = ldapRoleMapper.getRoles( username );
319 if ( roleNames.isEmpty() )
321 return Collections.emptyList();
324 List<Role> roles = new ArrayList<Role>( roleNames.size() );
326 for ( String name : roleNames )
328 roles.add( this.rbacImpl.getRole( name ) );// new RoleImpl( name ) );
333 catch ( MappingException e )
335 throw new RbacManagerException( e.getMessage(), e );
339 public Collection<Role> getAssignedRoles( UserAssignment userAssignment )
340 throws RbacManagerException
342 return getAssignedRoles( userAssignment.getPrincipal() );
345 public Map<String, Role> getChildRoles( Role role )
346 throws RbacManagerException
348 return this.rbacImpl.getChildRoles( role );
351 public Map<String, Role> getParentRoles( Role role )
352 throws RbacManagerException
354 return this.rbacImpl.getParentRoles( role );
358 public Collection<Role> getEffectivelyAssignedRoles( String username )
359 throws RbacManagerException
362 return this.rbacImpl.getEffectivelyAssignedRoles( username );
366 public Collection<Role> getEffectivelyUnassignedRoles( String username )
367 throws RbacManagerException
370 return this.rbacImpl.getEffectivelyUnassignedRoles( username );
373 public Set<Role> getEffectiveRoles( Role role )
374 throws RbacManagerException
376 return this.rbacImpl.getEffectiveRoles( role );
379 public Resource getGlobalResource()
380 throws RbacManagerException
382 return this.rbacImpl.getGlobalResource();
385 public Operation getOperation( String operationName )
386 throws RbacManagerException
388 return this.rbacImpl.getOperation( operationName );
391 public Permission getPermission( String permissionName )
392 throws RbacManagerException
394 return this.rbacImpl.getPermission( permissionName );
397 public Resource getResource( String resourceIdentifier )
398 throws RbacManagerException
400 return this.rbacImpl.getResource( resourceIdentifier );
403 public Role getRole( String roleName )
404 throws RbacManagerException
406 //verify it's a ldap group
409 if ( !ldapRoleMapper.getAllRoles().contains( roleName ) )
414 catch ( MappingException e )
416 throw new RbacManagerException( e.getMessage(), e );
418 return this.rbacImpl.getRole( roleName );
421 public Map<String, Role> getRoles( Collection<String> roleNames )
422 throws RbacManagerException
424 return this.rbacImpl.getRoles( roleNames );
427 public Collection<Role> getUnassignedRoles( String username )
428 throws RbacManagerException
432 List<String> allRoles = ldapRoleMapper.getAllRoles();
433 final List<String> userRoles = ldapRoleMapper.getRoles( username );
435 List<Role> unassignedRoles = new ArrayList<Role>();
437 for ( String roleName : allRoles )
439 if ( !userRoles.contains( roleName ) )
441 unassignedRoles.add( rbacImpl.getRole( roleName ) );
444 return unassignedRoles;
446 catch ( MappingException e )
448 throw new RbacManagerException( e.getMessage(), e );
452 public UserAssignment getUserAssignment( String username )
453 throws RbacManagerException
457 List<String> roles = ldapRoleMapper.getRoles( username );
459 return new UserAssignmentImpl( username, roles );
461 catch ( MappingException e )
463 throw new RbacManagerException( e.getMessage(), e );
466 //return this.rbacImpl.getUserAssignment( username );
469 public List<UserAssignment> getUserAssignmentsForRoles( Collection<String> roleNames )
470 throws RbacManagerException
473 return this.rbacImpl.getUserAssignmentsForRoles( roleNames );
476 public boolean operationExists( Operation operation )
478 return this.rbacImpl.operationExists( operation );
481 public boolean operationExists( String name )
483 return this.rbacImpl.operationExists( name );
486 public boolean permissionExists( Permission permission )
488 return this.rbacImpl.permissionExists( permission );
491 public boolean permissionExists( String name )
493 return this.rbacImpl.permissionExists( name );
496 public void rbacInit( boolean freshdb )
498 if ( rbacImpl instanceof RBACManagerListener )
500 ( (RBACManagerListener) this.rbacImpl ).rbacInit( freshdb );
504 public void rbacPermissionRemoved( Permission permission )
506 if ( rbacImpl instanceof RBACManagerListener )
508 ( (RBACManagerListener) this.rbacImpl ).rbacPermissionRemoved( permission );
513 public void rbacPermissionSaved( Permission permission )
515 if ( rbacImpl instanceof RBACManagerListener )
517 ( (RBACManagerListener) this.rbacImpl ).rbacPermissionSaved( permission );
522 public void rbacRoleRemoved( Role role )
524 if ( rbacImpl instanceof RBACManagerListener )
526 ( (RBACManagerListener) this.rbacImpl ).rbacRoleRemoved( role );
531 public void rbacRoleSaved( Role role )
533 if ( rbacImpl instanceof RBACManagerListener )
535 ( (RBACManagerListener) this.rbacImpl ).rbacRoleSaved( role );
540 public void rbacUserAssignmentRemoved( UserAssignment userAssignment )
542 if ( rbacImpl instanceof RBACManagerListener )
544 ( (RBACManagerListener) this.rbacImpl ).rbacUserAssignmentRemoved( userAssignment );
549 public void rbacUserAssignmentSaved( UserAssignment userAssignment )
551 if ( rbacImpl instanceof RBACManagerListener )
553 ( (RBACManagerListener) this.rbacImpl ).rbacUserAssignmentSaved( userAssignment );
558 public void removeListener( RBACManagerListener listener )
560 this.rbacImpl.removeListener( listener );
563 public void removeOperation( Operation operation )
564 throws RbacManagerException
566 this.rbacImpl.removeOperation( operation );
569 public void removeOperation( String operationName )
570 throws RbacManagerException
572 this.rbacImpl.removeOperation( operationName );
575 public void removePermission( Permission permission )
576 throws RbacManagerException
578 this.rbacImpl.removePermission( permission );
581 public void removePermission( String permissionName )
582 throws RbacManagerException
584 this.rbacImpl.removePermission( permissionName );
587 public void removeResource( Resource resource )
588 throws RbacManagerException
590 this.rbacImpl.removeResource( resource );
593 public void removeResource( String resourceIdentifier )
594 throws RbacManagerException
596 this.rbacImpl.removeResource( resourceIdentifier );
599 public void removeRole( Role role )
600 throws RbacManagerException
602 RBACObjectAssertions.assertValid( role );
604 if ( role.isPermanent() )
606 throw new RbacPermanentException( "Unable to delete permanent role [" + role.getName() + "]" );
612 ldapRoleMapper.removeRole( role.getName() );
614 catch ( MappingException e )
616 throw new RbacManagerException( e.getMessage(), e );
618 fireRbacRoleRemoved( role );
622 public void removeRole( String roleName )
623 throws RbacManagerException
625 if ( roleName == null )
629 removeRole( new RoleImpl( roleName ) );
632 public void removeUserAssignment( String username )
633 throws RbacManagerException
635 // TODO ldap cannot or isWritable ldap ?
636 this.rbacImpl.removeUserAssignment( username );
639 public void removeUserAssignment( UserAssignment userAssignment )
640 throws RbacManagerException
642 // TODO ldap cannot or isWritable ldap ?
643 this.rbacImpl.removeUserAssignment( userAssignment );
646 public boolean resourceExists( Resource resource )
648 return this.rbacImpl.resourceExists( resource );
651 public boolean resourceExists( String identifier )
653 return this.rbacImpl.resourceExists( identifier );
657 public boolean roleExists( Role role )
658 throws RbacManagerException
664 return roleExists( role.getName() );
667 public boolean roleExists( String name )
668 throws RbacManagerException
670 if ( StringUtils.isEmpty( name ) )
676 return ldapRoleMapper.getAllRoles().contains( name );
678 catch ( Exception e )
680 throw new RbacManagerException( e.getMessage(), e );
684 public Operation saveOperation( Operation operation )
685 throws RbacManagerException
687 return this.rbacImpl.saveOperation( operation );
690 public Permission savePermission( Permission permission )
691 throws RbacManagerException
693 return this.rbacImpl.savePermission( permission );
696 public Resource saveResource( Resource resource )
697 throws RbacManagerException
699 return this.rbacImpl.saveResource( resource );
702 public synchronized Role saveRole( Role role )
703 throws RbacManagerException
709 ldapRoleMapper.saveRole( role.getName() );
710 if ( !role.getChildRoleNames().isEmpty() )
712 for ( String roleName : role.getChildRoleNames() )
714 ldapRoleMapper.saveRole( roleName );
717 fireRbacRoleSaved( role );
719 catch ( MappingException e )
721 throw new RbacManagerException( e.getMessage(), e );
724 return this.rbacImpl.saveRole( role );
725 //return new RoleImpl( role.getName(), role.getPermissions() );
728 public synchronized void saveRoles( Collection<Role> roles )
729 throws RbacManagerException
735 for ( Role role : roles )
737 ldapRoleMapper.saveRole( role.getName() );
738 fireRbacRoleSaved( role );
741 catch ( MappingException e )
743 throw new RbacManagerException( e.getMessage(), e );
746 this.rbacImpl.saveRoles( roles );
750 public UserAssignment saveUserAssignment( UserAssignment userAssignment )
751 throws RbacManagerException
756 if ( !userManager.userExists( userAssignment.getPrincipal() ) )
758 User user = userManager.createUser( userAssignment.getPrincipal(), null, null );
759 userManager.addUser( user );
762 List<String> allRoles = ldapRoleMapper.getAllRoles();
764 List<String> currentUserRoles = ldapRoleMapper.getRoles( userAssignment.getPrincipal() );
766 for ( String role : userAssignment.getRoleNames() )
768 if ( !currentUserRoles.contains( role ) && writableLdap )
770 // role exists in ldap ?
771 if ( !allRoles.contains( role ) )
773 ldapRoleMapper.saveRole( role );
774 allRoles.add( role );
776 ldapRoleMapper.saveUserRole( role, userAssignment.getPrincipal() );
777 currentUserRoles.add( role );
781 for ( String role : currentUserRoles )
783 if ( !userAssignment.getRoleNames().contains( role ) && writableLdap )
785 ldapRoleMapper.removeUserRole( role, userAssignment.getPrincipal() );
789 return userAssignment;
791 catch ( UserManagerException e )
793 throw new RbacManagerException( e.getMessage(), e );
795 catch ( MappingException e )
797 throw new RbacManagerException( e.getMessage(), e );
800 //this.rbacImpl.saveUserAssignment( userAssignment );
802 //return userAssignment;
805 public boolean userAssignmentExists( String principal )
808 return this.rbacImpl.userAssignmentExists( principal );
811 public boolean userAssignmentExists( UserAssignment assignment )
814 return this.rbacImpl.userAssignmentExists( assignment );
817 public RBACManager getRbacImpl()
822 public void setRbacImpl( RBACManager rbacImpl )
824 this.rbacImpl = rbacImpl;
827 public boolean isWritableLdap()
832 public void setWritableLdap( boolean writableLdap )
834 this.writableLdap = writableLdap;
837 public LdapRoleMapper getLdapRoleMapper()
839 return ldapRoleMapper;
842 public void setLdapRoleMapper( LdapRoleMapper ldapRoleMapper )
844 this.ldapRoleMapper = ldapRoleMapper;
847 private static class RoleImpl
852 private String description;
854 private List<Permission> permissions = new ArrayList<Permission>();
856 private List<String> childRoleNames = new ArrayList<String>();
858 private RoleImpl( String name )
863 private RoleImpl( String name, List<Permission> permissions )
866 this.permissions = permissions;
869 public void addPermission( Permission permission )
871 this.permissions.add( permission );
874 public void addChildRoleName( String name )
876 this.childRoleNames.add( name );
879 public List<String> getChildRoleNames()
881 return this.childRoleNames;
884 public String getDescription()
886 return this.description;
889 public String getName()
894 public List<Permission> getPermissions()
896 return this.permissions;
899 public boolean isAssignable()
904 public void removePermission( Permission permission )
906 this.permissions.remove( permission );
909 public void setAssignable( boolean assignable )
914 public void setChildRoleNames( List<String> names )
916 this.childRoleNames = names;
919 public void setDescription( String description )
921 this.description = description;
924 public void setName( String name )
929 public void setPermissions( List<Permission> permissions )
931 this.permissions = permissions;
934 public boolean isPermanent()
939 public void setPermanent( boolean permanent )
945 public String toString()
947 final StringBuilder sb = new StringBuilder();
948 sb.append( "RoleImpl" );
949 sb.append( "{name='" ).append( name ).append( '\'' );
951 return sb.toString();
955 public boolean equals( Object o )
961 if ( o == null || getClass() != o.getClass() )
966 RoleImpl role = (RoleImpl) o;
968 if ( name != null ? !name.equals( role.name ) : role.name != null )
977 public int hashCode()
979 return name != null ? name.hashCode() : 0;
983 private static class UserAssignmentImpl
984 implements UserAssignment
986 private String username;
988 private List<String> roleNames;
990 private boolean permanent;
992 private UserAssignmentImpl( String username, Collection<String> roleNames )
994 this.username = username;
996 if ( roleNames == null )
998 this.roleNames = new ArrayList<String>();
1002 this.roleNames = new ArrayList<String>( roleNames );
1006 public String getPrincipal()
1008 return this.username;
1011 public List<String> getRoleNames()
1013 return this.roleNames;
1016 public void addRoleName( Role role )
1022 this.roleNames.add( role.getName() );
1025 public void addRoleName( String roleName )
1027 if ( roleName == null )
1031 this.roleNames.add( roleName );
1034 public void removeRoleName( Role role )
1040 this.roleNames.remove( role.getName() );
1043 public void removeRoleName( String roleName )
1045 if ( roleName == null )
1049 this.roleNames.remove( roleName );
1052 public void setPrincipal( String principal )
1054 this.username = principal;
1057 public void setRoleNames( List<String> roles )
1059 this.roleNames = roles;
1062 public boolean isPermanent()
1064 return this.permanent;
1067 public void setPermanent( boolean permanent )
1069 this.permanent = permanent;
1073 public String toString()
1075 final StringBuilder sb = new StringBuilder();
1076 sb.append( "UserAssignmentImpl" );
1077 sb.append( "{username='" ).append( username ).append( '\'' );
1078 sb.append( ", roleNames=" ).append( roleNames );
1079 sb.append( ", permanent=" ).append( permanent );
1081 return sb.toString();