18

I was looking for a little help to find all users with a particular Custom Permission assigned to them, either via Profile or Permission Set.

6
  • Apart from Adrian's answer here is a good apex class example to look at : github.com/john-brock/Custom-Permissions/blob/master/classes/… Commented Aug 27, 2016 at 18:19
  • @MukeshVerma It's not entirely straightforward how to change direction when you get so many inner-joins involved. Interesting class though.
    – Adrian Larson
    Commented Aug 27, 2016 at 18:38
  • Yes @Adrian Larson I understand the complexity. May be it would be good to vote for this idea success.salesforce.com/ideaView?id=08730000000DiLXAA0 Commented Aug 27, 2016 at 18:48
  • @MukeshVerma I had found that class and was using it as a reference but was struggling to adapt it. Others may find it helpful; That's a good addition. Commented Aug 27, 2016 at 18:49
  • @MukeshVerma Both of those links are focused on permissions for a single user, which actually is not what is being asked here.
    – Adrian Larson
    Commented Aug 27, 2016 at 18:52

1 Answer 1

35

Update

Please note that for the running user, you can use the FeatureManagement class:

Boolean isEnabled = FeatureManagement.checkPermission('My_Permission_Api_Name');

Surprisingly, I don't think you can do it more simply than the below.

Execution

public static List<User> getUsersWithCustomPermission(String name)
{
    Set<Id> permissionSetIds = new Set<Id>();
    for (SetupEntityAccess access : [
        SELECT ParentId 
        FROM SetupEntityAccess 
        WHERE SetupEntityId IN (
            SELECT Id 
            FROM CustomPermission 
            WHERE DeveloperName = :name
        )
    ]) {
        permissionSetIds.add(access.ParentId);
    }
    return permissionSetIds.isEmpty() ? new List<User>() : [
        SELECT Username FROM User WHERE Id IN (
            SELECT AssigneeId FROM PermissionSetAssignment
            WHERE PermissionSetId IN :permissionSetIds
        )
    ];
}

Explanation

At the end of the day, you need to hit four separate tables to make this work.

  • CustomPermission
  • SetupEntityAccess
    (adds the CustomPermission to a PermissionSet)
  • PermissionSet
  • PermissionSetAssignment

You can reduce your queries consumed to two by using inner-joins.


EDIT

It was mentioned in the comments that you may want to filter for namespace. To do so, I would modify the above join on CustomPermission as below:

SELECT Id 
FROM CustomPermission 
WHERE DeveloperName = :name
AND NamespacePrefix = null

You could also use overloads at the method level:

public static List<User> getUsersWithCustomPermission(String name)
{
    return getUsersWithCustomPermission(name, null);
}
public static List<User> getUsersWithCustomPermission(String name, String namespacePrefix)
{
    // use modified queries
}
6
  • 1
    I was somewhere in the ball Park but was not quite getting the SOQL Correct. You did an excellent Job of laying out the procedure. Thank you Commented Aug 27, 2016 at 18:45
  • 1
    @Scott as to your comment in the edit history, the ternary is so you don't consume a second query when you know there will be no results.
    – Adrian Larson
    Commented May 24, 2017 at 13:37
  • @AdrianLarson Makes sense. Commented May 24, 2017 at 15:18
  • You should probably filter by namespace in this query, as well. Commented Aug 14, 2019 at 19:51
  • @CharlesKoppelman on which objects?
    – Adrian Larson
    Commented Aug 14, 2019 at 19:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .