SharePoint – Create unique permissions on document check in
If you have a metadata-oriented structure in you document libraries, you might want to use unique permissions for each document.
This is NOT a good choice if you use folders. It will create a huge permissions matrix.
I have implemented this at my customer and I haven’t noticed any noticeable performance issues.
Let’s say you create a choice field called “Security class” with 4 choices, “Base, low, medium, high” and you want this to control the permissions for the current document.
- Base – Base permission, keep inheritance, every one can contribute. <– Default value for the field.
- Low – Everyone can read, members can contribute, owners and created by has full control.
- Medium – Members can read, no contributors, owners and created by has full control.
- High – No readers, no contributors, Owners and created by has full control.
So basically, in your editform.aspx you have a drop-down with these 4 options.
Implementation
First, create a class that will handle the permissions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
public static class PermissionsHandler { public static void SetPermissions(SPWeb web, SPListItem listItem) { if (listItem.Fields.ContainsField("Security class")) { string permissionClass = (string)listItem["Security class"]; if (!string.IsNullOrEmpty(permissionClass) && permissionClass != "Base") { //Define the roles SPRoleDefinition readRole = web.RoleDefinitions.GetByType(SPRoleType.Reader); SPRoleDefinition contributeRole = web.RoleDefinitions.GetByType(SPRoleType.Contributor); SPRoleDefinition ownerRole = web.RoleDefinitions.GetByType(SPRoleType.Administrator); //Get the groups. These are the groups that you have defined for your site. SPGroup visitorsGroup = web.Groups["Visitors"]; SPGroup membersGroup = web.Groups["Members"]; SPGroup onwersGroup = web.Groups["Owners"]; //Create the roleassignments SPRoleAssignment visitorsAssignment = new SPRoleAssignment(visitorsGroup); SPRoleAssignment membersAssignment = new SPRoleAssignment(membersGroup); SPRoleAssignment ownersAssignment = new SPRoleAssignment(onwersGroup); //Clear permissions listItem.ClearItemPermissions(); switch (permissionClass) { case "Low": //Add visitors as readers visitorsAssignment.RoleDefinitionBindings.Add(readRole); listItem.RoleAssignments.Add(visitorsAssignment); //add members as contributors membersAssignment.RoleDefinitionBindings.Add(contributeRole); listItem.RoleAssignments.Add(membersAssignment); break; case "Medium": //add members as readers visitorsAssignment.RoleDefinitionBindings.Add(readRole); listItem.RoleAssignments.Add(membersAssignment); break; } //Always add owners as full control ownersAssignment.RoleDefinitionBindings.Add(ownerRole); listItem.RoleAssignments.Add(ownersAssignment); //Fetch the creator as an SPUser //Add the creator as full control SPUser creator = (listItem.ParentList.Fields.GetField("Created by") .GetFieldValue(listItem["Created by"].ToString()) as SPFieldUserValue).User; SPRoleAssignment creatorAssignment = new SPRoleAssignment(creator); creatorAssignment.RoleDefinitionBindings.Add(ownerRole); listItem.RoleAssignments.Add(creatorAssignment); } } } private static void ClearItemPermissions(this SPListItem item) { if (!item.HasUniqueRoleAssignments) { item.BreakRoleInheritance(false); } for (int i = item.RoleAssignments.Count - 1; i >= 0; i--) { item.RoleAssignments.Remove(i); } } } |
Then you will have to create an Event Receiver and override ItemCheckedIn.
Let the base check in the item first or you might have a permissions conflict.
You have to elevate the privileges or you will loose your permissions when the permissions are cleared. Do not use the SPListItem from the event properties, it’s not elevated. You need to get the SPListItem from the elevated SPWeb. Call the permissionshandler with you elevated objects.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public override void ItemCheckedIn(SPItemEventProperties properties) { base.ItemCheckedIn(properties); SPSecurity.RunWithElevatedPrivileges(()=> { using (SPSite site = new SPSite(properties.SiteId)) { using (SPWeb web = site.OpenWeb()) { SPListItem item = web.GetListItem(string.Format("{0}/{1}", web.ServerRelativeUrl, properties.ListItem.Url)); PermissionsHandler.SetPermissions(web, item); } } }); } |
By setting permissions this way you will allow users to easily change permissions in a controlled way.