You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@archiva.apache.org by ma...@apache.org on 2020/11/17 18:11:40 UTC

[archiva-redback-core] 02/03: Adding model information to roles

This is an automated email from the ASF dual-hosted git repository.

martin_s pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/archiva-redback-core.git

commit 4e8adffac299202482e3867e2192356475613fab
Author: Martin Stockhammer <ma...@apache.org>
AuthorDate: Mon Nov 16 12:01:06 2020 +0100

    Adding model information to roles
---
 redback-rbac/redback-rbac-model/pom.xml            |   4 +
 .../archiva/redback/rbac/AbstractRBACManager.java  |  21 ++
 .../apache/archiva/redback/rbac/RBACManager.java   | 250 ++++++++++++++++-----
 .../java/org/apache/archiva/redback/rbac/Role.java |   4 +-
 .../redback/rbac/cached/CachedRbacManager.java     |  72 +++++-
 .../src/main/resources/META-INF/spring-context.xml |  11 +
 .../redback-rbac-jpa/pom.xml                       |   5 +
 .../archiva/redback/rbac/jpa/JpaRbacManager.java   |  65 +++++-
 .../archiva/redback/rbac/jpa/model/JpaRole.java    |   5 +
 .../archiva/redback/rbac/ldap/LdapRbacManager.java |  82 +++++--
 .../redback/rbac/memory/MemoryRbacManager.java     |  43 +++-
 .../archiva/redback/role/DefaultRoleManager.java   |  27 ++-
 .../apache/archiva/redback/role/RoleManager.java   |  14 +-
 .../role/processor/DefaultRoleModelProcessor.java  |   3 +
 .../template/DefaultRoleTemplateProcessor.java     |   7 +-
 .../redback/role/AbstractRoleManagerTest.java      |   4 +-
 16 files changed, 503 insertions(+), 114 deletions(-)

diff --git a/redback-rbac/redback-rbac-model/pom.xml b/redback-rbac/redback-rbac-model/pom.xml
index 64e7362..99b88e8 100644
--- a/redback-rbac/redback-rbac-model/pom.xml
+++ b/redback-rbac/redback-rbac-model/pom.xml
@@ -56,6 +56,10 @@
       <groupId>jakarta.annotation</groupId>
       <artifactId>jakarta.annotation-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+    </dependency>
 
   </dependencies>
 
diff --git a/redback-rbac/redback-rbac-model/src/main/java/org/apache/archiva/redback/rbac/AbstractRBACManager.java b/redback-rbac/redback-rbac-model/src/main/java/org/apache/archiva/redback/rbac/AbstractRBACManager.java
index 9ba04b4..8ace7e6 100644
--- a/redback-rbac/redback-rbac-model/src/main/java/org/apache/archiva/redback/rbac/AbstractRBACManager.java
+++ b/redback-rbac/redback-rbac-model/src/main/java/org/apache/archiva/redback/rbac/AbstractRBACManager.java
@@ -16,6 +16,7 @@ package org.apache.archiva.redback.rbac;
  * limitations under the License.
  */
 
+import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
@@ -186,6 +187,12 @@ public abstract class AbstractRBACManager
     }
 
     @Override
+    public Role createRole(String name) {
+        final String id = DigestUtils.sha1Hex( name );
+        return createRole( id, name );
+    }
+
+    @Override
     public void removeRole( String roleName )
         throws RbacObjectNotFoundException, RbacManagerException
     {
@@ -193,6 +200,12 @@ public abstract class AbstractRBACManager
     }
 
     @Override
+    public void removeRoleById( String id ) throws RbacManagerException
+    {
+        removeRole( getRoleById( id ) );
+    }
+
+    @Override
     public void removePermission( String permissionName )
         throws RbacObjectNotFoundException, RbacManagerException
     {
@@ -359,6 +372,14 @@ public abstract class AbstractRBACManager
     }
 
     @Override
+    public boolean roleExistsById( final String id )
+        throws RbacManagerException
+    {
+        return getAllRoles( ).stream( ).filter( role -> StringUtils.equals( role.getId( ), id ) )
+            .findAny( ).isPresent( );
+    }
+
+    @Override
     public boolean userAssignmentExists( String principal )
     {
         try
diff --git a/redback-rbac/redback-rbac-model/src/main/java/org/apache/archiva/redback/rbac/RBACManager.java b/redback-rbac/redback-rbac-model/src/main/java/org/apache/archiva/redback/rbac/RBACManager.java
index 9299cb0..11b56db 100644
--- a/redback-rbac/redback-rbac-model/src/main/java/org/apache/archiva/redback/rbac/RBACManager.java
+++ b/redback-rbac/redback-rbac-model/src/main/java/org/apache/archiva/redback/rbac/RBACManager.java
@@ -25,11 +25,12 @@ import java.util.Map;
 import java.util.Set;
 
 /**
- * RBACManager
+ * Manages the roles, permissions and operations of the RBAC system.
  *
  * @author Jesse McConnell
  * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
- * TODO expand on javadoc
+ * @author Martin Stockhammer <ma...@apache.org>
+ *
  */
 public interface RBACManager
 {
@@ -55,71 +56,171 @@ public interface RBACManager
     Role createRole( String name );
 
     /**
+     * Creates a new role with the given id and role name.
+     * @param id the role identifier, which must be unique
+     * @param name the role name, which must be unique
+     * @return the new role instance
+     */
+    Role createRole(String id, String name);
+
+    /**
      * Tests for the existence of a Role.
      *
      * @return true if role exists in store.
-     * @throws RbacManagerException
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     boolean roleExists( String name )
         throws RbacManagerException;
 
+    /**
+     * Returns <code>true</code>, if a role with the given id exists.
+     * @param id the role id
+     * @return <code>true</code>, if the role with the given id exists, otherwise <code>false</code>
+     * @throws RbacManagerException if the access to the backend datastore failed
+     */
+    boolean roleExistsById( String id ) throws RbacManagerException;
+
+    /**
+     * Returns true, if the given role exists.
+     *
+     * @param role the role to check
+     * @return <code>true</code>, if the role exists, otherwise <code>false</code>
+     * @throws RbacManagerException if the access to the backend datastore failed
+     */
     boolean roleExists( Role role )
         throws RbacManagerException;
 
+    /**
+     * Persists the given role to the backend datastore.
+     *
+     * @param role the role to save
+     * @return the persisted role, if the method was successful
+     * @throws RbacObjectInvalidException if the given role object was not valid
+     * @throws RbacManagerException if the access to the backend datastore failed
+     */
     Role saveRole( Role role )
         throws RbacObjectInvalidException, RbacManagerException;
 
+    /**
+     * Persists all of the given roles to the backend datastore.
+     * Implementations should try to save all role instances and throw exceptions afterwards.
+     *
+     * @param roles the list of roles to save
+     * @throws RbacObjectInvalidException if one of the given role objects was not valid
+     * @throws RbacManagerException if the access to the backend datastore failed
+     */
     void saveRoles( Collection<Role> roles )
         throws RbacObjectInvalidException, RbacManagerException;
 
     /**
-     * @param roleName
-     * @return
-     * @throws RbacObjectNotFoundException
-     * @throws RbacManagerException
+     * Returns the role identified by the given name
+     *
+     * @param roleName the role name
+     * @return the role instance, if a role by this name was found
+     * @throws RbacObjectNotFoundException if not role was found with the given name
+     * @throws RbacManagerException if the access to the underlying datastore failed
      */
     Role getRole( String roleName )
         throws RbacObjectNotFoundException, RbacManagerException;
 
+    /**
+     * Returns the role identified by the given ID
+     * @param id the role id
+     * @return the role object, if the role with the given id exists
+     * @throws RbacObjectNotFoundException if no role was found with the given id
+     * @throws RbacManagerException if the access to the underlying datastore failed
+     */
+    Role getRoleById( String id ) throws RbacObjectNotFoundException, RbacManagerException;
+
+    /**
+     * Returns the role instances for the given role names.
+     *
+     * @param roleNames the list of role names.
+     * @return a map of (name,role) pairs
+     * @throws RbacObjectNotFoundException if one of the given roles was not found
+     * @throws RbacManagerException if the access to the backend datastore failed
+     */
     Map<String, ? extends Role> getRoles( Collection<String> roleNames )
         throws RbacObjectNotFoundException, RbacManagerException;
 
+    /**
+     * Adds a child to a role.
+     *
+     * @param role the parent role
+     * @param childRole the child role, that is added to the parent role
+     * @throws RbacObjectInvalidException if one of the role objects was not valid
+     * @throws RbacManagerException if the access to the backend datastore failed
+     */
     void addChildRole( Role role, Role childRole )
         throws RbacObjectInvalidException, RbacManagerException;
 
+    /**
+     * Returns all the child roles of a given role.
+     * @param role the parent role
+     * @return the list of child roles
+     * @throws RbacManagerException if the access to the backend datastore failed
+     */
     Map<String, ? extends Role> getChildRoles( Role role )
         throws RbacManagerException;
 
+    /**
+     * Returns all the parent roles of a given role.
+     * @param role the role to check for parent roles
+     * @return the list of parent roles that have <code>role</code> als child
+     * @throws RbacManagerException if the access to the backend datastore failed
+     */
     Map<String, ? extends Role> getParentRoles( Role role )
         throws RbacManagerException;
 
     /**
-     * Method getRoles
+     * Returns all roles defined in the datastore.
+     *
+     * @return the list of roles defined in the datastore
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     List<? extends Role> getAllRoles()
         throws RbacManagerException;
 
     /**
-     * Method getEffectiveRoles
+     * Returns all effective roles. Which means a list with the current role and all child roles recursively.
+     *
+     * @param role the role to use as starting point
+     * @return the set of roles that are found as children of the given role
+     * @throws RbacObjectNotFoundException if the given role was not found
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     Set<? extends Role> getEffectiveRoles( Role role )
         throws RbacObjectNotFoundException, RbacManagerException;
 
     /**
-     * Method removeRole
+     * Removes the given role from the datastore.
      *
-     * @param role
+     * @param role the role to remove
+     * @throws RbacManagerException if the access to the backend datastore failed
+     * @throws RbacObjectNotFoundException if the given role was not found
+     * @throws RbacObjectInvalidException if the given role has invalid data
      */
     void removeRole( Role role )
         throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException;
 
     /**
-     * Method removeRole
+     * Removes the role with the given name from the datastore.
      *
-     * @param roleName
+     * @param roleName the role name
+     * @throws RbacObjectNotFoundException if the role with the given name was not found
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     void removeRole( String roleName )
-        throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException;
+        throws RbacObjectNotFoundException, RbacManagerException;
+
+    /**
+     * Removes the role with the given id from the datastore.
+     *
+     * @param id the role id
+     * @throws RbacObjectNotFoundException if no role with the given id was found
+     * @throws RbacManagerException if the access to the backend datastore failed
+     */
+    void removeRoleById( String id ) throws RbacObjectNotFoundException, RbacManagerException;
 
     // ------------------------------------------------------------------
     // Permission Methods
@@ -133,7 +234,7 @@ public interface RBACManager
      *
      * @param name the name.
      * @return the new Permission.
-     * @throws RbacManagerException
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     Permission createPermission( String name )
         throws RbacManagerException;
@@ -148,7 +249,7 @@ public interface RBACManager
      * @param operationName      the {@link Operation#setName(String)} value
      * @param resourceIdentifier the {@link Resource#setIdentifier(String)} value
      * @return the new Permission.
-     * @throws RbacManagerException
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     Permission createPermission( String name, String operationName, String resourceIdentifier )
         throws RbacManagerException;
@@ -163,18 +264,22 @@ public interface RBACManager
 
     boolean permissionExists( Permission permission );
 
+    @SuppressWarnings( "DuplicateThrows" )
     Permission savePermission( Permission permission )
         throws RbacObjectInvalidException, RbacManagerException;
 
+    @SuppressWarnings( "DuplicateThrows" )
     Permission getPermission( String permissionName )
         throws RbacObjectNotFoundException, RbacManagerException;
 
     List<? extends Permission> getAllPermissions()
         throws RbacManagerException;
 
+    @SuppressWarnings( "DuplicateThrows" )
     void removePermission( Permission permission )
         throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException;
 
+    @SuppressWarnings( "DuplicateThrows" )
     void removePermission( String permissionName )
         throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException;
 
@@ -190,7 +295,7 @@ public interface RBACManager
      *
      * @param name the name.
      * @return the new Operation.
-     * @throws RbacManagerException
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     Operation createOperation( String name )
         throws RbacManagerException;
@@ -204,21 +309,24 @@ public interface RBACManager
      *
      * @param operation the operation to save (new or existing)
      * @return the Operation that was saved.
-     * @throws RbacObjectInvalidException
-     * @throws RbacManagerException
+     * @throws RbacObjectInvalidException if the object is not valid and cannot be saved
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     Operation saveOperation( Operation operation )
         throws RbacObjectInvalidException, RbacManagerException;
 
+    @SuppressWarnings( "DuplicateThrows" )
     Operation getOperation( String operationName )
         throws RbacObjectNotFoundException, RbacManagerException;
 
     List<? extends Operation> getAllOperations()
         throws RbacManagerException;
 
+    @SuppressWarnings( "DuplicateThrows" )
     void removeOperation( Operation operation )
         throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException;
 
+    @SuppressWarnings( "DuplicateThrows" )
     void removeOperation( String operationName )
         throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException;
 
@@ -234,7 +342,7 @@ public interface RBACManager
      *
      * @param identifier the identifier.
      * @return the new Resource.
-     * @throws RbacManagerException
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     Resource createResource( String identifier )
         throws RbacManagerException;
@@ -243,18 +351,22 @@ public interface RBACManager
 
     boolean resourceExists( Resource resource );
 
+    @SuppressWarnings( "DuplicateThrows" )
     Resource saveResource( Resource resource )
         throws RbacObjectInvalidException, RbacManagerException;
 
+    @SuppressWarnings( "DuplicateThrows" )
     Resource getResource( String resourceIdentifier )
         throws RbacObjectNotFoundException, RbacManagerException;
 
     List<? extends Resource> getAllResources()
         throws RbacManagerException;
 
+    @SuppressWarnings( "DuplicateThrows" )
     void removeResource( Resource resource )
         throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException;
 
+    @SuppressWarnings( "DuplicateThrows" )
     void removeResource( String resourceIdentifier )
         throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException;
 
@@ -270,7 +382,7 @@ public interface RBACManager
      *
      * @param principal the principal reference to the user.
      * @return the new UserAssignment object.
-     * @throws RbacManagerException
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     UserAssignment createUserAssignment( String principal )
         throws RbacManagerException;
@@ -282,22 +394,29 @@ public interface RBACManager
     /**
      * Method saveUserAssignment
      *
-     * @param userAssignment
+     * @param userAssignment the user assignment instance to save
+     * @throws RbacObjectInvalidException if the instance has invalid data and cannot be saved
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     UserAssignment saveUserAssignment( UserAssignment userAssignment )
         throws RbacObjectInvalidException, RbacManagerException;
 
+    @SuppressWarnings( "DuplicateThrows" )
     UserAssignment getUserAssignment( String principal )
         throws RbacObjectNotFoundException, RbacManagerException;
 
     /**
-     * Method getAssignments
+     * Returns all user assignments defined
+     * @return list of assignments
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     List<? extends UserAssignment> getAllUserAssignments()
         throws RbacManagerException;
 
     /**
-     * Method getUserAssignmentsForRoless
+     * Returns the assignments for the given roles
+     * @param roleNames collection of role names
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     List<? extends UserAssignment> getUserAssignmentsForRoles( Collection<String> roleNames )
         throws RbacManagerException;
@@ -305,7 +424,10 @@ public interface RBACManager
     /**
      * Method removeAssignment
      *
-     * @param userAssignment
+     * @param userAssignment the assignment to remove
+     * @throws RbacObjectNotFoundException if the assignment was not found
+     * @throws RbacObjectInvalidException if the provided assignment instance has invalid data
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     void removeUserAssignment( UserAssignment userAssignment )
         throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException;
@@ -313,7 +435,10 @@ public interface RBACManager
     /**
      * Method removeAssignment
      *
-     * @param principal
+     * @param principal the principal for which the assignment should be removed
+     * @throws RbacObjectNotFoundException if the user with the given principal name was not found
+     * @throws RbacObjectInvalidException if the principal string was invalid
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     void removeUserAssignment( String principal )
         throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException;
@@ -323,15 +448,15 @@ public interface RBACManager
     // ------------------------------------------------------------------
 
     /**
-     * returns the active roles for a given principal
+     * Returns the active roles for a given principal
      *
-     * NOTE: roles that are returned might have have roles themselves, if
+     * NOTE: roles that are returned might have parent roles themselves, if
      * you just want all permissions then use {@link #getAssignedPermissions(String principal)}
      *
-     * @param principal
+     * @param principal the user principal to search for assignments
      * @return Collection of {@link Role} objects.
-     * @throws RbacObjectNotFoundException
-     * @throws RbacManagerException
+     * @throws RbacObjectNotFoundException if the user with the given principal name was not found
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     Collection<? extends Role> getAssignedRoles( String principal )
         throws RbacObjectNotFoundException, RbacManagerException;
@@ -339,8 +464,10 @@ public interface RBACManager
     /**
      * Get the Collection of {@link Role} objects for this UserAssignment.
      *
-     * @param userAssignment
+     * @param userAssignment the user assignment instance
      * @return Collection of {@link Role} objects for the provided UserAssignment.
+     * @throws RbacObjectNotFoundException if the assignment could not be found
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     Collection<? extends Role> getAssignedRoles( UserAssignment userAssignment )
         throws RbacObjectNotFoundException, RbacManagerException;
@@ -349,10 +476,10 @@ public interface RBACManager
      * Get a list of all assignable roles that are currently not effectively assigned to the specific user,
      * meaning, not a child of any already granted role
      *
-     * @param principal
-     * @return
-     * @throws RbacManagerException
-     * @throws RbacObjectNotFoundException
+     * @param principal the user principal
+     * @return the list of roles, that are currently not assigned to the user, or a empty list, if no such role was found.
+     * @throws RbacManagerException if the access to the backend datastore failed
+     * @throws RbacObjectNotFoundException if the user with the given principal was not found
      */
     Collection<? extends Role> getEffectivelyUnassignedRoles( String principal )
         throws RbacManagerException, RbacObjectNotFoundException;
@@ -360,10 +487,10 @@ public interface RBACManager
     /**
      * Get a list of the effectively assigned roles to the specified user, this includes child roles
      *
-     * @param principal
-     * @return
-     * @throws RbacObjectNotFoundException
-     * @throws RbacManagerException
+     * @param principal the user principal
+     * @return the list of roles effectively assigned to the given user
+     * @throws RbacObjectNotFoundException if the user with the given principal was not found
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     Collection<? extends Role> getEffectivelyAssignedRoles( String principal )
         throws RbacObjectNotFoundException, RbacManagerException;
@@ -371,22 +498,22 @@ public interface RBACManager
     /**
      * Get a list of all assignable roles that are currently not assigned to the specific user.
      *
-     * @param principal
-     * @return
-     * @throws RbacManagerException
-     * @throws RbacObjectNotFoundException
+     * @param principal the user principal name
+     * @return the list of roles not assigned to the given user
+     * @throws RbacManagerException if the access to the backend datastore failed
+     * @throws RbacObjectNotFoundException if the user with the given principal was not found
      */
     Collection<? extends Role> getUnassignedRoles( String principal )
         throws RbacManagerException, RbacObjectNotFoundException;
 
     /**
-     * returns a set of all permissions that are in all active roles for a given
-     * principal
+     * Returns a set of all permissions that are in all active roles for a given
+     * principal. This includes permissions from all assigned parent roles.
      *
-     * @param principal
-     * @return
-     * @throws RbacObjectNotFoundException
-     * @throws RbacManagerException
+     * @param principal the user principal name
+     * @return the list of all permissions assigned to the user
+     * @throws RbacObjectNotFoundException if the user with the given principal name was not found
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     Set<? extends Permission> getAssignedPermissions( String principal )
         throws RbacObjectNotFoundException, RbacManagerException;
@@ -394,29 +521,28 @@ public interface RBACManager
     /**
      * returns a map of assigned permissions keyed off of operation with a list value of Permissions
      *
-     * @param principal
-     * @return
-     * @throws RbacObjectNotFoundException
-     * @throws RbacManagerException
+     * @param principal the user principal name
+     * @return the map of (operation,permission list) pairs
+     * @throws RbacObjectNotFoundException if the user with the given principal was not found
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     Map<String, List<? extends Permission>> getAssignedPermissionMap( String principal )
         throws RbacObjectNotFoundException, RbacManagerException;
 
     /**
-     * returns a list of all assignable roles
+     * Returns a list of all assignable roles
      *
-     * @return
-     * @throws RbacManagerException
-     * @throws RbacObjectNotFoundException
+     * @return list of assignable roles
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     List<? extends Role> getAllAssignableRoles()
-        throws RbacManagerException, RbacObjectNotFoundException;
+        throws RbacManagerException;
 
     /**
-     * returns the global resource object
+     * Returns the global resource object
      *
-     * @return
-     * @throws RbacManagerException
+     * @return the global resource object
+     * @throws RbacManagerException if the access to the backend datastore failed
      */
     Resource getGlobalResource()
         throws RbacManagerException;
diff --git a/redback-rbac/redback-rbac-model/src/main/java/org/apache/archiva/redback/rbac/Role.java b/redback-rbac/redback-rbac-model/src/main/java/org/apache/archiva/redback/rbac/Role.java
index 6990273..407be44 100644
--- a/redback-rbac/redback-rbac-model/src/main/java/org/apache/archiva/redback/rbac/Role.java
+++ b/redback-rbac/redback-rbac-model/src/main/java/org/apache/archiva/redback/rbac/Role.java
@@ -157,9 +157,7 @@ public interface Role
      * @since 3.0
      * @return the role identifier
      */
-    default String getId() {
-        return StringUtils.isEmpty( getModelId() )?getName():(isTemplateInstance()?getModelId()+"."+getResource():getModelId());
-    }
+    String getId();
 
     /**
      * Sets the role id
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-cached/src/main/java/org/apache/archiva/redback/rbac/cached/CachedRbacManager.java b/redback-rbac/redback-rbac-providers/redback-rbac-cached/src/main/java/org/apache/archiva/redback/rbac/cached/CachedRbacManager.java
index 01bbc50..8ffc360 100644
--- a/redback-rbac/redback-rbac-providers/redback-rbac-cached/src/main/java/org/apache/archiva/redback/rbac/cached/CachedRbacManager.java
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-cached/src/main/java/org/apache/archiva/redback/rbac/cached/CachedRbacManager.java
@@ -74,6 +74,10 @@ public class CachedRbacManager
     private Cache<String, Role> rolesCache;
 
     @Inject
+    @Named( value = "cache#rolesById" )
+    private Cache<String, Role> rolesByIdCache;
+
+    @Inject
     @Named( value = "cache#userAssignments" )
     private Cache<String, UserAssignment> userAssignmentsCache;
 
@@ -147,11 +151,26 @@ public class CachedRbacManager
     @Override
     public Role createRole( String name )
     {
-        rolesCache.remove( name );
+        if (rolesCache.hasKey( name ))
+        {
+            Role role = rolesCache.remove( name );
+            rolesByIdCache.remove( role.getId( ) );
+        }
         return this.rbacImpl.createRole( name );
     }
 
     @Override
+    public Role createRole( String id, String name )
+    {
+        if (rolesByIdCache.hasKey( id ))
+        {
+            Role role = rolesByIdCache.remove( id );
+            rolesCache.remove( role.getName( ) );
+        }
+        return this.rbacImpl.createRole( id, name );
+    }
+
+    @Override
     public UserAssignment createUserAssignment( String principal )
         throws RbacManagerException
     {
@@ -397,11 +416,22 @@ public class CachedRbacManager
         {
             Role role = this.rbacImpl.getRole( roleName );
             rolesCache.put( roleName, role );
+            rolesByIdCache.put( role.getId( ), role );
             return role;
         }
     }
 
     @Override
+    public Role getRoleById( String id ) throws RbacObjectNotFoundException, RbacManagerException
+    {
+        if (rolesByIdCache.hasKey( id )) {
+            return rolesByIdCache.get( id );
+        } else {
+            return this.rbacImpl.getRoleById( id );
+        }
+    }
+
+    @Override
     public Map<String, ? extends Role> getRoles( Collection<String> roleNames )
         throws RbacObjectNotFoundException, RbacManagerException
     {
@@ -508,6 +538,7 @@ public class CachedRbacManager
         this.operationsCache.clear();
         this.permissionsCache.clear();
         this.rolesCache.clear();
+        this.rolesByIdCache.clear();
         this.userAssignmentsCache.clear();
         this.userPermissionsCache.clear();
     }
@@ -644,11 +675,24 @@ public class CachedRbacManager
     public void removeRole( String roleName )
         throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
     {
-        rolesCache.remove( roleName );
+        Role role = rolesCache.remove( roleName );
+        if (role!=null) {
+            rolesByIdCache.remove( role.getId( ) );
+        }
         this.rbacImpl.removeRole( roleName );
     }
 
     @Override
+    public void removeRoleById( String id ) throws RbacObjectNotFoundException, RbacManagerException
+    {
+        Role role = rolesByIdCache.remove( id );
+        if (role!=null) {
+            rolesCache.remove( role.getName( ) );
+        }
+        this.rbacImpl.removeRoleById( id );
+    }
+
+    @Override
     public void removeUserAssignment( String principal )
         throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
     {
@@ -690,7 +734,7 @@ public class CachedRbacManager
     public boolean roleExists( Role role )
         throws RbacManagerException
     {
-        if ( rolesCache.hasKey( role.getName() ) )
+        if ( rolesByIdCache.hasKey( role.getId() ) )
         {
             return true;
         }
@@ -711,6 +755,16 @@ public class CachedRbacManager
     }
 
     @Override
+    public boolean roleExistsById( String id ) throws RbacManagerException
+    {
+        if (rolesByIdCache.hasKey( id )) {
+            return true;
+        } else {
+            return this.rbacImpl.roleExistsById( id );
+        }
+    }
+
+    @Override
     public Operation saveOperation( Operation operation )
         throws RbacObjectInvalidException, RbacManagerException
     {
@@ -819,6 +873,7 @@ public class CachedRbacManager
         if ( role != null )
         {
             rolesCache.remove( role.getName() );
+            rolesByIdCache.remove( role.getId( ) );
             // if a role changes we need to invalidate the entire effective role set cache
             // since we have no concept of the heirarchy involved in the role sets
             effectiveRoleSetCache.clear();
@@ -909,12 +964,23 @@ public class CachedRbacManager
         return rolesCache;
     }
 
+
     @SuppressWarnings( "unchecked" )
     public void setRolesCache( Cache<String, ? extends Role> rolesCache )
     {
         this.rolesCache = (Cache<String, Role>) rolesCache;
     }
 
+    public Cache<String, ? extends Role> getRolesByIdCache( )
+    {
+        return rolesByIdCache;
+    }
+
+    public void setRolesByIdCache( Cache<String, ? extends Role> rolesByIdCache )
+    {
+        this.rolesByIdCache = (Cache<String, Role>) rolesByIdCache;
+    }
+
     public Cache<String, ? extends UserAssignment> getUserAssignmentsCache()
     {
         return userAssignmentsCache;
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-cached/src/main/resources/META-INF/spring-context.xml b/redback-rbac/redback-rbac-providers/redback-rbac-cached/src/main/resources/META-INF/spring-context.xml
index b1054ca..33541b8 100644
--- a/redback-rbac/redback-rbac-providers/redback-rbac-cached/src/main/resources/META-INF/spring-context.xml
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-cached/src/main/resources/META-INF/spring-context.xml
@@ -75,6 +75,17 @@
     <property name="timeToLiveSeconds" value="14400"/>
   </bean>
 
+  <bean name="cache#rolesById" class="org.apache.archiva.components.cache.ehcache.EhcacheCache"
+        init-method="initialize">
+    <property name="diskPersistent" value="false"/>
+    <property name="eternal" value="false"/>
+    <property name="maxElementsInMemory" value="1000"/>
+    <property name="memoryEvictionPolicy" value="LRU"/>
+    <property name="name" value="roles"/>
+    <property name="timeToIdleSeconds" value="1800"/>
+    <property name="timeToLiveSeconds" value="14400"/>
+  </bean>
+
   <bean name="cache#effectiveRoleSet" class="org.apache.archiva.components.cache.ehcache.EhcacheCache"
       init-method="initialize">
     <property name="diskPersistent" value="false"/>
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/pom.xml b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/pom.xml
index 51c8c95..9b89d7d 100644
--- a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/pom.xml
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/pom.xml
@@ -108,6 +108,11 @@
       <artifactId>hsqldb</artifactId>
       <scope>test</scope>
     </dependency>
+
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/JpaRbacManager.java b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/JpaRbacManager.java
index c423370..0c7a9da 100644
--- a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/JpaRbacManager.java
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/JpaRbacManager.java
@@ -35,6 +35,7 @@ import org.apache.archiva.redback.rbac.jpa.model.JpaPermission;
 import org.apache.archiva.redback.rbac.jpa.model.JpaResource;
 import org.apache.archiva.redback.rbac.jpa.model.JpaRole;
 import org.apache.archiva.redback.rbac.jpa.model.JpaUserAssignment;
+import org.apache.commons.codec.digest.DigestUtils;
 import org.springframework.stereotype.Service;
 
 import javax.persistence.EntityManager;
@@ -43,6 +44,9 @@ import javax.persistence.PersistenceContext;
 import javax.persistence.Query;
 import javax.persistence.TypedQuery;
 import javax.transaction.Transactional;
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -68,14 +72,51 @@ public class JpaRbacManager extends AbstractRBACManager  {
     }
 
 
-
     @Override
-    public Role createRole(String name) {
-        JpaRole role = new JpaRole();
-        role.setName(name);
+    public Role createRole( String id, String name )
+    {
+        JpaRole role = new JpaRole( );
+        role.setId( id );
+        role.setName( name );
         return role;
     }
 
+    @Override
+    public boolean roleExistsById( String id ) throws RbacManagerException
+    {
+        final EntityManager em = getEm();
+        TypedQuery<Long> q = em.createQuery("SELECT COUNT(r) FROM JpaRole  r WHERE r.id = :roleid", Long.class);
+        q.setParameter("roleid",id);
+        Long num;
+        try {
+            num = q.getSingleResult();
+        } catch (NoResultException ex) {
+            return false;
+        }
+        return num>0;
+    }
+
+    @Override
+    public boolean roleExists( String name ) throws RbacManagerException
+    {
+        final EntityManager em = getEm();
+        TypedQuery<Long> q = em.createQuery("SELECT COUNT(r) FROM JpaRole  r WHERE r.name = :rolename", Long.class);
+        q.setParameter("rolename",name);
+        Long num;
+        try {
+            num = q.getSingleResult();
+        } catch (NoResultException ex) {
+            return false;
+        }
+        return num>0;
+    }
+
+    @Override
+    public boolean roleExists( Role role ) throws RbacManagerException
+    {
+        return this.roleExistsById( role.getId() );
+    }
+
     @Transactional
     @Override
     public Role saveRole(Role role) throws RbacObjectInvalidException, RbacManagerException {
@@ -144,6 +185,22 @@ public class JpaRbacManager extends AbstractRBACManager  {
     }
 
     @Override
+    public Role getRoleById( String id ) throws RbacObjectNotFoundException, RbacManagerException
+    {
+        final EntityManager em = getEm();
+        TypedQuery<JpaRole> q = em.createQuery("SELECT r FROM JpaRole  r WHERE r.id = :roleid", JpaRole.class);
+        q.setParameter("roleid",id);
+        Role role;
+        try {
+            role = q.getSingleResult();
+        } catch (NoResultException ex) {
+            log.warn("Role {} not found", id);
+            throw new RbacObjectNotFoundException("Role not found "+id);
+        }
+        return role;
+    }
+
+    @Override
     public List<? extends Role> getAllRoles() throws RbacManagerException {
         final EntityManager em = getEm();
         TypedQuery<JpaRole> q = em.createQuery("SELECT r FROM JpaRole r", JpaRole.class);
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaRole.java b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaRole.java
index 323a73f..d21eb6a 100644
--- a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaRole.java
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaRole.java
@@ -40,6 +40,7 @@ import java.util.List;
 public class JpaRole extends AbstractRole implements Serializable {
 
     private static final Logger log = LoggerFactory.getLogger( JpaRole.class );
+    private static final long serialVersionUID = 4564608138465995665L;
 
     @Id
     @Column(name="NAME")
@@ -83,6 +84,10 @@ public class JpaRole extends AbstractRole implements Serializable {
     @Column(name="RESOURCE",nullable = false)
     private String resource = "";
 
+    public JpaRole( )
+    {
+    }
+
     @Override
     public void addPermission(Permission permission) {
         if (permission instanceof JpaPermission) {
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-ldap/src/main/java/org/apache/archiva/redback/rbac/ldap/LdapRbacManager.java b/redback-rbac/redback-rbac-providers/redback-rbac-ldap/src/main/java/org/apache/archiva/redback/rbac/ldap/LdapRbacManager.java
index 599edc9..df05dcf 100644
--- a/redback-rbac/redback-rbac-providers/redback-rbac-ldap/src/main/java/org/apache/archiva/redback/rbac/ldap/LdapRbacManager.java
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-ldap/src/main/java/org/apache/archiva/redback/rbac/ldap/LdapRbacManager.java
@@ -169,9 +169,9 @@ public class LdapRbacManager
     }
 
     @Override
-    public Role createRole( String name )
+    public Role createRole( String id, String name )
     {
-        return this.rbacImpl.createRole( name );
+        return this.rbacImpl.createRole( id, name );
     }
 
     @Override
@@ -459,6 +459,10 @@ public class LdapRbacManager
         catch ( LdapException e )
         {
             throw new RbacManagerException( e.getMessage(), e );
+        } finally
+        {
+            closeContext( context );
+            closeLdapConnection( ldapConnection );
         }
     }
 
@@ -544,6 +548,28 @@ public class LdapRbacManager
         {
             return role;
         }
+        if ( !checkIfLdapRole( roleName ) ) return null;
+        role = this.rbacImpl.getRole( roleName );
+        if (role==null)
+        {
+            try
+            {
+                String groupName = ldapRoleMapperConfiguration.getLdapGroupMappings( ).entrySet( ).stream( )
+                    .filter( entry -> entry.getValue( ).contains( roleName ) )
+                    .map( entry -> entry.getKey( ) ).findFirst( ).orElseGet( String::new );
+                role = new RoleImpl( groupName + roleName, roleName );
+            }
+            catch ( MappingException e )
+            {
+                role = new RoleImpl( roleName );
+            }
+        };
+        rolesCache.put( roleName, role );
+        return role;
+    }
+
+    protected boolean checkIfLdapRole( String roleName ) throws RbacManagerException
+    {
         LdapConnection ldapConnection = null;
         DirContext context = null;
         //verify it's a ldap group
@@ -553,7 +579,7 @@ public class LdapRbacManager
             context = ldapConnection.getDirContext();
             if ( !ldapRoleMapper.hasRole( context, roleName ) )
             {
-                return null;
+                return false;
             }
         }
         catch ( MappingException e )
@@ -563,25 +589,27 @@ public class LdapRbacManager
         catch ( LdapException e )
         {
             throw new RbacManagerException( e.getMessage(), e );
-        }
-        role = this.rbacImpl.getRole( roleName );
-        if (role==null)
+        } finally
         {
-            try
-            {
-                String groupName = ldapRoleMapperConfiguration.getLdapGroupMappings( ).entrySet( ).stream( )
-                    .filter( entry -> entry.getValue( ).contains( roleName ) )
-                    .map( entry -> entry.getKey( ) ).findFirst( ).orElseGet( String::new );
-                role = new RoleImpl( groupName + roleName, roleName );
-            }
-            catch ( MappingException e )
-            {
-                role = new RoleImpl( roleName );
+            closeContext( context );
+            closeLdapConnection( ldapConnection );
+        }
+        return true;
+    }
+
+    @Override
+    public Role getRoleById( String id ) throws RbacObjectNotFoundException, RbacManagerException
+    {
+        Role role = rbacImpl.getRoleById( id );
+        if (role==null) {
+            throw new RbacObjectNotFoundException( "Role with id " + id + " not found" );
+        } else {
+            if (checkIfLdapRole( role.getName() )) {
+                return role;
+            } else {
+                return null;
             }
-        };
-        role = ( role == null ) ? new RoleImpl( roleName ) : role;
-        rolesCache.put( roleName, role );
-        return role;
+        }
     }
 
     @Override
@@ -852,6 +880,9 @@ public class LdapRbacManager
             catch ( LdapException e )
             {
                 throw new RbacManagerException( e.getMessage(), e );
+            } finally {
+                closeContext( context );
+                closeLdapConnection( ldapConnection );
             }
             fireRbacRoleRemoved( role );
         }
@@ -952,6 +983,17 @@ public class LdapRbacManager
     }
 
     @Override
+    public boolean roleExistsById( String id ) throws RbacManagerException
+    {
+        Role role = rbacImpl.getRoleById( id );
+        if (role==null) {
+            return false;
+        } else {
+            return roleExists( role.getName() );
+        }
+    }
+
+    @Override
     public Operation saveOperation( Operation operation )
         throws RbacManagerException
     {
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-memory/src/main/java/org/apache/archiva/redback/rbac/memory/MemoryRbacManager.java b/redback-rbac/redback-rbac-providers/redback-rbac-memory/src/main/java/org/apache/archiva/redback/rbac/memory/MemoryRbacManager.java
index 1c743b0..235d3ab 100644
--- a/redback-rbac/redback-rbac-providers/redback-rbac-memory/src/main/java/org/apache/archiva/redback/rbac/memory/MemoryRbacManager.java
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-memory/src/main/java/org/apache/archiva/redback/rbac/memory/MemoryRbacManager.java
@@ -71,6 +71,7 @@ public class MemoryRbacManager
     // Role methods
     // ----------------------------------------------------------------------
 
+    @Override
     public Role saveRole( Role role )
         throws RbacManagerException
     {
@@ -93,6 +94,7 @@ public class MemoryRbacManager
         return role;
     }
 
+    @Override
     public void saveRoles( Collection<Role> roles )
         throws RbacObjectInvalidException, RbacManagerException
     {
@@ -117,6 +119,7 @@ public class MemoryRbacManager
         }
     }
 
+    @Override
     public Role getRole( String roleName )
         throws RbacObjectNotFoundException
     {
@@ -127,6 +130,16 @@ public class MemoryRbacManager
         return roles.get( roleName );
     }
 
+    @Override
+    public Role getRoleById( String id ) throws RbacObjectNotFoundException, RbacManagerException
+    {
+        triggerInit();
+        return roles.values( ).stream( ).filter( role -> StringUtils.equals( role.getId( ), id ) ).findAny( ).orElseThrow(
+            () -> new RbacObjectNotFoundException( "Role with id " + id + " not found" )
+        );
+    }
+
+    @Override
     public void removeRole( Role role )
         throws RbacManagerException, RbacObjectNotFoundException
     {
@@ -144,6 +157,7 @@ public class MemoryRbacManager
         roles.remove( role.getName() );
     }
 
+    @Override
     public List<Role> getAllRoles()
         throws RbacManagerException
     {
@@ -156,6 +170,7 @@ public class MemoryRbacManager
     // Permission methods
     // ----------------------------------------------------------------------
 
+    @Override
     public Operation saveOperation( Operation operation )
         throws RbacManagerException
     {
@@ -167,6 +182,7 @@ public class MemoryRbacManager
         return operation;
     }
 
+    @Override
     public Permission savePermission( Permission permission )
         throws RbacManagerException
     {
@@ -183,6 +199,7 @@ public class MemoryRbacManager
         return permission;
     }
 
+    @Override
     public Resource saveResource( Resource resource )
         throws RbacManagerException
     {
@@ -194,6 +211,7 @@ public class MemoryRbacManager
         return resource;
     }
 
+    @Override
     public UserAssignment saveUserAssignment( UserAssignment userAssignment )
         throws RbacManagerException
     {
@@ -207,6 +225,7 @@ public class MemoryRbacManager
         return userAssignment;
     }
 
+    @Override
     public Operation createOperation( String name )
         throws RbacManagerException
     {
@@ -225,6 +244,7 @@ public class MemoryRbacManager
         return operation;
     }
 
+    @Override
     public Permission createPermission( String name )
         throws RbacManagerException
     {
@@ -243,6 +263,7 @@ public class MemoryRbacManager
         return permission;
     }
 
+    @Override
     public Permission createPermission( String name, String operationName, String resourceIdentifier )
         throws RbacManagerException
     {
@@ -274,6 +295,7 @@ public class MemoryRbacManager
         return permission;
     }
 
+    @Override
     public Resource createResource( String identifier )
         throws RbacManagerException
     {
@@ -292,10 +314,12 @@ public class MemoryRbacManager
         return resource;
     }
 
-    public Role createRole( String name )
+    @Override
+    public Role createRole( String id, String name )
     {
         Role role = new MemoryRole();
         role.setName( name );
+        role.setId( id );
 
         return role;
     }
@@ -309,6 +333,7 @@ public class MemoryRbacManager
         }
     }
 
+    @Override
     public Permission getPermission( String permissionName )
         throws RbacObjectNotFoundException, RbacManagerException
     {
@@ -327,6 +352,7 @@ public class MemoryRbacManager
         return Collections.unmodifiableList( new ArrayList<Resource>( resources.values() ) );
     }
 
+    @Override
     public void removeOperation( Operation operation )
         throws RbacObjectNotFoundException, RbacManagerException
     {
@@ -351,6 +377,7 @@ public class MemoryRbacManager
         }
     }
 
+    @Override
     public void removePermission( Permission permission )
         throws RbacObjectNotFoundException, RbacManagerException
     {
@@ -368,6 +395,7 @@ public class MemoryRbacManager
         permissions.remove( permission.getName() );
     }
 
+    @Override
     public void removeResource( Resource resource )
         throws RbacObjectNotFoundException, RbacManagerException
     {
@@ -402,6 +430,7 @@ public class MemoryRbacManager
         }
     }
 
+    @Override
     public void removeUserAssignment( UserAssignment userAssignment )
         throws RbacObjectNotFoundException, RbacManagerException
     {
@@ -420,6 +449,7 @@ public class MemoryRbacManager
         userAssignments.remove( userAssignment.getPrincipal() );
     }
 
+    @Override
     public void eraseDatabase()
     {
         userAssignments.clear();
@@ -429,6 +459,7 @@ public class MemoryRbacManager
         roles.clear();
     }
 
+    @Override
     public UserAssignment createUserAssignment( String principal )
         throws RbacManagerException
     {
@@ -447,6 +478,7 @@ public class MemoryRbacManager
         }
     }
 
+    @Override
     public List<Operation> getAllOperations()
         throws RbacManagerException
     {
@@ -455,6 +487,7 @@ public class MemoryRbacManager
         return Collections.unmodifiableList( new ArrayList<Operation>( operations.values() ) );
     }
 
+    @Override
     public List<Permission> getAllPermissions()
         throws RbacManagerException
     {
@@ -463,6 +496,7 @@ public class MemoryRbacManager
         return Collections.unmodifiableList( new ArrayList<Permission>( permissions.values() ) );
     }
 
+    @Override
     public List<Resource> getAllResources()
         throws RbacManagerException
     {
@@ -471,6 +505,7 @@ public class MemoryRbacManager
         return Collections.unmodifiableList( new ArrayList<Resource>( resources.values() ) );
     }
 
+    @Override
     public List<UserAssignment> getAllUserAssignments()
         throws RbacManagerException
     {
@@ -479,6 +514,7 @@ public class MemoryRbacManager
         return Collections.unmodifiableList( new ArrayList<UserAssignment>( userAssignments.values() ) );
     }
 
+    @Override
     public List<UserAssignment> getUserAssignmentsForRoles( Collection<String> roleNames )
         throws RbacManagerException
     {
@@ -501,6 +537,7 @@ public class MemoryRbacManager
         return userAssignments;
     }
 
+    @Override
     public UserAssignment getUserAssignment( String principal )
         throws RbacObjectNotFoundException, RbacManagerException
     {
@@ -511,6 +548,7 @@ public class MemoryRbacManager
         return userAssignments.get( principal );
     }
 
+    @Override
     public Operation getOperation( String operationName )
         throws RbacObjectNotFoundException, RbacManagerException
     {
@@ -521,6 +559,7 @@ public class MemoryRbacManager
         return operations.get( operationName );
     }
 
+    @Override
     public Resource getResource( String resourceIdentifier )
         throws RbacObjectNotFoundException, RbacManagerException
     {
@@ -546,11 +585,13 @@ public class MemoryRbacManager
         return true;
     }
 
+    @Override
     public String getDescriptionKey()
     {
         return "archiva.redback.rbacmanager.memory";
     }
 
+    @Override
     public boolean isReadOnly()
     {
         return false;
diff --git a/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/DefaultRoleManager.java b/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/DefaultRoleManager.java
index 6fdefaa..9d68db6 100644
--- a/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/DefaultRoleManager.java
+++ b/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/DefaultRoleManager.java
@@ -97,18 +97,15 @@ public class DefaultRoleManager
     private RBACManager rbacManager;
 
 
+    @Override
     public void loadRoleModel( URL resource )
         throws RoleManagerException
     {
         RedbackRoleModelStaxReader reader = new RedbackRoleModelStaxReader();
 
-        InputStreamReader inputStreamReader = null;
-
-        try
+        try(InputStreamReader inputStreamReader = new InputStreamReader( resource.openStream() ))
         {
 
-            inputStreamReader = new InputStreamReader( resource.openStream() );
-
             RedbackRoleModel roleModel = reader.read( inputStreamReader );
 
             for ( ModelApplication app : roleModel.getApplications() )
@@ -132,12 +129,9 @@ public class DefaultRoleManager
         {
             throw new RoleManagerException( "error parsing redback profile", e );
         }
-        finally
-        {
-            IOUtils.closeQuietly( inputStreamReader );
-        }
     }
 
+    @Override
     public void loadRoleModel( RedbackRoleModel roleModel )
         throws RoleManagerException
     {
@@ -189,6 +183,7 @@ public class DefaultRoleManager
      * create a role for the given roleName using the resource passed in for
      * resolving the ${resource} expression
      */
+    @Override
     public void createTemplatedRole( String templateId, String resource )
         throws RoleManagerException
     {
@@ -199,6 +194,7 @@ public class DefaultRoleManager
      * remove the role corresponding to the role using the resource passed in for resolving the
      * ${resource} expression
      */
+    @Override
     public void removeTemplatedRole( String templateId, String resource )
         throws RoleManagerException
     {
@@ -232,7 +228,8 @@ public class DefaultRoleManager
      * NOTE: this requires removal and creation of the role since the jdo store does not tolerate renaming
      * because of the use of the name as an identifier
      */
-    public void updateRole( String templateId, String oldResource, String newResource )
+    @Override
+    public void moveTemplatedRole( String templateId, String oldResource, String newResource )
         throws RoleManagerException
     {
         // make the new role
@@ -264,6 +261,7 @@ public class DefaultRoleManager
         templateProcessor.remove( blessedModel, templateId, oldResource );
     }
 
+    @Override
     public void assignRole( String roleId, String principal )
         throws RoleManagerException
     {
@@ -296,6 +294,7 @@ public class DefaultRoleManager
         }
     }
 
+    @Override
     public void assignRoleByName( String roleName, String principal )
         throws RoleManagerException
     {
@@ -326,6 +325,7 @@ public class DefaultRoleManager
         }
     }
 
+    @Override
     public void assignTemplatedRole( String templateId, String resource, String principal )
         throws RoleManagerException
     {
@@ -363,6 +363,7 @@ public class DefaultRoleManager
         }
     }
 
+    @Override
     public void unassignRole( String roleId, String principal )
         throws RoleManagerException
     {
@@ -396,6 +397,7 @@ public class DefaultRoleManager
         }
     }
 
+    @Override
     public void unassignRoleByName( String roleName, String principal )
         throws RoleManagerException
     {
@@ -427,6 +429,7 @@ public class DefaultRoleManager
         }
     }
 
+    @Override
     public boolean roleExists( String roleId )
         throws RoleManagerException
     {
@@ -458,6 +461,7 @@ public class DefaultRoleManager
         }
     }
 
+    @Override
     public boolean templatedRoleExists( String templateId, String resource )
         throws RoleManagerException
     {
@@ -488,6 +492,7 @@ public class DefaultRoleManager
         }
     }
 
+    @Override
     @PostConstruct
     public void initialize()
     {
@@ -531,11 +536,13 @@ public class DefaultRoleManager
         log.info( "DefaultRoleManager initialize time {}", stopWatch.getTime() );
     }
 
+    @Override
     public RedbackRoleModel getModel()
     {
         return blessedModel;
     }
 
+    @Override
     public void verifyTemplatedRole( String templateId, String resource )
         throws RoleManagerException
     {
diff --git a/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/RoleManager.java b/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/RoleManager.java
index 9a77eff..7c727e8 100644
--- a/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/RoleManager.java
+++ b/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/RoleManager.java
@@ -70,17 +70,15 @@ public interface RoleManager
 
 
     /**
-     * allows for a role coming from a template to be renamed effectively swapping out the bits of it that
-     * were labeled with the oldResource with the newResource
+     * Moves the instance of the templated role from the old resource to the new resource and updates the
+     * user assignments.
      *
-     * it also manages any user assignments for that role
-     *
-     * @param templateId
-     * @param oldResource
-     * @param newResource
+     * @param templateId the name of the role template
+     * @param oldResource the old resource name
+     * @param newResource the new resource name
      * @throws RoleManagerException
      */
-    void updateRole( String templateId, String oldResource, String newResource )
+    void moveTemplatedRole( String templateId, String oldResource, String newResource )
         throws RoleManagerException;
 
 
diff --git a/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/processor/DefaultRoleModelProcessor.java b/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/processor/DefaultRoleModelProcessor.java
index 203bfc7..e0b4b65 100644
--- a/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/processor/DefaultRoleModelProcessor.java
+++ b/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/processor/DefaultRoleModelProcessor.java
@@ -196,6 +196,9 @@ public class DefaultRoleModelProcessor
                 try
                 {
                     Role role = rbacManager.createRole( roleProfile.getName() );
+                    role.setId( roleProfile.getId() );
+                    role.setModelId( roleProfile.getId() );
+                    role.setTemplateInstance( false );
                     role.setDescription( roleProfile.getDescription() );
                     role.setPermanent( roleProfile.isPermanent() );
                     role.setAssignable( roleProfile.isAssignable() );
diff --git a/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/template/DefaultRoleTemplateProcessor.java b/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/template/DefaultRoleTemplateProcessor.java
index 1bb0f6f..3c43333 100644
--- a/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/template/DefaultRoleTemplateProcessor.java
+++ b/redback-rbac/redback-rbac-role-manager/src/main/java/org/apache/archiva/redback/role/template/DefaultRoleTemplateProcessor.java
@@ -177,7 +177,8 @@ public class DefaultRoleTemplateProcessor
     private void processTemplate( RedbackRoleModel model, ModelTemplate template, String resource )
         throws RoleManagerException
     {
-        String templateName = template.getNamePrefix() + template.getDelimiter() + resource;
+        final String templateName = template.getNamePrefix() + template.getDelimiter() + resource;
+        final String roleId = template.getId( ) + "." + resource;
 
         List<Permission> permissions = processPermissions( model, template, resource );
 
@@ -197,6 +198,10 @@ public class DefaultRoleTemplateProcessor
             try
             {
                 Role role = rbacManager.createRole( templateName );
+                role.setId( roleId );
+                role.setModelId( template.getId() );
+                role.setResource( resource );
+                role.setTemplateInstance( true );
                 role.setDescription( template.getDescription() );
                 role.setPermanent( template.isPermanent() );
                 role.setAssignable( template.isAssignable() );
diff --git a/redback-rbac/redback-rbac-role-manager/src/test/java/org/apache/archiva/redback/role/AbstractRoleManagerTest.java b/redback-rbac/redback-rbac-role-manager/src/test/java/org/apache/archiva/redback/role/AbstractRoleManagerTest.java
index 2b31d9f..50b303a 100644
--- a/redback-rbac/redback-rbac-role-manager/src/test/java/org/apache/archiva/redback/role/AbstractRoleManagerTest.java
+++ b/redback-rbac/redback-rbac-role-manager/src/test/java/org/apache/archiva/redback/role/AbstractRoleManagerTest.java
@@ -81,7 +81,7 @@ public abstract class AbstractRoleManagerTest
         assertTrue( roleManager.templatedRoleExists( "test-template-2", "foo" ) );
         assertTrue( roleManager.templatedRoleExists( "test-template", "foo" ) );
 
-        roleManager.updateRole( "test-template-2", "foo", "bar" );
+        roleManager.moveTemplatedRole( "test-template-2", "foo", "bar" );
 
         assertFalse( roleManager.templatedRoleExists( "test-template-2", "foo" ) );
         // TODO: bug - assertFalse( roleManager.templatedRoleExists( "test-template", "foo" ) );
@@ -104,7 +104,7 @@ public abstract class AbstractRoleManagerTest
         roleManager.createTemplatedRole( "test-template-2", "cold" );
         roleManager.assignTemplatedRole( "test-template-2", "cold", principal );
 
-        roleManager.updateRole( "test-template-2", "cold", "frigid" );
+        roleManager.moveTemplatedRole( "test-template-2", "cold", "frigid" );
 
         assertTrue( roleManager.templatedRoleExists( "test-template-2", "frigid" ) );