Creating Item Level Security for an Event Receiver based upon metadata (Part 2)

After completing the process of creating a MOSS configuration list and the SetConfiguration method in the event receiver (Creating Item Level Security for an Event Receiver based upon metadata (Part 1)), it’s now time to create the methods for actually implementing the security for the individual documents.

SetSecurityForItem:

This method will set the applicable security for the document. For my purposes, I added a boolean field in the document library called ChangeSecurity that can be checked if different security needs to be applied.  Once this is done,  we need to call the method BreakRoleInheritance(false) so that it will not copy down the permissions from the library.  I did find when you call the ItemUpdated method, that you need to remove all inherited roles to be able to apply the correct assignment (See line 23). Therefore, one of the parameters passed into the SetSecuritForItem method requires the type of method being called (“ItemAdded”, “ItemUpdated”, etc…) At this point, we need to set the SPRoleDefinitionCollection (I chose to utilize caching in this instance again).  To obtain the role definitons, the SPWeb parameter is called. Following this, a new array of type SPRoleDefinition is created passing in the roleType from the custom list. Last portion of this method is to iterate through the SPFieldUserValue to apply the permission to the document.

   1: #region SetSecurityForItem
   2:        // This function sets the Item Level Security for the document
   3:        private void SetSecurityForItem(SPItemEventProperties properties, SPWeb spWebSet, string methodType)
   4:        {
   5:            SPFieldUserValueCollection sharePointGroups;
   6:            SPList spList = properties.ListItem.ParentList;
   7:            SPListItem docItem = properties.ListItem;
   8:  
   9:            bool isChangeSecurity = (bool)docItem["ChangeSecurity"];
  10:  
  11:            if (isChangeSecurity)
  12:            {
  13:                sharePointGroups = group2;
  14:            }
  15:            else
  16:            {
  17:                sharePointGroups = group1;
  18:            }
  19:            //Break the Inheritance to assign new role definition to the group
  20:            docItem.BreakRoleInheritance(false);
  21:  
  22:            //Remove the previous RoleAssignment if this is an update
  23:            if (methodType == "ItemUpdated")
  24:            {
  25:                //remove all the inherited roles  
  26:                for (int i = docItem.RoleAssignments.Count - 1; i >= 0; --i)
  27:                {
  28:                    docItem.RoleAssignments.Remove(i);
  29:                }
  30:            }
  31:            // Get Role Definitions
  32:            SPRoleDefinitionCollection roleDefinitions = HttpRuntime.Cache.Get("WebRoleDefinitions") as SPRoleDefinitionCollection;
  33:            if (roleDefinitions == null)
  34:            {
  35:                roleDefinitions = spWebSet.RoleDefinitions;
  36:                HttpRuntime.Cache.Insert("WebRoleDefinitions", roleDefinitions);
  37:            }
  38:  
  39:            SPRoleDefinition[] rolesToApply = new SPRoleDefinition[1] { roleDefinitions[roleType] };
  40:  
  41:            foreach (SPFieldUserValue fuv in sharePointGroups)
  42:            {
  43:                addPermissionToListItem(properties.ListItem.Web, properties.ListItem, fuv, rolesToApply);
  44:            }
  45:  
  46:        }
  47:        #endregion

addPermissionToListItem is called in SetSecurityForItem which I will go into detail below:

addPermissiontoListItem:

With this method, it allows you to programmatically add security to a list item by the means of iterating through the values of a SharePoint User or Group column, including support for passing in a list of SPRoleDefinition items to grant to the security item. SPPrincipal represents either a user or group that will be assigned permissions.  Once we distinguish the type of SPPrincipal, a new SPRoleAssignment is created and the binding information is then iterated through and added to the role assignment. Finally, the group’s (or user’s) role assignment is then added to the list item. One thing to note about this method is that if the field user value is a User, a lookup is performed to obtain the SPPrincipal value (line 21)

   1: #region addPermissionToListItem
   2:        private void addPermissionToListItem(SPWeb SharePointWeb, SPListItem ListItemToAddTo, SPFieldUserValue UserOrGroupToAdd, params SPRoleDefinition[] RolesToGrant)
   3:        {
   4:            if (SharePointWeb != null && ListItemToAddTo != null && UserOrGroupToAdd != null && RolesToGrant != null && RolesToGrant.Length > 0)
   5:            {
   6:                SPPrincipal newItemToAdd = null;
   7:  
   8:                bool isUser = false;
   9:                try
  10:                {
  11:                    if (UserOrGroupToAdd.User != null)
  12:                    {
  13:                        isUser = true;
  14:                        newItemToAdd = UserOrGroupToAdd.User as SPPrincipal;
  15:                    }
  16:                }
  17:                catch { }
  18:  
  19:                if (!isUser)
  20:                {
  21:                    newItemToAdd = SharePointWeb.SiteGroups.GetByID(UserOrGroupToAdd.LookupId) as SPPrincipal;
  22:                }
  23:  
  24:                if (newItemToAdd != null)
  25:                {
  26:                    //Create a new assignment for the new group
  27:                    SPRoleAssignment newRoleAssignmentToAdd = new SPRoleAssignment(newItemToAdd);
  28:  
  29:                    //Get the role definitions binding collection for the new assignment
  30:                    foreach (SPRoleDefinition roleDefinition in RolesToGrant)
  31:                    {
  32:                        newRoleAssignmentToAdd.RoleDefinitionBindings.Add(roleDefinition);
  33:                    }
  34:  
  35:                    // Add Group
  36:                    ListItemToAddTo.RoleAssignments.Add(newRoleAssignmentToAdd);
  37:                }
  38:            }
  39:        }
  40:        #endregion

Final Step:

Create your overload methods for ItemAdded and ItemUpdated inheriting from the SPItemEventProperties. Make sure to call the methods above and also set the SPWeb value.

   1: #region ItemAdded
   2:        public override void ItemAdded(SPItemEventProperties properties)
   3:        {
   4:            base.ItemAdded(properties);
   5:  
   6:            if (properties.ListItem != null)
   7:            {
   8:                SPWeb spWeb = properties.ListItem.Web;
   9:  
  10:                SetConfiguration(spWeb, properties.ListTitle);
  11:  
  12:                if (applySecurity)
  13:                {
  14:                    SetSecurityForItem(properties, spWeb, "ItemAdded");
  15:                }
  16:            }
  17:        }
  18:        #endregion

Finally, build your project and deploy as a feature. That’s a brief overview of how to apply item level security based upon a metadata value.

Leave a Reply

Your email address will not be published. Required fields are marked *