0

I've seen this question a couple times, but yet to find a scenario or answer which helps me.

I am building up a cross-site navigation menu, and when building the menu I look at each site and want to return the ones which the user has permission to.

So now for a specific site, my user has been revoked access to, and I get this page...

enter image description here

In my code, I have this check...

SPUserToken adminToken = SPContext.Current.Web.AllUsers["SHAREPOINT\\System"].UserToken;
SPUser currentUser = SPContext.Current.Site.RootWeb.CurrentUser;

SPSiteCollection siteCollections = SPContext.Current.Site.WebApplication.Sites;

foreach (SPSite site in siteCollections)
{
    using (SPWeb oWebsite = new SPSite(site.Url, adminToken).OpenWeb())
    {
        SPWebCollection collWebsites = oWebsite.Webs;

        foreach (SPWeb subSite in collWebsites)
        {
            if (subSite.DoesUserHavePermissions(currentUser.LoginName, SPBasePermissions.Open))
            {
                SiteMapNode knowledgeShareChildNode = new SiteMapNode(this, "knowledgeShare", subSite.Url, subSite.Title);
                knowledgeShareSubMenu.Add(knowledgeShareChildNode);
            }

            subSite.Close();
        }
    }
}

but despite that, the 'DoesUserHavePermissions' returns true

enter image description here

This previous question appears to address the same issue, but there is no solution that was provided which helps me.

https://stackoverflow.com/questions/4188210/how-to-check-if-a-user-has-permssion-to-a-sharepoint-site-collection

Is there any other way that I can check for permission access to a site?

Not sure what else to try (cant use 'Groups' of the user, since we allow 'Everyone' read access, with the few exceptions as trying to illustrate in this case)

Thanks!


As suggested below to rely on searching using a Content Class of 'STS_Site' which should have security trimming built in, when I tried to search for STS_Sites using my user, I was not expecting to then see sites that I dont have access to return in the results, but as seen below, they are still returning.. :(

enter image description here

1

I know you'll be disappointed by my answer since it won't provide exatly what you want, but here it is:
Looping through all site collections/sub-sites in the context of a Web part is definitely not a good option. This will be very resources-consumming (especially in the way you do it, where you forget to close a number of objects, and open unecessary others).
The best approach would definitely be to request the search engine, with a request like contentclass:STS_Web. Search is security-trimmer by default, and much more performant.
Here's a sample code. The end result is a dictionary result containing for all root sites and sub-sites the current user has access to (in the limit of 500 entries -500 is a very high limit for the search, but still much more performant than opening 500 SPWeb and their parent SPSite!):

    string searchQuery = "(contentclass:\"STS_Site\" OR contentclass:\"STS_Web\")";

    Dictionary<string, string> result = new Dictionary<string, string>();

    // We prepare the search
    KeywordQuery keywordQuery = new KeywordQuery(SPContext.Current.Site);
    keywordQuery.QueryText = searchQuery;
    keywordQuery.RowLimit = 500;
    keywordQuery.TrimDuplicates = false;
    SearchExecutor searchExecutor = new SearchExecutor();

    // We trigger the search
    ResultTableCollection searchResult = searchExecutor.ExecuteQuery(keywordQuery);

    // We get the result table
    DataTable resultsTable = searchResult.Filter("TableType", KnownTableTypes.RelevantResults).First().Table;

    // Each row is a result with a Path and a Title: we add an entry in the dictionary
    foreach (DataRow row in resultsTable.Rows)
    {
        if (row["Path"] != null)
        {
            string siteUrl = row["Path"].ToString().TrimEnd('/').ToLower();
            result[siteUrl] = (row["Title"] != null) ? row["Title"].ToString() : "unknown title";
        }
    }
  • Thanks @Evariste, and appreciate the comments on the the efficiency of the code. I like your idea of using something like the search engine as a different approach, just entirely sure where to start in replicating what ive done using that approach? In other words, how to effectively get the list of sites the user has access to reliably. Going to do some digging now on it, but if youre familiar with an approach off the top of your head, it would be appreciated. :) Thanks! – Simon Oct 15 '15 at 15:25
  • Edited my answer to include a sample code. – Evariste Oct 15 '15 at 16:48
  • Thanks Evariste for the help. So i tried your code, and a couple of variations of it, but I cant seem to get it to work as I expect it to.. I attached a screenshot in my original post showing that when I search the STS_Site content type from the front end, I am still seeing results of sites that I dont have access to. When you mentioned leveraging search it should have security trimming built in, but this doesnt seem to be the case, or is it? Thanks again! – Simon Oct 16 '15 at 7:17
  • Search is definitely security-trimmed. If you run the code I posted in the context of a Web part, by using the contextual SPSite object, unless there's a huge bug in SP, you should not get any SP result the user can't access... Can you try with contentclass:"STS_Site" instead of STS_Site? Do you surely crawl your SP content as an SP site and not as a simple Web site? – Evariste Oct 16 '15 at 7:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.