Saturday, 24 September 2011

SPSecurity.RunWithElevatedPrivileges Doesn't Work: The Pleasures and Sorrows of the Non-Admin User

I blogged the last time about deploying event handlers using features and components. So your event handler is sitting there, ready to fire. You update, add, or delete or whatever it is you want to do. Nothing happens. You have a look at the feature to check all is well. No typos? No copy-and-paste issues with the component name? Got the right list template ID? Instrumented your error code and recording nothing?

Then you look at the top right corner of your site and see the tell-tale message "Logged In As Serf Minion". You log out and log back in as "God of All Admins" and hey presto, everything works fine. Only problem being that you don't want every user in the damn system having admin privileges on this site or list or document library because - well you just don't. That way madness lies.

So what do you do?

Well I had this problem just a week or so ago. Since I am a novice, I did a bit of googling and came across the function SPSecurity.RunWithElevatedPrivileges. You pass in a delegate, which is a fancy word for an entire wodge of code, and all that code runs as if you're logged in as an admin. Hurrah, thought I, my problem is solved. And gentle reader, I took care to read the warnings. It is bad practice to instantiate your SPSite and SPWeb objects outside the RunWithElevatedPrivileges block. Why? Well, what is the point of creating the admin code block when you already have your site object instantiated as Serf Minion when firing the event handler? Bit of a waste of time that.

So what you're supposed to do is get your site Guid from your existing properties object and then create your site within the delegate block, treating the whole thing like a bubble. Thusly:

Guid siteID = properties.SiteID;
Guid webID = properties.ListItem.Web.ID;

SPSecurity.RunWithElevatedPrivileges(delegate() {
//create site
          using (SPSite site = new SPSite(siteID))
              using (SPWeb web = site.OpenWeb(webID))
                         //insert godly admin code here with no reference to properties object

So I tried that, fair readers, or something very similar. Guess what? My code, which had been failing for non-admin users, now failed for everybody. I tried everything in the book to make it work. I could not figure out what the hell I was doing wrong! Then a thought suddenly struck me: maybe this is just a load of crap. So I googled "Run With Elevated Privileges doesn't work" and came straight back with this link from a Mr Ishai Sagi and all I can say it, I wish to God I'd found it sooner. I googled further to find the code somebody had written to create an Impersonation class (Lesson no. 1 - NEVER code something before checking someone else has done it on the internet.) Replaced the settings with my own server settings, ran the thing and HEY PRESTO IT WORKED.

So lesson learned: always test as non-admin and keep in mind non-admin privileges when writing your event handler. And the hell with RunWithElevatedPrivileges where event handlers are concerned. Sorry Mr Microsoft guys, I just couldn't make it work ::sniff::

No comments:

Post a Comment