In some code I’m working on, I need to check if the user who created the request has “ManageWeb” rights, but I need to ensure that any web underneath does not.
Since where I’m checking the users effective rights is some time after the user requested the action (In a different assembly not running under the webs context), I store the SPUserToken of the user along with the requesting zone so that I can open that same web back up, within that user’s context from the zone they made the request from (To check for Policy overrides, etc).
The SPSite object has a constructor where you can pass in the SPUserToken and the Zone and open up the Site and web from that users context when they visited the site. I then call DoesUserHavePermissions() to validate that the user does in fact have a specific right. Very cool stuff!.
For example:
// Some code in a galaxy far, far away
int theSavedZone = (int)Microsoft.SharePoint.SPContext.Current.Site.Zone;
Guid theGuidOfTheSite = Microsoft.SharePoint.SPContext.Site.ID;
theSPUserToken = Microsoft.SharePoint.SPContext.Current.Web.CurrentUser.UserToken;
Guid theGuidOfTheWeb = Microsoft.SharePoint.SPContext.Web.ID
// Code in a different assembly somewhere outside of the WebApp.
SPSite site = new Microsoft.SharePoint.SPSite(theGuidOfTheSite, theSavedZone, theSPUserToken);
// Important call here!
site.CatchAccessDeniedException = false;
SPWeb web = site.OpenWeb(theGuidOfTheWeb);
if(web.DoesUserHavePermissions(Microsoft.SharePoint.SPBasePermissions.ManageWeb))
rockin = true;
So let’s pretend that the web in question DOES in fact allow the user to manage the web, thus rockin == true.
Now, a subweb from this web does not, so you would think you could do something like this:
foreach(subweb in web.Webs)
{
if(subweb.DoesUserHavePermissions(Microsoft.SharePoint.SPBasePermissions.ManageWeb))
rockin = true;
}
But I have found, that even though the subweb does in fact not allow the user to manage it, this call still evaluates true.
The workaround (which was painful and not very efficient) was to re-open yet another site object under that users context then call the sites OpenWeb() method with the guid of the subweb as we did on the parent, then DoesUserHavePermissions() worked reliably.
foreach(subweb in web.Webs)
{
SPSite localsite = null;
SPWeb localweb = null;
try
{
Guid web_guid = subweb.ID
Guid sc_guid = subweb.Site.ID;
localsite = new Microsoft.SharePoint.SPSite(theGuidOfTheSite, theSavedZone, theSPUserToken);
// Important call here!
localsite.CatchAccessDeniedException = false;
localweb = site.OpenWeb(theGuidOfTheWeb);
if( localweb.DoesUserHavePermissions(Microsoft.SharePoint.SPBasePermissions.ManageWeb))
rockin = true;
}
catch(Exception e)
{
// Handle the exception
}
finally
{
// Clean up those pesky dangling unmanged resources.
if(localweb != null)
localweb.Dispose();
if(localsite != null)
localsite.Dispose();
}
}
Not as efficient as just enumerating the subwebs and “Assuming” that DoesUserHavePermissiosn() is going to work reliably, but this worked.
HTH
– Keith
OR you can maybe do SPWeb.GetSubWebsForCurrentUser()