06 April 2015

Skip Logic using Custom Permission

On my blog post last June, we discuss about using custom settings for skipping execution of triggers, validation rules and workflow rules. Today we can achieve the same logic using a feature Salesforce.com release last Summer 14.

But first, what is custom permission? Custom Permission allows us to extend a profile and custom permission access by allowing us to create our own "permission" attribute and can be optionally associated with a connected app. It's a simple yet powerful feature that can be use on a custom or generic application.

Below I created 3 custom permissions via Setup --> Develop --> Custom Permission.


Checking custom permission assignment in Apex Trigger requires querying the data from three setup objects called SetupEntityAccess, CustomPermission and PermissionSetAssignment. I have created a utility class that can be used to check if a user is assigned to any of the above custom permissions as below. The class cache the assignment in a permission set Id/DeveloperName and Boolean key/value pair where passing an Id or the custom permission developer name can return TRUE (if its assigned) or FALSE (if not assigned).



public class CustomPermissionUtil {
    private static Map<String,Boolean> permissionMap;
    
    public static Boolean hasCustomPermAccess(String devName){
        Boolean hasCustomPerm = false;
        if(permissionMap==null){
            refreshCache();
        }
        
        if(permissionMap.size()>0){
            if(permissionMap.containsKey(devName)){
                hasCustomPerm = permissionMap.get(devName);
            }
        }
        
        return hasCustomPerm;
    }
    
    public static Boolean hasCustomPermAccess(Id permId){
        Boolean hasCustomPerm = false;
        if(permissionMap==null){
            refreshCache();
        }
        
        if(permissionMap.size()>0){
            if(permissionMap.containsKey(permId)){
                hasCustomPerm = permissionMap.get(permId);
            }
        }
        
        return hasCustomPerm;
    }
    
    private static void refreshCache(){
        permissionMap = new Map<String,Boolean>();
        
        Set<Id> permissionIds = new Set<Id>();
        
        Map<Id,CustomPermission> customPermMap = new Map<Id,CustomPermission>(
                [SELECT Id, DeveloperName FROM CustomPermission 
                WHERE NamespacePrefix = null]);
        for(CustomPermission permObj : customPermMap.values()) {
            permissionMap.put(permObj.DeveloperName, false);
            permissionMap.put(permObj.Id, false);
            permissionIds.add(permObj.Id);
        }
        
        for(SetupEntityAccess setupEntObj : [SELECT SetupEntityId FROM 
                               SetupEntityAccess WHERE SetupEntityId in 
                               :permissionIds AND ParentID IN (SELECT 
                               PermissionSetId FROM PermissionSetAssignment 
                               WHERE AssigneeID = :UserInfo.getUserId())]){
                                                    
            permissionMap.put(setupEntObj.SetupEntityId, true);
            permissionMap.put(customPermMap.get(setupEntObj.SetupEntityId).
                DeveloperName,true);
        }
    }
    
}

To use in a trigger, an IF-condition must be added on top of the trigger code as below.

trigger TestAccountTrigger on Account (before update) {
    
    if(!CustomPermissionUtil.hasCustomPermAccess('Skip_Trigger')){
    // body of trigger
    }
    
}

For validation rule and workflow rules, a $Permission global variable is available for use.



So which one is better to use for our use-case? Custom Settings or Custom Permission? Below are the pros and cons.

Custom Settings 
Pro:
  • No SOQL required to retrieve the information (when using the custom settings method).
  • Custom Label global variable for formula.
Cons:
  • Bounded by Custom Setting data limit.
  • Access is managed on the custom setting section.
  • Data needs to be created on test classes.
Custom Permission 
Pro:
  • Custom Permission global variable for formula.
  • Assignment is aligned with how permission is given via Profile or Permission Set.
Cons:
  • Requires SOQL query to retrieve assignment.
Personally, I would go and use custom permission rather than custom settings not just because its a new feature but because it aligns to how we manage permissions to user. I would like to think that future enhancements would be released for the feature as well. However, I would recommend my readers to vote to this idea so that custom permission can be access as a global variable in Apex Code the same way we access Custom Labels. 

Happy coding!




No comments:

Post a Comment