Binding on ISecurableObject

I have a static method static void Bind(ISecurableObject iSecurableObject, SPRoleDefinition roleDefinition, SPPrincipal principal) I use whenever I want to add a new permission to either SPWeb, SPList, SPListItem objects.

Binding permissions works something like this:
You take an object that has unique role assignments and add to the role assignments of this object a tuple of (SPRoleDefinition, SPPrincipal), where a role definition is a pre-defined permissions mask like read, write or administrate and a principal is the super type of group and user.
Every ISecurableObject contains a collection of SPRoleAssignments. This allows more than one SPRoleDefinition per SPPrincipal. The SPRoleDefinitions can be merged together. This works because of the permissions mask (can be realized as bit mask, every 1 overwrites a 0 (logical OR).

My function works like this:

public static void Bind(ISecurableObject iSecurableObject, 
                        SPRoleDefinition roleDefinition, 
                        SPPrincipal principal)
{
    if(!iSecurableObject.HasUniqueRoleAssignments)
    {
        BreakInheritance(iSecurableObject);
    }
    SPRoleAssignment assignee = new SPRoleAssignment(principal);
    assignee.RoleDefinitionBindings.Add(roleDefinition);
    try
    {
        iSecurableObject.RoleAssignments.Remove(principal);           
    } 
    catch(Exception) {}
    iSecurableObject.RoleAssignments.Add(assignee);
}

Whoever finds the bug is pretty damn good. 🙂 (in my opinion).

The problem is that if you have a list, and it has items with unique permission sets, the different principals have an automatic limited permissions. If you have more than one item and the principal has permissions on both items, the permission on the prior item is deleted, because the role assignment is removed. So get the role assignment if it exists, then add the role definition to the existing role assignment.

This would look like this:

public static void Bind(ISecurableObject iSecurableObject, 
                        SPRoleDefinition roleDefinition, 
                        SPPrincipal principal)
{
    if(!iSecurableObject.HasUniqueRoleAssignments)
    {
        BreakInheritance(iSecurableObject);
    }
    SPRoleAssignment assignee;
    try
    {
        assignee = iSecurableObject.RoleAssignments.
                   GetAssignmentByPrincipal(principal);
        if(!assignee.RoleDefinitionBindings.Contains(roleDefinition))
        {
            assignee.RoleDefinitionBindings.Add(roleDefinition)    
        }
    } 
    catch(Exception) 
    {
        assignee = new SPRoleAssignment(principal);
        assignee.RoleDefinitionsBindings.Add(roleDefinition);
        iSecurableObject.RoleAssignments.Add(assignee);
    }
}

The try-catch-block is needed because the SPRoleAssignmentCollection throws an argument exception if there is no assignment of this principal in the collection.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: