I often get the following question from administrators, “now that a user can have multiple permission sets in addition to their profile, how can I tell what permissions they have?”
It makes sense, after all: a user’s permissions determines their right to do almost anything in an org. For compliance and troubleshooting reasons, it’s important to be able to track down why a user has a certain access right and correct it if need be.
Summer ’12 introduces the ability to answer this question using the permission set API. We’ve created a new field on the PermissionSet SObject called IsOwnedByProfile. This field determines whether a permission set is a custom one or if it is parented by a profile. This is made possible because for every profile, there is one underlying permission set. That way, permissions layer equally across permission sets without having to treat a profile differently. In the setup user interface, you only see the profile but in the API, you can see both the profile and the underlying permission set.
As a result, running the following query in SOQL will return both permission sets you’ve created and permission sets parented by a profile:
SELECT Id,IsOwnedByProfile,Label FROM PermissionSet
By adding IsOwnedByProfile to the WHERE clause, you will quickly differentiate between permission sets you’ve created versus those parented by a profile:
SELECT Id,IsOwnedByProfile,Label FROM PermissionSet WHERE IsOwnedByProfile = TRUE
Once you have the hang of this, you can start to answer all sorts of questions about your users such as, “which users have Read on Accounts and why”:
SELECT Assignee.Name, PermissionSet.Id, PermissionSet.isOwnedByProfile, PermissionSet.Profile.Name, PermissionSet.Label FROM PermissionSetAssignment WHERE PermissionSetId IN (SELECT ParentId FROM ObjectPermissions WHERE SObjectType = 'Account' AND PermissionsRead = true)
You might need to answer questions about a specific user such as, “what are all of the Account fields where John Doe has at least Read access and why”
SELECT Id, SObjectType, PermissionsRead, Parent.label, Parent.IsOwnedByProfile FROM ObjectPermissions WHERE (ParentId IN (SELECT PermissionSetId FROM PermissionSetAssignment WHERE Assignee.Name = 'John Doe')) AND (PermissionsRead = true) AND (SobjectType = 'Account')
Using permission sets in this way, you can find out why a user has access to an apex page, class or a particular user, object, or field permission, regardless of whether it’s through their profile or permission set.
These SOQL queries are great if you have one off questions about your user’s permissions. If you have a more regular need to query user’s permissions, think about creating a Visualforce page with an Apex controller that uses these queries to find out what your users can do and why.