Second Life of a Hungarian SharePoint Geek

March 1, 2014

How to check from code if a SharePoint Site / List has Content with Unique Permissions

Filed under: Permissions, Reflection, Security, SP 2010 — Tags: , , , — Peter Holpar @ 00:25

Assume you have a SharePoint site / list, and you would like to know if it has any content configured with unique permissions, that means any content (list / folder / list item) that does not inherit the permissions configured for the current site / list. It is easy to see this information from the user interface, when you check the permissions configured for the given site / list object through the page _layouts/user.aspx.

image

But how could we get the same information if we need to access it from code? One logical solution would be to iterate through all subsites / lists / folders / items, and see if any of them has its HasUniqueRoleAssignments property (inherited from the SPSecurableObject base class that implements the obsolete ISecurableObject interface) with value true. Although this approach should definitely do the job, it might be not the most effective and simplest solution. Let’s see instead, how it is implemented in the UserRoles class (namespace and assembly Microsoft.SharePoint.ApplicationPages) that is the class behind the user.aspx page.
The base class of the UserRoles is the CBaseAclPage class, that has a public field called m_Securable of type SPSecurableObject. This field contains the related SPWeb / SPList / SPItem object, all of these are derived classes of the SPSecurableObject class. The highlighted message on the above screenshot comes from the SetExceptionStatus() method (declared as private) of the UserRoles class. In this method we check first if we have an SPWeb or an SPList in the m_Securable field.

If the m_Securable is an SPWeb, we call its internal HasListsWithUniquePermissions() method. If the m_Securable is an SPList, we check its internal HasUniqueScopes property. As the objects of type SPItem (the third derived type of SPSecurableObject) may not have any child objects, it has no sense to check for content with unique permissions in this case.

Note: Well, I did not tell the truth in my previous sentence. We might have folders (also SPItem objects, see Folder property of the SPListItem, inherited from SPItem) in our lists, that contain items with unique permissions. In this case this fact should be indicated on the UI, but I found, that the user.aspx page / UserRoles class ignores this fact. We do as well in this post, and restrict our scope to sites and lists.

Note 2: I’ve found that the Permissions page simply ignores subsites with unique permission. Should you have a site with a subsite, and the subsite configured with its own permission set, the Permissions page of the parent site does not indicate this. This seems to be a bug, but we follow this buggy behavior in this post. Instead of this, we could call the public GetWebsAndListsWithUniquePermissions() method of SPWeb and check the count of items returned by the method. If the count is greater than one, the site has content with unique permissions. This approach works, even if not the subsite itself, but one of its list has unique permissions. But wait a minute! A new problem arose… This method returns subsites / lists that had formerly unique permissions, but later this unique permission set was removed by inheriting back the parent permissions. What to do now? The GetWebsAndListsWithUniquePermissions() method returns a collection of SPWebListInfo objects, and this type has a property called HasUniqueRoleAssignments. It means, a viable alternative of the buggy out-of-the-box solution might be:

bool hasUniquePerms = web.GetWebsAndListsWithUniquePermissions().Any(p => p.HasUniqueRoleAssignments);

But back to the original behavior… It’s quite easy to implement the same logic in our own code by accessing the above mentioned members via reflection.

I’ve created a few extension methods to achieve this goal:

  1. internal static class Extensions
  2. {
  3.     internal static bool HasSubItemWithUniquePermissions(this SPSecurableObject securable)
  4.     {
  5.         bool result = false;
  6.  
  7.         if (securable != null)
  8.         {
  9.             if (securable is SPWeb)
  10.             {
  11.                 result = (((SPWeb)securable).HasListsWithUniquePermissions());
  12.             }
  13.             else if (securable is SPList)
  14.             {
  15.                 result = ((SPList)securable).HasUniqueScopes();
  16.             }
  17.         }
  18.  
  19.         return result;
  20.     }
  21.  
  22.     internal static bool HasListsWithUniquePermissions(this SPWeb web)
  23.     {
  24.         bool result = false;
  25.  
  26.         if (web != null)
  27.         {
  28.             Type webType = typeof(SPWeb);
  29.             MethodInfo mi_HasListsWithUniquePermissions = webType.GetMethod("HasListsWithUniquePermissions", BindingFlags.NonPublic | BindingFlags.Instance);
  30.             result = (bool)mi_HasListsWithUniquePermissions.Invoke(web, new object[] { });
  31.         }
  32.  
  33.         return result;
  34.     }
  35.  
  36.     internal static bool HasUniqueScopes(this SPList list)
  37.     {
  38.         bool result = false;
  39.  
  40.         if (list != null)
  41.         {
  42.             Type listType = typeof(SPList);
  43.             PropertyInfo pi_HasUniqueScopes = listType.GetProperty("HasUniqueScopes", BindingFlags.NonPublic | BindingFlags.Instance);
  44.             result = (bool)pi_HasUniqueScopes.GetValue(list, new object[] { });
  45.         }
  46.  
  47.         return result;
  48.     }     
  49. }

Having this methods you can call the HasSubItemWithUniquePermissions method on your SPWeb / SPList instances (or even in case of SPItem as well, although in this case you will always receive a value of false), and check, if these object have any content with unique permissions.

Note: In my case I declared the helper methods as internal. However, if you wish to access the functionality from external assemblies as well, you might want to declare the HasSubItemWithUniquePermissions method (and the Extensions class itself) as public.

I will demonstrate the usage of these methods in a sample application in an upcoming post (see here).

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: