In SPItemEventReceiver ItemAdded, how do I set change permission of item when contributor?

5.6k views Asked by At

OK. I am trying to write an event receiver to give a user full control of any file that they upload. I can get the code to work so long as I'm logged in as Administrator. The same code gets an System.UnauthorizedAccessException:> Access is denied. (Exception from HRESULT: x80070005E_ACCESSDENIED)) exception when I login as a contributor and upload a file.

I have tried a couple 'solutions' and various other things to solve the problem as seen in commented code below. From what I've read, it will be necessary to somehow recreate the object while privileges are elevated in order to have those privileges on the object in question. But neither of the methods is able to find the item. It seems the item is not yet in the list. Oh, and this is a Document Library.

    //Works as admin
    public override void ItemAdded(SPItemEventProperties properties)
    {
        base.ItemAdded(properties);//tried putting this at top and bottom of method, thinking perhaps this where the file get put in list.

        SPSecurity.RunWithElevatedPrivileges(delegate
        {
            using (var site = new SPSite(properties.SiteId))
            using (var web = site.OpenWeb(properties.RelativeWebUrl))
            {
                    ...

                    //works when admin
                    var item = properties.ListItem;

                    //attempt: by item url
                       //this does not work, file not found
                    var item = web.GetListItem(properties.ListItem.Url);

                    //attempt: by item ID
                      // this works
                    var list = web.Lists[properties.ListId]; 
                      //this does not
                    var item = list.GetItemById(properties.ListItemId); 


                    item.BreakRoleInheritance(true); //this get the access denied error
                    item.RoleAssignments.Add(GetRoleAssignment(web, item));

                    ...
            }
        }
        base.ItemAdded(properties);
    }




UPDATE


So, the solution that is currently working is:

        ...

        SPSecurity.RunWithElevatedPrivileges(delegate
        {
            using (var site = new SPSite(properties.SiteId))
            using (var web = site.OpenWeb(properties.RelativeWebUrl))
            {
                try
                {
                    properties.ListItem.File.CheckIn(String.Empty);
                    System.Threading.Thread.Sleep(1000);
                    var list = web.Lists[properties.ListId];
                    var item = list.Items[properties.ListItem.UniqueId];
                    item.BreakRoleInheritance(true);
                    item.RoleAssignments.Add(GetRoleAssignment(web, item));
                }
                catch (Exception e)
                {
                    LogError(e.ToString());
                }
                finally
                {
                    properties.ListItem.File.CheckOut();
                    ...
                }
            }
        });

        ...

I have some apprehension concerning the necessity of the timer, the idea for which I gleaned from elsewhere. From what I've seen, it appears that ItemAdded is fired asynchronously, and since the timer is necessary (I tried it without), it seems CheckIn is also asynchronous. I really don't know why it is behaving as such, but that is my hypothesis.

2

There are 2 answers

0
EvgK On BEST ANSWER

Possible, the file you are uploading is checked out by default, so even in RunwithElevatedPrevileges block you cannot retrieve its ListItem. Try do this:

properties.ListItem.File.CheckIn(String.Empty);

just before RunwithElevatedPrevileges block.

1
Madhur Ahuja On

It seems that your application pool account is not the site collection administrator. When you do RunwithElevatedPrevileges , it basically impersonates to application pool account. So make sure that you have that account's permission in place.