The Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges is a useful method that can execute a delegate method that runs a subset of code in the context of an account with higher privileges than the current user.
Sample usage:
SPSecurity.RunWithElevatedPrivileges(delegate(){ // implementation details omitted});
Something you need to watch for, which is eluded to in the SDK is that you must create a new
SPSite object inside the delegate because
SPSite objects created outside do not have Full Control even when referenced inside the delegate. Now it’s not only the SPSite object that you need to concern yourself about. For instance if you have some custom code that run with Elevated Privileges and that code accepts a SPListItem as a parameter, then that SPListItem will have the same security as when it was created. This is to say that the RunWithElevatedPrivileges method does not increase the security for objects that already exist. You need to create the objects within the method for them to adopt the elevated privilege.
Take for example the following scenario; You have two folders in the same document libraries, one (Folder A) where users have the permissions to contribute with the other (Folder B) is locked down and only the system administrator can contribute, all other users only have read access. The use case is that, when a user sets the document approval status to approved and checks in the file the file will be moved from Folder A to Folder B. The issue arise where the user who executes the method does not have the correct privileges on Folder B to add the file. This is where RunWithElevatedPrivileges comes into play. The following shows an example a possible Move Document method:
This code will Error!
private void MoveDocument(SPItemEventProperties properties)
{
string targetDir = [PathToSharePointFolder];
SPList list = web.Lists[properties.ListId];
SPListItem item = list.GetItemById(properties.ListItemId);
SPFile file = item.File;
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(properties.SiteId))
{
using (SPWeb web = site.OpenWeb(properties.RelativeWebUrl))
{
file.MoveTo(targetDir + "/" + file.Name, true);
}
}
});
}
catch (Exception ex)
{
}
}
When you run this code in your ItemCheckedIn EventHandler you notice that you’re getting an unauthorised exception! What is causing this?
Well the culprit in this case is the SPFile object. As the file object is instantiated out side of the RunWithElevatedPrivileges method the file object has the security context of the user who performed the action. This user does not have sufficient privileges on folder B hence the error message.
To rectify the issue you can instantiate the file object within the RunWithElevatedPrivileges method as show below:
This code should execute successfully
private void MoveDocument(SPItemEventProperties properties)
{
string targetDir = [PathToSharePointFolder];
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPList list = web.Lists[properties.ListId];
SPListItem item = list.GetItemById(properties.ListItemId);
SPFile file = item.File;
using (SPSite site = new SPSite(properties.SiteId))
{
using (SPWeb web = site.OpenWeb(properties.RelativeWebUrl))
{
file.MoveTo(targetDir + "/" + file.Name, true);
}
}
});
}
catch (Exception ex)
{
}
}
So it is important to be aware of where SharePoint Object are created when using the RunWithElevatedPrivileges method and if you are experiencing a unauthorised error the chances are that a object is being created outside of the RunWithElevatedPrivileges method.
Note: The code in this article is for demonstration purposes and should not be used in any other context than what it is intended for.