Thursday, February 11, 2010

SharePoint BreakRoleInheritance() and ResetRoleInheritance() code sample

Here is some sample code that shows how to use the SPListItem.BreakRoleInheritance() and SPListItem.ResetRoleInheritance() methods to implement Item Level Permissions and Restore List Level Permissions respectively. I implemented these methods in Event Handler code that was attached to a SharePoint Document Library.


using System;
using System.Web;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebControls;

namespace KiranK.SharePointSite.EventHandlers
{
public class DownloadManager : SPItemEventReceiver
{
public override void ItemAdding(SPItemEventProperties properties)
{

try
{
this.DisableEventFiring();

//Get Security Level and Select Users/Groups values
string strSecLevel = properties.AfterProperties["Security_x0020_Level"].ToString().Trim();
string strUserOrGroups = properties.AfterProperties["Select_x0020_Users_x0020_or_x002"].ToString().Trim();

//If Specific User is selected, but Users/Groups is blank, we need to display an error message and prevent saving of the Item.
if (strSecLevel == "Specific User" & (strUserOrGroups == "" | strUserOrGroups == string.Empty))
{
properties.ErrorMessage = "The 'Select Users or Groups' field cannot be blank, if you select 'Specific User' as the Security Level for this Document." + "
" + "Please click on the Back button in the browser and select User(s) and/or Group(s).";
properties.Cancel = true;
}
}
catch (Exception ex)
{
throw ex;
}

finally
{
this.EnableEventFiring();
}


}

public override void ItemAdded(SPItemEventProperties properties)
{



try
{
//This prevents the Event Receiver from running twice
this.DisableEventFiring();

//Collect the values entered by the user in the newly created Item in the Download Manager List

//Retrieve the properties associated with the newly created Item in the Download Manager List here
SPListItem dwdMgrItem = properties.ListItem;

//Get the Security Level value selected here
string strSecLevel = dwdMgrItem["Security Level"].ToString().Trim();



//Check if Security Level = Specific User
//If True, then we need to call the function that breaks role inhertitance from the Parent List, and implements Item Level permissions
if (strSecLevel == "Specific User")
{

BreakRoleInheritance(properties);
}

}

catch (Exception ex)
{

throw ex;
}

finally
{
this.EnableEventFiring();
}


}

public void BreakRoleInheritance(SPItemEventProperties properties)
{

//Get the Users or Groups selected here
//Multiple Users are stored like this -> User or Group selected = 173;#John Doe;#175;#Jane Doe;#172;#John Pongo
//Single User is stored like this -> 173;#John Doe
//Multiple values are separated by semicolons
//string strUserGroupSelected = dwdMgrItem["Select Users or Groups"].ToString().Trim();


//Initialize a SPWeb and SPListItem objects
SPWeb elevatedWeb = null;
SPListItem elevatedListItem = null;

try
{

//Run this code block with Elevated Privileges
//This is because Site Users will NOT have FULL CONTROL in SharePoint
//They will have CONTRIBUTE access in SharePoint and this access level
//does not allow you to break role inheritance.
//However, SPSite and SPWeb objects obtained via the Run With Elevated Privileges method
//will allow these Users to perform this operation.
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//This will be a POST request. Call ValidateFormDigest to ensure that this is a valid update and not a cross-site scripting attack
//Refer: http://hristopavlov.wordpress.com/2008/05/21/what-you-need-to-know-about-allowunsafeupdates-part-2/
SPUtility.ValidateFormDigest();

//Get a handle to the SPSite object inside the Elevated code block
using (SPSite elevatedSite = new SPSite(properties.SiteId))
{

//Get a handle to the SPWeb object inside the Elevated code block
using (elevatedWeb = elevatedSite.OpenWeb())
{

//Get the following error if AllowUnsafeUpdates is NOT set to True
//Microsoft.SharePoint.SPException: The security validation for this page is invalid.
elevatedWeb.AllowUnsafeUpdates = true;

//Get a handle to the List Item using the elevated SPWeb object
elevatedListItem = elevatedWeb.GetListItem(properties.ListItem.Url);

//Get all the Users in the Web
//SPUserCollection users = elevatedWeb.AllUsers;
SPUserCollection users = elevatedWeb.SiteUsers;

//Get all the Cross-site Groups for the Site Collection
//SPGroupCollection groups = web.Groups;
SPGroupCollection groups = elevatedWeb.SiteGroups;

//Call BreakRoleInheritance. false indicates that current role assignments in the Parent List will NOT be copied to this Item.
elevatedListItem.BreakRoleInheritance(false);

//Update the List Item
elevatedListItem.Update();



//Call function that will set Item Level Permissions.The user or users will be assigned Contributor permissions to this Item
elevatedListItem = SetItemLevelPermissions(elevatedWeb, elevatedListItem, SPRoleType.Contributor, users, groups);

//Update the Item again
elevatedListItem.Update();

//Set AllowUnsafeUpdates back to false
elevatedWeb.AllowUnsafeUpdates = false;

} //using elevatedWeb
} //using elevateSite

}); //closing for SPSecurity.RunWithElevatedPrivileges


}
catch (Exception ex)
{

throw ex;
}

finally
{
//Dispose SPWeb object
if (elevatedWeb != null)
elevatedWeb.Dispose();

////Dispose SPSite object
//if (elevatedSite != null)
// elevatedSite.Dispose();
}

}

public SPListItem SetItemLevelPermissions(SPWeb setSPWeb, SPListItem setListItem, SPRoleType setRoleType, SPUserCollection users, SPGroupCollection groups)
{
try
{
//Create an ArrayList that will store the User or Group IDs
ArrayList alUserGroup = new ArrayList();

//Get the Users or Groups selected here
//Multiple Users are stored like this -> User or Group selected = 173;#John Doe;#175;#Jane Doe;#172;#John Pongo
//Single User is stored like this -> 173;#John Doe
//Multiple values are separated by semicolons
string strUserGroupSelected = setListItem["Select Users or Groups"].ToString().Trim();

//Split the multiple values and store them in an Array
string[] strArrUserGroup = Regex.Split(strUserGroupSelected, ";#");

//Iterate through the Array and store the User or Group IDs in the ArrayList
foreach (string strUserGroupValue in strArrUserGroup)
{
//Check if the value is a number
//If True, this is a User or Group ID
if (IsWholeNumber(strUserGroupValue))
{
//Add User or Group IDs to the ArrayList
alUserGroup.Add(Int32.Parse(strUserGroupValue));
}
}

//Set the Role Definition to Contribute here...
SPRoleDefinition roleDefinition = setSPWeb.RoleDefinitions.GetByType(setRoleType);

//Iterate through the ArrayList
//Get the User or Group ID
foreach (int intUserGroupID in alUserGroup)
{
//determine if ID is user or group
Boolean isGroup = false;
foreach (SPGroup testGroup in setSPWeb.SiteGroups)
{
if (testGroup.ID == intUserGroupID)
{
isGroup = true;
}
}
if (isGroup == false) //this is a User ID
{

SPUser userToAdd = users.GetByID(intUserGroupID);

SPRoleAssignment userRoleAssignment = new SPRoleAssignment(userToAdd);
userRoleAssignment.RoleDefinitionBindings.Add(roleDefinition);
setListItem.RoleAssignments.Add(userRoleAssignment);
}
else //this is a Group ID
{

SPGroup groupToAdd = groups.GetByID(intUserGroupID);

SPRoleAssignment groupRoleAssignment = new SPRoleAssignment(groupToAdd);
groupRoleAssignment.RoleDefinitionBindings.Add(roleDefinition);
setListItem.RoleAssignments.Add(groupRoleAssignment);
}
}

//Add 'SP Site Administrators' group to the Item Permissions List

SPGroup oSiteAdminGroup = setSPWeb.SiteGroups["SP Site Administrators"];
SPRoleAssignment siteAdminGroupRoleAssignment = new SPRoleAssignment(oSiteAdminGroup);
siteAdminGroupRoleAssignment.RoleDefinitionBindings.Add(roleDefinition);
setListItem.RoleAssignments.Add(siteAdminGroupRoleAssignment);

return setListItem;
}
catch (Exception ex)
{

throw ex;
}

finally
{
//Do nothing
}
}

public override void ItemUpdating(SPItemEventProperties properties)
{

try
{
this.DisableEventFiring();

//Get Security Level and Select Users/Groups values
string strSecLevel = properties.AfterProperties["Security_x0020_Level"].ToString().Trim();
string strUserOrGroups = properties.AfterProperties["Select_x0020_Users_x0020_or_x002"].ToString().Trim();

//If Specific User is selected, but Users/Groups is blank, we need to display an error message and prevent saving of the Item.
if (strSecLevel == "Specific User" & (strUserOrGroups == "" | strUserOrGroups == string.Empty))
{
properties.ErrorMessage = "The 'Select Users or Groups' field cannot be blank, if you select 'Specific User' as the Security Level for this Document." + "
" + "Please click on the Back button in the browser and select User(s) and/or Group(s).";
properties.Cancel = true;
}
}
catch (Exception ex)
{

throw ex;
}

finally
{
this.EnableEventFiring();
}

}

public override void ItemUpdated(SPItemEventProperties properties)
{



try
{
this.DisableEventFiring();
string strSecLevel = properties.AfterProperties["Security_x0020_Level"].ToString().Trim();

if (strSecLevel != "Specific User")
{

ResetRoleInheritance(properties);
}

}

catch (Exception ex)
{

throw ex;
}

finally
{
this.EnableEventFiring();
}

}

private void ResetRoleInheritance(SPItemEventProperties properties)
{
//Initialize a SPWeb and SPListItem objects
SPWeb elevatedWeb = null;
SPListItem elevatedListItem = null;

try
{

//Run this code block with Elevated Privileges
//This is because Site Users will NOT have FULL CONTROL in SharePoint
//They will have CONTRIBUTE access in SharePoint and this access level
//does not allow you to reset role inheritance.
//However, SPSite and SPWeb objects obtained via the Run With Elevated Privileges method
//will allow these Users to perform this operation.
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//This will be a POST request. Call ValidateFormDigest to ensure that this is a valid update and not a cross-site scripting attack
//Refer: http://hristopavlov.wordpress.com/2008/05/21/what-you-need-to-know-about-allowunsafeupdates-part-2/
SPUtility.ValidateFormDigest();

//Get a handle to the SPSite object inside the Elevated code block
using (SPSite elevatedSite = new SPSite(properties.SiteId))
{

//Get a handle to the SPWeb object inside the Elevated code block
using (elevatedWeb = elevatedSite.OpenWeb())
{

//Get the following error if AllowUnsafeUpdates is NOT set to True
//Microsoft.SharePoint.SPException: The security validation for this page is invalid.
elevatedWeb.AllowUnsafeUpdates = true;

//Get a handle to the List Item using the elevated SPWeb object
elevatedListItem = elevatedWeb.GetListItem(properties.ListItem.Url);

//Remove Users and Groups from the People Picker field in this Item
elevatedListItem["Select Users or Groups"] = string.Empty;

//Call ResetRoleInheritance.
//This will remove Item Level Permissions and restore List level Permissions.
//In other words, the Permissions assigned to the List will be inherited by the Item.
elevatedListItem.ResetRoleInheritance();

//Update the List Item
elevatedListItem.Update();

//Set AllowUnsafeUpdates back to false
elevatedWeb.AllowUnsafeUpdates = false;

} //using elevatedWeb
} //using elevateSite

}); //closing for SPSecurity.RunWithElevatedPrivileges



}

catch (Exception ex)
{

throw ex;
}

finally
{
//Dispose SPWeb object
if (elevatedWeb != null)
elevatedWeb.Dispose();

////Dispose SPSite object
//if (elevatedSite != null)
// elevatedSite.Dispose();
}
}



//This method checks if the string that is passed is a valid whole number or not
public bool IsWholeNumber(String strNumber)
{
Regex objNotWholePattern = new Regex("[^0-9]");
return !objNotWholePattern.IsMatch(strNumber);
}
}
}

No comments: