Changing Item-level permissions in a Sharepoint List (WSS 3.0) with Elevated Privileges

Most blogs, books, articles, etc... provide some nice sample code, but they all assume that the user is logged on to Sharepoint as a Site Admin or someone with "Full Control" privileges. :-) 

What if you need to do something to the currently logged on user (which is NOT a Site Admin with Full Control) that requires elevated permissions... such as changing the user's item-level permission on a document they just added to the List.

Your knee jerk reaction is to steal a commonly published workaround for running code with elevated permissions by using...

SPSecurity.RunWithEleveatedPrivilege(delegate(){....//add your elevated privileged code here... });

The problem is that you have just changed the user context to Sharepoint\System, but you need it to be the actual logged on Domain\UserName, so you can change/lookup/remove/add/etc... that particular user's Group/Role Assignment affiliations and/or permissions.

So here is some sample code (that does NOT assume the logged on user has "Full Control" permissions already, although its ok if they do), that overrides the ItemAdded event handler and does some work requiring elevated permissions, but with the actual user context instead of Sharepoint\System.  It first checks if the user is in a particular Group, then based on that will remove their Group affiliations, and ultimately change their permissions ONLY on the file that they just added to the Document Library (this same code example applies to any Sharepoint List).  Note that I added a LogEvent method for basic debugging, but as a best practice I would use the Sharepoint Tracing log.

public override void ItemAdded(SPItemEventProperties properties){    this.DisableEventFiring();    base.ItemAdded(properties);

    SPSecurity.RunWithElevatedPrivileges(delegate()    {        using (SPSite _site = new SPSite(properties.WebUrl))        {            using (SPWeb _web = _site.OpenWeb(properties.RelativeWebUrl))            {

                SPUserToken userToken = _web.AllUsers[properties.UserLoginName].UserToken;                if (bIsInGroup(properties.WebUrl, properties.RelativeWebUrl, userToken, "Nuckolls University Professors") == false)                {                    LogEvent("================Changing Permissions==============");                    SPListItem _item = _web.Lists[properties.ListId].GetItemById(properties.ListItemId);

                    _item.BreakRoleInheritance(true);

                    SPRoleAssignmentCollection sr = _item.RoleAssignments;                    for (int i = sr.Count - 1; i > -1; i--)                    {                        sr.Remove(i);                    }                    LogEvent("=================Removed All Roles=================");                    SPUserCollection users = _web.SiteUsers;                    SPUser student = users[properties.UserLoginName];

                    SPRoleDefinition readerRoleDefinition = _web.RoleDefinitions.GetByType(SPRoleType.Reader);                    SPRoleAssignment studentRoleAssignment = new SPRoleAssignment(student as SPPrincipal);                    studentRoleAssignment.RoleDefinitionBindings.Add(readerRoleDefinition);                    _item.RoleAssignments.Add(studentRoleAssignment);                    LogEvent("================Permissions Changes================");                }                else                {                    LogEvent("This user is in the 'Nuckolls University Professors' group");                }                    _web.Dispose();                }                _site.Dispose();            }        });    this.EnableEventFiring();}

private bool bIsInGroup(string siteCollURL, string siteRelativeURL, SPUserToken userToken, string strGroupName){    try    {        LogEvent("executed bIsInGroup");            //Since we need to get site information in context of the "User" (ie. Domain\Steve")            //instead of the user with elevated previledges (ie. Sharepoint\System), we are             //creating a new Site object with the "UserToken" and evaluating the "User" with            //a particular Sharepoint group.            using (SPSite contextSiteColl = new SPSite(siteCollURL, userToken))            {                using (SPWeb contextSite = contextSiteColl.OpenWeb(siteRelativeURL))                {                    SPGroup userGroup = contextSite.Groups[strGroupName];                    if (userGroup != null)                    {                        LogEvent(String.Format("Is user in group = {0}", userGroup.ContainsCurrentUser.ToString()));                        if (!userGroup.ContainsCurrentUser)                        {                            return false;                        }                        else                        {                            return true;                        }                    }                    LogEvent("userGroup = null");                    return false;                }            }    }    catch (Exception exception)    {        LogEvent("Error checking if user is in a particular group: " + exception.Message.ToString());    }    return false;}

private void ChangeItemLevelPermissions(string user){    LogEvent("We should change this user's permission because they are NOT a professor: " + user);}

private void LogEvent(string debugMsg){    StreamWriter sw = File.AppendText(@"C:\HomeworkListLog.txt");    StringBuilder sb = new StringBuilder();    sb.AppendFormat("[{0}] {1}", DateTime.Now.ToString(), debugMsg);    sw.WriteLine(sb.ToString());    sw.Close();}

 

I hope this will save you time!  And if you've struggling with this for a while, as many others have, then I suggest you should bookmark this blog and get some sleep.  :-)