fix some unit test for Ldap rbacmanager impl

git-svn-id: https://svn.apache.org/repos/asf/archiva/redback/redback-core/trunk@1433396 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Olivier Lamy 2013-01-15 13:22:03 +00:00
parent 56f7b83925
commit 030ecf0664
16 changed files with 799 additions and 59 deletions

View File

@ -654,7 +654,6 @@
<groupId>org.easytesting</groupId>
<artifactId>fest-assert</artifactId>
<version>1.4</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -40,9 +40,11 @@ import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -165,6 +167,33 @@ public class DefaultLdapRoleMapper
}
}
public List<String> getAllRoles()
throws MappingException
{
// TODO read from ldap ?
List<String> groups = getAllGroups();
if ( groups.isEmpty() )
{
return Collections.emptyList();
}
List<String> roles = new ArrayList<String>( groups.size() );
Map<String, String> mapping = getLdapGroupMappings();
for ( String group : groups )
{
String role = mapping.get( group );
if ( role != null )
{
roles.add( role );
}
}
return roles;
}
public List<String> getGroupsMember( String group )
throws MappingException
{
@ -405,7 +434,7 @@ public class DefaultLdapRoleMapper
String groupName = HashBiMap.create( getLdapGroupMappings() ).inverse().get( roleName );
if ( groupName == null )
{
log.warn( "skip group creation as no mapping fro roleName:'{}", roleName );
log.warn( "skip group creation as no mapping fro roleName:'{}'", roleName );
return false;
}
@ -426,9 +455,7 @@ public class DefaultLdapRoleMapper
// attribute mandatory when created a group so add admin as default member
// TODO make this default configurable
BasicAttribute basicAttribute = new BasicAttribute( "uniquemember" );
//
basicAttribute.add( "uid=admin," + getBaseDn() );
attributes.put( basicAttribute );
LdapConnection ldapConnection = null;
@ -443,7 +470,7 @@ public class DefaultLdapRoleMapper
context.createSubcontext( dn, attributes );
log.debug( "created group with dn:'{}", dn );
log.info( "created group with dn:'{}", dn );
return true;
}
@ -465,6 +492,89 @@ public class DefaultLdapRoleMapper
}
}
public boolean saveUserRole( String roleName, String username )
throws MappingException
{
String groupName = HashBiMap.create( getLdapGroupMappings() ).inverse().get( roleName );
if ( groupName == null )
{
log.warn( "no group found for role '{}", roleName );
return false;
}
LdapConnection ldapConnection = null;
NamingEnumeration<SearchResult> namingEnumeration = null;
try
{
ldapConnection = ldapConnectionFactory.getConnection();
DirContext context = ldapConnection.getDirContext();
SearchControls searchControls = new SearchControls();
searchControls.setDerefLinkFlag( true );
searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
String filter = "objectClass=" + getLdapGroupClass();
namingEnumeration = context.search( "cn=" + groupName + "," + getGroupsDn(), filter, searchControls );
while ( namingEnumeration.hasMore() )
{
SearchResult searchResult = namingEnumeration.next();
Attribute attribute = searchResult.getAttributes().get( "uniquemember" );
if ( attribute == null )
{
BasicAttribute basicAttribute = new BasicAttribute( "uniquemember" );
basicAttribute.add( "uid=" + username + "," + getGroupsDn() );
context.modifyAttributes( "cn=" + groupName + "," + getGroupsDn(), new ModificationItem[]{
new ModificationItem( DirContext.ADD_ATTRIBUTE, basicAttribute ) } );
}
else
{
attribute.add( "uid=" + username + "," + getGroupsDn() );
context.modifyAttributes( "cn=" + groupName + "," + getGroupsDn(), new ModificationItem[]{
new ModificationItem( DirContext.REPLACE_ATTRIBUTE, attribute ) } );
}
return true;
}
return false;
}
catch ( LdapException e )
{
throw new MappingException( e.getMessage(), e );
}
catch ( NamingException e )
{
throw new MappingException( e.getMessage(), e );
}
finally
{
if ( ldapConnection != null )
{
ldapConnection.close();
}
if ( namingEnumeration != null )
{
try
{
namingEnumeration.close();
}
catch ( NamingException e )
{
log.warn( "failed to close search results", e );
}
}
}
}
public void removeAllRoles()
throws MappingException
{
@ -524,7 +634,7 @@ public class DefaultLdapRoleMapper
context.unbind( dn );
log.debug( "deleted group with dn:'{}", dn );
log.info( "deleted group with dn:'{}", dn );
}
catch ( LdapException e )

View File

@ -43,11 +43,22 @@ public interface LdapRoleMapper
/**
* read all groups from ldap
*
* @return all LDAP groups
*/
List<String> getAllGroups()
throws MappingException;
/**
* read all ldap groups then map to corresponding role (if no mapping found group is ignored)
*
* @return all roles
* @throws Exception
*/
List<String> getAllRoles()
throws MappingException;
/**
* @return the base dn which contains all ldap groups
@ -110,6 +121,17 @@ public interface LdapRoleMapper
boolean saveRole( String roleName )
throws MappingException;
/**
* associate role to user in ldap
*
* @param roleName
* @param username
* @return <code>true</code> if role was added to user, <code>false</code> if role already exists for the user
* @throws MappingException
*/
boolean saveUserRole( String roleName, String username )
throws MappingException;
void removeAllRoles()
throws MappingException;

View File

@ -82,6 +82,8 @@ public interface UserConfigurationKeys
String LDAP_GROUPS_ROLE_START_KEY = "ldap.config.groups.role.";
String LDAP_WRITABLE = "ldap.config.writable";
String APPLICATION_URL = "application.url";
String EMAIL_URL_PATH = "email.url.path";

View File

@ -29,7 +29,6 @@ import java.util.Set;
*
* @author Jesse McConnell <jmcconnell@apache.org>
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
*
* @todo expand on javadoc
*/
public interface RBACManager
@ -60,9 +59,11 @@ public interface RBACManager
* @return true if role exists in store.
* @throws RbacManagerException
*/
boolean roleExists( String name );
boolean roleExists( String name )
throws RbacManagerException;
boolean roleExists( Role role );
boolean roleExists( Role role )
throws RbacManagerException;
Role saveRole( Role role )
throws RbacObjectInvalidException, RbacManagerException;

View File

@ -46,7 +46,7 @@ import java.util.Set;
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
*/
@Service("rbacManager#cached")
@Service( "rbacManager#cached" )
public class CachedRbacManager
implements RBACManager, RBACManagerListener
{
@ -54,35 +54,35 @@ public class CachedRbacManager
private Logger log = LoggerFactory.getLogger( getClass() );
@Inject
@Named(value = "rbacManager#jdo")
@Named( value = "rbacManager#jdo" )
private RBACManager rbacImpl;
@Inject
@Named(value = "cache#operations")
@Named( value = "cache#operations" )
private Cache<String, Operation> operationsCache;
@Inject
@Named(value = "cache#permissions")
@Named( value = "cache#permissions" )
private Cache<String, Permission> permissionsCache;
@Inject
@Named(value = "cache#resources")
@Named( value = "cache#resources" )
private Cache<String, Resource> resourcesCache;
@Inject
@Named(value = "cache#roles")
@Named( value = "cache#roles" )
private Cache<String, Role> rolesCache;
@Inject
@Named(value = "cache#userAssignments")
@Named( value = "cache#userAssignments" )
private Cache<String, UserAssignment> userAssignmentsCache;
@Inject
@Named(value = "cache#userPermissions")
@Named( value = "cache#userPermissions" )
private Cache<String, Map<String, List<Permission>>> userPermissionsCache;
@Inject
@Named(value = "cache#effectiveRoleSet")
@Named( value = "cache#effectiveRoleSet" )
private Cache<String, Set<Role>> effectiveRoleSetCache;
public void addChildRole( Role role, Role childRole )
@ -206,7 +206,7 @@ public class CachedRbacManager
/**
* @see org.apache.archiva.redback.rbac.RBACManager#getAssignedPermissionMap(java.lang.String)
*/
@SuppressWarnings("unchecked")
@SuppressWarnings( "unchecked" )
public Map<String, List<Permission>> getAssignedPermissionMap( String principal )
throws RbacObjectNotFoundException, RbacManagerException
{
@ -274,7 +274,7 @@ public class CachedRbacManager
return this.rbacImpl.getEffectivelyUnassignedRoles( principal );
}
@SuppressWarnings("unchecked")
@SuppressWarnings( "unchecked" )
public Set<Role> getEffectiveRoles( Role role )
throws RbacObjectNotFoundException, RbacManagerException
{
@ -624,6 +624,7 @@ public class CachedRbacManager
}
public boolean roleExists( Role role )
throws RbacManagerException
{
if ( rolesCache.hasKey( role.getName() ) )
{
@ -634,6 +635,7 @@ public class CachedRbacManager
}
public boolean roleExists( String name )
throws RbacManagerException
{
if ( rolesCache.hasKey( name ) )
{

View File

@ -68,6 +68,10 @@
<groupId>org.apache.archiva.redback</groupId>
<artifactId>redback-common-ldap</artifactId>
</dependency>
<dependency>
<groupId>org.apache.archiva.redback</groupId>
<artifactId>redback-users-ldap</artifactId>
</dependency>
<dependency>
<groupId>org.apache.archiva.redback</groupId>
<artifactId>redback-rbac-jdo</artifactId>

View File

@ -20,8 +20,14 @@ package org.apache.archiva.redback.rbac.ldap;
*/
import org.apache.archiva.redback.common.ldap.MappingException;
import org.apache.archiva.redback.common.ldap.connection.LdapConnection;
import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory;
import org.apache.archiva.redback.common.ldap.connection.LdapException;
import org.apache.archiva.redback.common.ldap.role.LdapRoleMapper;
import org.apache.archiva.redback.components.cache.Cache;
import org.apache.archiva.redback.configuration.UserConfiguration;
import org.apache.archiva.redback.configuration.UserConfigurationKeys;
import org.apache.archiva.redback.rbac.AbstractRole;
import org.apache.archiva.redback.rbac.Operation;
import org.apache.archiva.redback.rbac.Permission;
import org.apache.archiva.redback.rbac.RBACManager;
@ -32,10 +38,17 @@ import org.apache.archiva.redback.rbac.RbacObjectNotFoundException;
import org.apache.archiva.redback.rbac.Resource;
import org.apache.archiva.redback.rbac.Role;
import org.apache.archiva.redback.rbac.UserAssignment;
import org.apache.archiva.redback.users.User;
import org.apache.archiva.redback.users.UserManager;
import org.apache.archiva.redback.users.UserManagerException;
import org.apache.archiva.redback.users.ldap.ctl.LdapController;
import org.apache.archiva.redback.users.ldap.ctl.LdapControllerException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.ArrayList;
@ -66,11 +79,28 @@ public class LdapRbacManager
@Named( value = "ldapRoleMapper#default" )
private LdapRoleMapper ldapRoleMapper;
/**
* limited to role / group write
*/
@Inject
@Named( value = "userConfiguration#default" )
private UserConfiguration userConf;
@Inject
@Named( value = "userManager#ldap" )
private UserManager userManager;
@Inject
private LdapConnectionFactory ldapConnectionFactory;
@Inject
private LdapController ldapController;
private boolean writableLdap = false;
@PostConstruct
public void initialize()
{
this.writableLdap = userConf.getBoolean( UserConfigurationKeys.LDAP_WRITABLE, this.writableLdap );
}
public void addChildRole( Role role, Role childRole )
throws RbacObjectInvalidException, RbacManagerException
@ -141,8 +171,23 @@ public class LdapRbacManager
public List<Role> getAllAssignableRoles()
throws RbacManagerException, RbacObjectNotFoundException
{
// TODO FROM ldap or from real impl ?
return this.rbacImpl.getAllAssignableRoles();
try
{
Collection<String> roleNames = ldapRoleMapper.getLdapGroupMappings().values();
List<Role> roles = new ArrayList<Role>();
for ( String name : roleNames )
{
roles.add( new RoleImpl( name ) );
}
return roles;
}
catch ( MappingException e )
{
throw new RbacManagerException( e.getMessage(), e );
}
}
public List<Operation> getAllOperations()
@ -166,7 +211,6 @@ public class LdapRbacManager
public List<Role> getAllRoles()
throws RbacManagerException
{
// TODO FROM ldap or from real impl ?
try
{
List<String> groups = ldapRoleMapper.getAllGroups();
@ -183,7 +227,38 @@ public class LdapRbacManager
throws RbacManagerException
{
// TODO FROM ldap or from real impl ?
return this.rbacImpl.getAllUserAssignments();
//return this.rbacImpl.getAllUserAssignments();
LdapConnection ldapConnection = null;
try
{
ldapConnection = ldapConnectionFactory.getConnection();
Map<String, Collection<String>> usersWithRoles =
ldapController.findUsersWithRoles( ldapConnection.getDirContext() );
List<UserAssignment> userAssignments = new ArrayList<UserAssignment>( usersWithRoles.size() );
for ( Map.Entry<String, Collection<String>> entry : usersWithRoles.entrySet() )
{
UserAssignment userAssignment = new UserAssignmentImpl( entry.getKey(), entry.getValue() );
userAssignments.add( userAssignment );
}
return userAssignments;
}
catch ( LdapControllerException e )
{
throw new RbacManagerException( e.getMessage(), e );
}
catch ( LdapException e )
{
throw new RbacManagerException( e.getMessage(), e );
}
finally
{
if ( ldapConnection != null )
{
ldapConnection.close();
}
}
}
public Map<String, List<Permission>> getAssignedPermissionMap( String username )
@ -241,15 +316,9 @@ public class LdapRbacManager
List<Role> roles = new ArrayList<Role>( roleNames.size() );
// TODO normally new Role with name must be enough
for ( String name : roleNames )
{
Role role = rbacImpl.getRole( name );
if ( role != null )
{
roles.add( role );
}
roles.add( new RoleImpl( name ) );
}
return roles;
@ -263,8 +332,8 @@ public class LdapRbacManager
public Collection<Role> getAssignedRoles( UserAssignment userAssignment )
throws RbacObjectNotFoundException, RbacManagerException
{
// TODO here !!
return this.rbacImpl.getAssignedRoles( userAssignment );
return getAssignedRoles( userAssignment.getPrincipal() );
//return this.rbacImpl.getAssignedRoles( userAssignment );
}
public Map<String, Role> getChildRoles( Role role )
@ -516,13 +585,30 @@ public class LdapRbacManager
}
public boolean roleExists( Role role )
throws RbacManagerException
{
return this.rbacImpl.roleExists( role );
if ( role == null )
{
return false;
}
return roleExists( role.getName() );
}
public boolean roleExists( String name )
throws RbacManagerException
{
return this.rbacImpl.roleExists( name );
if ( StringUtils.isEmpty( name ) )
{
return false;
}
try
{
return ldapRoleMapper.getAllRoles().contains( name );
}
catch ( Exception e )
{
throw new RbacManagerException( e.getMessage(), e );
}
}
public Operation saveOperation( Operation operation )
@ -583,7 +669,44 @@ public class LdapRbacManager
public UserAssignment saveUserAssignment( UserAssignment userAssignment )
throws RbacObjectInvalidException, RbacManagerException
{
return this.rbacImpl.saveUserAssignment( userAssignment );
try
{
if ( !userManager.userExists( userAssignment.getPrincipal() ) )
{
User user = userManager.createUser( userAssignment.getPrincipal(), null, null );
user = userManager.addUser( user );
}
List<String> allRoles = ldapRoleMapper.getAllRoles();
List<String> currentUserRoles = ldapRoleMapper.getRoles( userAssignment.getPrincipal() );
for ( String role : userAssignment.getRoleNames() )
{
if ( !currentUserRoles.contains( role ) && writableLdap )
{
// role exists in ldap ?
if ( !allRoles.contains( role ) )
{
ldapRoleMapper.saveRole( role );
}
ldapRoleMapper.saveUserRole( role, userAssignment.getPrincipal() );
}
}
return userAssignment;
}
catch ( UserManagerException e )
{
throw new RbacManagerException( e.getMessage(), e );
}
catch ( MappingException e )
{
throw new RbacManagerException( e.getMessage(), e );
}
//return this.rbacImpl.saveUserAssignment( userAssignment );
}
public boolean userAssignmentExists( String principal )
@ -627,4 +750,180 @@ public class LdapRbacManager
{
this.ldapRoleMapper = ldapRoleMapper;
}
private static class RoleImpl
extends AbstractRole
{
private String name;
private RoleImpl( String name )
{
this.name = name;
}
public void addPermission( Permission permission )
{
// no op
}
public void addChildRoleName( String name )
{
// no op
}
public List<String> getChildRoleNames()
{
return Collections.emptyList();
}
public String getDescription()
{
return null;
}
public String getName()
{
return this.name;
}
public List<Permission> getPermissions()
{
return Collections.emptyList();
}
public boolean isAssignable()
{
return true;
}
public void removePermission( Permission permission )
{
// no op
}
public void setAssignable( boolean assignable )
{
// no op
}
public void setChildRoleNames( List<String> names )
{
// no op
}
public void setDescription( String description )
{
// no op
}
public void setName( String name )
{
this.name = name;
}
public void setPermissions( List<Permission> permissions )
{
// no op
}
public boolean isPermanent()
{
return true;
}
public void setPermanent( boolean permanent )
{
// no op
}
}
private static class UserAssignmentImpl
implements UserAssignment
{
private String username;
private List<String> roleNames;
private boolean permanent;
private UserAssignmentImpl( String username, Collection<String> roleNames )
{
this.username = username;
if ( roleNames == null )
{
this.roleNames = new ArrayList<String>();
}
else
{
this.roleNames = new ArrayList<String>( roleNames );
}
}
public String getPrincipal()
{
return this.username;
}
public List<String> getRoleNames()
{
return this.roleNames;
}
public void addRoleName( Role role )
{
if ( role == null )
{
return;
}
this.roleNames.add( role.getName() );
}
public void addRoleName( String roleName )
{
if ( roleName == null )
{
return;
}
this.roleNames.add( roleName );
}
public void removeRoleName( Role role )
{
if ( role == null )
{
return;
}
this.roleNames.remove( role.getName() );
}
public void removeRoleName( String roleName )
{
if ( roleName == null )
{
return;
}
this.roleNames.remove( roleName );
}
public void setPrincipal( String principal )
{
this.username = principal;
}
public void setRoleNames( List<String> roles )
{
this.roleNames = roles;
}
public boolean isPermanent()
{
return this.permanent;
}
public void setPermanent( boolean permanent )
{
this.permanent = permanent;
}
}
}

View File

@ -52,7 +52,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
//@DirtiesContext( classMode = DirtiesContext.ClassMode.AFTER_CLASS )
@DirtiesContext( classMode = DirtiesContext.ClassMode.AFTER_CLASS )
public class LdapRbacManagerTest
extends AbstractRbacManagerTestCase
{
@ -286,4 +286,15 @@ public class LdapRbacManagerTest
{
assertTrue( ( ( eventTracker.initCount > 0 ) && ( eventTracker.initCount <= 2 ) ) );
}
/**
* it's mandatory to have at least 1 user when creating a group so unit test result need to be changed.
*
* @param size
* @return
*/
protected int incAssignements( int size )
{
return size + 1;
}
}

View File

@ -16,4 +16,14 @@
# under the License.
ldap.config.groups.role.theADMIN=ADMIN
ldap.config.groups.role.thePROJECT_ADMIN=PROJECT_ADMIN
ldap.config.groups.role.theDEVELOPER=DEVELOPER
ldap.config.groups.role.theDEVELOPER=DEVELOPER
ldap.config.groups.role.user-admin=User Administrator
ldap.config.groups.role.sys-admin=System Administrator
ldap.config.groups.role.trusted-dev=Trusted Developer
ldap.config.groups.role.developer=Developer
ldap.config.base.dn=dc=archiva,dc=apache,dc=org
ldap.config.writable=true
ldap.bind.authenticator.allowEmptyPasswords=true
ldap.config.groups.base.dn=dc=archiva,dc=apache,dc=org

View File

@ -47,5 +47,9 @@
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-assert</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -16,6 +16,7 @@ package org.apache.archiva.redback.tests;
* limitations under the License.
*/
import org.fest.assertions.Assertions;
import junit.framework.TestCase;
import org.apache.archiva.redback.rbac.Operation;
import org.apache.archiva.redback.rbac.RBACManager;
@ -45,8 +46,8 @@ import org.springframework.test.annotation.DirtiesContext;
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:/META-INF/spring-context.xml", "classpath*:/spring-context.xml" })
@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( locations = { "classpath*:/META-INF/spring-context.xml", "classpath*:/spring-context.xml" } )
public abstract class AbstractRbacManagerTestCase
extends TestCase
{
@ -658,17 +659,30 @@ public abstract class AbstractRbacManagerTestCase
assignment.addRoleName( adminRole.getName() );
assignment = manager.saveUserAssignment( assignment );
assertEquals( 3, assignment.getRoleNames().size() );
assertEquals( 1, manager.getAllUserAssignments().size() );
assertEquals( 3, manager.getAllRoles().size() );
Assertions.assertThat( assignment.getRoleNames() ).isNotNull().isNotEmpty().hasSize( 3 );
Assertions.assertThat( manager.getAllUserAssignments() ).isNotNull().isNotEmpty().hasSize(
incAssignements( 1 ) );
Assertions.assertThat( manager.getAllRoles() ).isNotNull().isNotEmpty().hasSize( 3 );
afterSetup();
// Get the List of Assigned Roles for user bob.
Collection<Role> assignedRoles = manager.getAssignedRoles( username );
assertNotNull( assignedRoles );
assertEquals( 3, assignedRoles.size() );
Assertions.assertThat( assignedRoles ).isNotNull().isNotEmpty().hasSize( 3 );
}
/**
* getAllUserAssignments() can return more for ldap as when creating a group
* it's mandatory to have at leat 1 user in the group
*
* @param size
* @return
*/
protected int incAssignements( int size )
{
return size;
}
@Test
@ -683,8 +697,8 @@ public abstract class AbstractRbacManagerTestCase
Role added = manager.saveRole( getDeveloperRole() );
String roleName = added.getName();
assertEquals( 3, manager.getAllRoles().size() );
assertEquals( 3, manager.getAllPermissions().size() );
Assertions.assertThat( manager.getAllRoles() ).isNotNull().isNotEmpty().hasSize( 3 );
Assertions.assertThat( manager.getAllPermissions() ).isNotNull().isNotEmpty().hasSize( 3 );
// Setup User / Assignment with 1 role.
String username = "bob";
@ -693,15 +707,14 @@ public abstract class AbstractRbacManagerTestCase
assignment.addRoleName( roleName );
manager.saveUserAssignment( assignment );
assertEquals( 1, manager.getAllUserAssignments().size() );
assertEquals( 3, manager.getAllRoles().size() );
assertEquals( 3, manager.getAllPermissions().size() );
Assertions.assertThat( manager.getAllUserAssignments() ).isNotNull().isNotEmpty().hasSize( 1 );
Assertions.assertThat( manager.getAllRoles() ).isNotNull().isNotEmpty().hasSize( 3 );
Assertions.assertThat( manager.getAllPermissions() ).isNotNull().isNotEmpty().hasSize( 3 );
// Get the List of Assigned Roles for user bob.
Collection<Permission> assignedPermissions = manager.getAssignedPermissions( username );
assertNotNull( assignedPermissions );
assertEquals( 1, assignedPermissions.size() );
Assertions.assertThat( assignedPermissions ).isNotNull().isNotEmpty().hasSize( 1 );
}
public Role getChildRole( RBACManager manager, Role role, String expectedChildRoleName, int childRoleCount )

View File

@ -215,4 +215,5 @@ public interface UserManager
* @since 2.1
*/
String getDescriptionKey();
}

View File

@ -22,6 +22,8 @@ package org.apache.archiva.redback.users.ldap;
import org.apache.archiva.redback.common.ldap.user.LdapUser;
import org.apache.archiva.redback.common.ldap.user.UserMapper;
import org.apache.archiva.redback.configuration.UserConfiguration;
import org.apache.archiva.redback.configuration.UserConfigurationKeys;
import org.apache.archiva.redback.users.AbstractUserManager;
import org.apache.archiva.redback.users.User;
import org.apache.archiva.redback.users.UserManager;
@ -37,6 +39,7 @@ import org.apache.archiva.redback.users.ldap.ctl.LdapControllerException;
import org.apache.archiva.redback.users.ldap.service.LdapCacheService;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import javax.naming.directory.DirContext;
@ -47,27 +50,40 @@ import java.util.List;
/**
* @author <a href="jesse@codehaus.org"> jesse
*/
@Service("userManager#ldap")
@Service( "userManager#ldap" )
public class LdapUserManager
extends AbstractUserManager
implements UserManager
{
@Inject
@Named(value = "ldapConnectionFactory#configurable")
@Named( value = "ldapConnectionFactory#configurable" )
private LdapConnectionFactory connectionFactory;
@Inject
private LdapController controller;
@Inject
@Named(value = "userMapper#ldap")
@Named( value = "userMapper#ldap" )
private UserMapper mapper;
@Inject
@Named( value = "userConfiguration#default" )
private UserConfiguration userConf;
@Inject
private LdapCacheService ldapCacheService;
private User guestUser;
private boolean writableLdap = false;
@PostConstruct
public void initialize()
{
this.writableLdap = userConf.getBoolean( UserConfigurationKeys.LDAP_WRITABLE, this.writableLdap );
controller.initialize();
}
public boolean isReadOnly()
{
return true;

View File

@ -19,27 +19,43 @@ package org.apache.archiva.redback.users.ldap.ctl;
* under the License.
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.apache.archiva.redback.common.ldap.connection.LdapConnection;
import org.apache.archiva.redback.common.ldap.connection.LdapException;
import org.apache.archiva.redback.common.ldap.user.LdapUser;
import org.apache.archiva.redback.common.ldap.user.LdapUserMapper;
import org.apache.archiva.redback.common.ldap.user.UserMapper;
import org.apache.archiva.redback.configuration.UserConfiguration;
import org.apache.archiva.redback.configuration.UserConfigurationKeys;
import org.apache.archiva.redback.policy.PasswordEncoder;
import org.apache.archiva.redback.policy.encoders.SHA1PasswordEncoder;
import org.apache.archiva.redback.users.User;
import org.apache.archiva.redback.users.UserManager;
import org.apache.archiva.redback.common.ldap.MappingException;
import org.apache.archiva.redback.users.ldap.LdapUserQuery;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@ -55,9 +71,33 @@ public class DefaultLdapController
private Logger log = LoggerFactory.getLogger( getClass() );
@Inject
@Named( value = "userMapper#ldap" )
@Named(value = "userMapper#ldap")
private UserMapper mapper;
@Inject
@Named( value = "userConfiguration#default" )
private UserConfiguration userConf;
private boolean writableLdap = false;
private PasswordEncoder passwordEncoder;
private String baseDn;
private String groupsDn;
private String ldapGroupClass = "groupOfUniqueNames";
@PostConstruct
public void initialize()
{
this.writableLdap = userConf.getBoolean( UserConfigurationKeys.LDAP_WRITABLE, this.writableLdap );
this.baseDn = userConf.getConcatenatedList( UserConfigurationKeys.LDAP_BASEDN, null );
this.passwordEncoder = new SHA1PasswordEncoder();
this.groupsDn = userConf.getConcatenatedList( UserConfigurationKeys.LDAP_GROUPS_BASEDN, this.groupsDn );
this.ldapGroupClass = userConf.getString( UserConfigurationKeys.LDAP_GROUPS_CLASS, this.ldapGroupClass );
}
/**
* @see org.apache.archiva.redback.users.ldap.ctl.LdapController#removeUser(String, javax.naming.directory.DirContext)
*/
@ -250,10 +290,55 @@ public class DefaultLdapController
}
if ( user.getUsername().equals( UserManager.GUEST_USERNAME ) )
{
log.debug( "skip user '{}' creation" );
//We don't store guest
return;
}
boolean userExists = userExists( user.getUsername(), context );
if ( userExists )
{
log.debug( "user '{}' exists skip creation", user.getUsername() );
return;
}
if ( writableLdap )
{
try
{
bindUserObject( context, user );
log.info( "user {} created in ldap", user.getUsername() );
}
catch ( NamingException e )
{
throw new LdapControllerException( e.getMessage(), e );
}
}
}
private void bindUserObject( DirContext context, User user )
throws NamingException
{
Attributes attributes = new BasicAttributes( true );
BasicAttribute objectClass = new BasicAttribute( "objectClass" );
objectClass.add( "top" );
objectClass.add( "inetOrgPerson" );
objectClass.add( "person" );
objectClass.add( "organizationalperson" );
attributes.put( objectClass );
attributes.put( "cn", user.getUsername() );
attributes.put( "sn", "foo" );
if ( StringUtils.isNotEmpty( user.getEmail() ) )
{
attributes.put( "mail", user.getEmail() );
}
if ( userConf.getBoolean( UserConfigurationKeys.LDAP_BIND_AUTHENTICATOR_ALLOW_EMPTY_PASSWORDS, false )
&& StringUtils.isNotEmpty( user.getPassword() ) )
{
attributes.put( "userPassword", passwordEncoder.encodePassword( user.getPassword() ) );
}
attributes.put( "givenName", "foo" );
context.createSubcontext( "cn=" + user.getUsername() + "," + this.getBaseDn(), attributes );
}
/**
@ -308,4 +393,154 @@ public class DefaultLdapController
}
}
public Map<String, Collection<String>> findUsersWithRoles( DirContext dirContext )
throws LdapControllerException
{
Map<String, Collection<String>> usersWithRoles = new HashMap<String, Collection<String>>();
NamingEnumeration<SearchResult> namingEnumeration = null;
try
{
SearchControls searchControls = new SearchControls();
searchControls.setDerefLinkFlag( true );
searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
String filter = "objectClass=" + getLdapGroupClass();
namingEnumeration = dirContext.search( getGroupsDn(), filter, searchControls );
while ( namingEnumeration.hasMore() )
{
SearchResult searchResult = namingEnumeration.next();
String groupName = searchResult.getName();
// cn=blabla we only want bla bla
groupName = StringUtils.substringAfter( groupName, "=" );
Attribute uniqueMemberAttr = searchResult.getAttributes().get( "uniquemember" );
if ( uniqueMemberAttr != null )
{
NamingEnumeration<String> allMembersEnum = (NamingEnumeration<String>) uniqueMemberAttr.getAll();
while ( allMembersEnum.hasMore() )
{
String userName = allMembersEnum.next();
// uid=blabla we only want bla bla
userName = StringUtils.substringAfter( userName, "=" );
userName = StringUtils.substringBefore( userName, "," );
Collection<String> roles = usersWithRoles.get( userName );
if ( roles == null )
{
roles = new HashSet<String>();
}
roles.add( groupName );
usersWithRoles.put( userName, roles );
}
}
log.debug( "found groupName: '{}' with users: {}", groupName );
}
return usersWithRoles;
}
catch ( NamingException e )
{
throw new LdapControllerException( e.getMessage(), e );
}
finally
{
if ( namingEnumeration != null )
{
try
{
namingEnumeration.close();
}
catch ( NamingException e )
{
log.warn( "failed to close search results", e );
}
}
}
}
//-----------------------------
// setters/getters
//-----------------------------
public UserMapper getMapper()
{
return mapper;
}
public void setMapper( UserMapper mapper )
{
this.mapper = mapper;
}
public UserConfiguration getUserConf()
{
return userConf;
}
public void setUserConf( UserConfiguration userConf )
{
this.userConf = userConf;
}
public boolean isWritableLdap()
{
return writableLdap;
}
public void setWritableLdap( boolean writableLdap )
{
this.writableLdap = writableLdap;
}
public PasswordEncoder getPasswordEncoder()
{
return passwordEncoder;
}
public void setPasswordEncoder( PasswordEncoder passwordEncoder )
{
this.passwordEncoder = passwordEncoder;
}
public String getBaseDn()
{
return baseDn;
}
public void setBaseDn( String baseDn )
{
this.baseDn = baseDn;
}
public String getGroupsDn()
{
return groupsDn;
}
public void setGroupsDn( String groupsDn )
{
this.groupsDn = groupsDn;
}
public String getLdapGroupClass()
{
return ldapGroupClass;
}
public void setLdapGroupClass( String ldapGroupClass )
{
this.ldapGroupClass = ldapGroupClass;
}
}

View File

@ -27,6 +27,7 @@ import org.apache.archiva.redback.users.ldap.LdapUserQuery;
import javax.naming.directory.DirContext;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
*
@ -54,4 +55,14 @@ public interface LdapController
List<User> getUsersByQuery( LdapUserQuery query, DirContext context )
throws LdapControllerException, MappingException;
void initialize();
/**
* @param dirContext
* @return Map key == username and value == list of role names
* @throws LdapControllerException
*/
Map<String, Collection<String>> findUsersWithRoles( DirContext dirContext )
throws LdapControllerException;
}