Check User Field Level Security Before DML

According to Salesforce best practice we must check the current user FLS (field level security) before running any DML action. It's sometimes annoying and in many cases in enterprise company no one really enforce it but if you want to develop something to the appexchange and go through the security review then it is must.

Following utility class/method can simplify the process and help understanding how to run this check.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public with sharing class SecurityChecker {

    //Check object access and FLS
    public static set<String> isUserAllowed(String action, list<SObject> l_records){
        set<String> s_errors = new set<String>();
        
        SObjectType objType = l_records.get(0).getSObjectType();
        
        if(action == 'delete' && objType.getDescribe().isDeletable() == false){
            s_errors.add('Missing delete permission on object : ' + objType);
        }
        else if(action == 'insert'){
            if (objType.getDescribe().isCreateable() == false) {
                s_errors.add('Missing create permission on object : ' + objType);
            }
            else {
                Map<String, Schema.SObjectField> fieldMap = objType.getDescribe().fields.getMap();
                
                for (SObject soRecord : l_records) {
            
                    for (String fieldName : soRecord.getPopulatedFieldsAsMap().keySet()) {
                        if (fieldName == 'Id') continue;
                        
                        Schema.SObjectField myField = fieldMap.get(fieldName);
                        if (myField == null) continue;
                        
                        Schema.DescribeFieldResult dfr = myField.getDescribe();
                        
                        if (dfr.isCalculated() == false && dfr.isPermissionable() == true && dfr.isUpdateable() == false) {
                            s_errors.add('Missing create permission on object/field : ' + objType + '/' + myField);
                        } 
                    }
                }
            }
        }
        else if(action == 'update'){
            if (objType.getDescribe().isUpdateable() == false) {
                s_errors.add('Missing update permission on object : ' + objType);
            }
            else {
                Map<String, Schema.SObjectField> fieldMap = objType.getDescribe().fields.getMap();
                
                for (SObject soRecord : l_records) {
            
                    for (String fieldName : soRecord.getPopulatedFieldsAsMap().keySet()) {
                        if (fieldName == 'Id') continue;
                        
                        Schema.SObjectField myField = fieldMap.get(fieldName);
                        if (myField == null) continue;
                        
                        Schema.DescribeFieldResult dfr = myField.getDescribe();
                        
                        if (dfr.isCalculated() == false && dfr.isPermissionable() == true && dfr.isUpdateable() == false) {
                            s_errors.add('Missing update permission on object/field : ' + objType + '/' + myField);
                        } 
                    }
                }
            }
        }
        
        return s_errors;
    }
}



Basically, having this utility class, all you need to do is to invoke it before update.
For instance:



1
2
3
4
5
6
7
8
set<String> s_errors = SecurityChecker.isUserAllowed('update', accountList);

if(s_errors.isEmpty()){
 update accountList;
}
else{
 //missing permissions. print errors
}



Hope this is helpful 😯

No comments:

Post a Comment

Retire of Permission on Profiles

If you are working as a Salesforce admin/developer you've probably heard somewhere that Salesforce is planning to make a significant cha...