Skip to content

Commit

Permalink
Implemented the listRoles procedure
Browse files Browse the repository at this point in the history
  • Loading branch information
OliviaYtterbrink authored and henriknyman committed Jun 16, 2016
1 parent 8b49459 commit cceacb1
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.stream.Collectors;

import org.neo4j.kernel.lifecycle.LifecycleAdapter;
import org.neo4j.server.security.auth.exception.ConcurrentModificationException;
Expand Down Expand Up @@ -194,6 +195,12 @@ public void removeUserFromAllRoles( String username ) throws ConcurrentModificat
}
}

@Override
public Set<String> getAllRoleNames()
{
return roles.stream().map( RoleRecord::name ).collect( Collectors.toSet() );
}

protected void populateUserMap( RoleRecord role )
{
for ( String username : role.users() )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,18 @@ public Stream<StringResult> listUsers() throws IllegalCredentialsException, IOEx
return shiroSubject.getUserManager().getAllUsernames().stream().map( StringResult::new );
}

@PerformsDBMS
@Procedure( "dbms.listRoles" )
public Stream<StringResult> listRoles() throws IllegalCredentialsException, IOException
{
ShiroAuthSubject shiroSubject = ShiroAuthSubject.castOrFail( authSubject );
if ( !shiroSubject.isAdmin() )
{
throw new AuthorizationViolationException( PERMISSION_DENIED );
}
return shiroSubject.getRoleManager().getAllRoleNames().stream().map( StringResult::new );
}

public class StringResult {
public final String value;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.neo4j.server.security.enterprise.auth;

import java.io.IOException;
import java.util.Set;

public interface RoleManager
{
Expand All @@ -42,4 +43,6 @@ public interface RoleManager
* @throws IOException
*/
void removeUserFromRole( String username, String roleName ) throws IOException;

Set<String> getAllRoleNames();
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,6 @@ public interface RoleRepository extends Lifecycle
boolean isValidName( String name );

void removeUserFromAllRoles( String username ) throws ConcurrentModificationException, IOException;

Set<String> getAllRoleNames();
}
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,13 @@ void activateUser( String username ) throws IOException
realm.activateUser( username );
}

@Override
public Set<String> getAllRoleNames()
{
assertAuthEnabled();
return roleRepository.getAllRoleNames();
}

public Set<String> getAllUsernames()
{
assertAuthEnabled();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,48 @@ public void userListing() throws Exception
} );
}

@Test
public void shouldReturnRoles() throws Exception
{
testResult( db, adminSubject, "CALL dbms.listRoles() YIELD value AS roles RETURN roles", r -> {
List<Object> roles = getObjectsAsList( r, "roles" );
Assert.assertThat( roles,
containsInAnyOrder( PredefinedRolesBuilder.ADMIN, PredefinedRolesBuilder.ARCHITECT,
PredefinedRolesBuilder.PUBLISHER, PredefinedRolesBuilder.READER ) );
assertEquals( 4, roles.size() );
} );
}

@Test
public void shouldNotAllowNonAdminListRoles() throws Exception
{
testFailListRoles( noneSubject );
testFailListRoles( readSubject );
testFailListRoles( writeSubject );
testFailListRoles( schemaSubject );
}

/*
Admin creates user Henrik with password bar
Henrik logs in with correct password → ok
Henrik lists all roles → permission denied
Admin lists all roles → ok
Admin adds user Henrik to role Admin
Henrik lists all roles → ok
*/
@Test
public void rolesListing() throws Exception
{
testCallEmpty( db, adminSubject, "CALL dbms.createUser('Henrik', 'bar', false)", null );
AuthSubject subject = manager.login( authToken( "Henrik", "bar" ) );
assertEquals( AuthenticationResult.SUCCESS, subject.getAuthenticationResult() );
testFailListRoles( subject );
testSuccessfulListRolesAction( adminSubject );
testCallEmpty( db, adminSubject, "CALL dbms.addUserToRole('Henrik', '" + PredefinedRolesBuilder.ADMIN + "')",
null );
testSuccessfulListRolesAction( subject );
}

//-------------Helper functions---------------

private void testSuccessfulReadAction( AuthSubject subject, Long count )
Expand Down Expand Up @@ -854,6 +896,25 @@ private void testFailListUsers( AuthSubject subject, Long count )
}
}

private void testSuccessfulListRolesAction( AuthSubject subject )
{
testCall( db, subject, "CALL dbms.listRoles() YIELD value AS roles RETURN count(roles)",
( r ) -> assertEquals( r.get( "count(roles)" ), 4L ) );
}

private void testFailListRoles( AuthSubject subject )
{
try
{
testSuccessfulListRolesAction( subject );
}
catch ( QueryExecutionException e )
{
assertTrue( "Exception should contain '" + AuthProcedures.PERMISSION_DENIED + "'",
e.getMessage().contains( AuthProcedures.PERMISSION_DENIED ) );
}
}

private List<Object> getObjectsAsList( Result r, String key )
{
return r.stream().map( s -> s.get( key ) ).collect( Collectors.toList() );
Expand Down

0 comments on commit cceacb1

Please sign in to comment.