stripInaccessible() is useful to strip the field that current user don't have access from query and sub-query. We can use it to remove inaccessible field from sObjects before DML operation to avoid exceptions. This method also provides the option an option to enforce the Object level access check.
Syntax :-
public static System.SObjectAccessDecision stripInaccessible(System.AccessType accessCheckType,
List<SObject> sourceRecords,
Boolean enforceRootObjectCRUD )
List<SObject> sourceRecords,
Boolean enforceRootObjectCRUD )
- accessCheckType : This parameter determines the type of field-level access check to be performed
- sourceRecords : A list of sObjects to be checked for fields that aren’t accessible in the context of the current user’s operation
- enforceRootObjectCRUD : Indicates whether an object-level access check is performed
Use Case 1: No access on Field
In this example, User don't have access on field called accountNumber on Account Object.
List<Account> accounts =[SELECT Id, Name,AccountNumber
FROM Account limit 2];
// Strip fields that are not readable
SObjectAccessDecision decision = Security.stripInaccessible(
AccessType.READABLE,
accounts);
// Print stripped records
for (Integer i = 0; i < accounts.size(); i++) {
System.debug('Insecure record access: '+accounts[i]);
System.debug('Secure record access: '+decision.getRecords()[i]);
}
// Print modified indexes
System.debug('Records modified by stripInaccessible: '+decision.getModifiedIndexes());
// Print removed fields
System.debug('Fields removed by stripInaccessible: '+decision.getRemovedFields());
In above example user dont have access on accountNumber field. After using the Security.scripInaccessible method we can simply strip out the same field. Which all field are removed we can check with "getRemovedFields" method. Here is output of above code.FROM Account limit 2];
// Strip fields that are not readable
SObjectAccessDecision decision = Security.stripInaccessible(
AccessType.READABLE,
accounts);
// Print stripped records
for (Integer i = 0; i < accounts.size(); i++) {
System.debug('Insecure record access: '+accounts[i]);
System.debug('Secure record access: '+decision.getRecords()[i]);
}
// Print modified indexes
System.debug('Records modified by stripInaccessible: '+decision.getModifiedIndexes());
// Print removed fields
System.debug('Fields removed by stripInaccessible: '+decision.getRemovedFields());
Use Case 2: No access on sObject
Let see another example when user don't have access on object itself. For demo I simply removed the access from Account object. Then we got the below exception.
System.NoAccessException: No access to entity: Account
we have "enforceRootObjectCRUD" optional parameter which is true by default we can set that as false to get null value.Use Case 3: SubQuery.
What about if you are try to access field from subquery ?
List<Account> accountsWithContacts =
[SELECT Name, AccountNumber,
(SELECT LastName, Phone FROM Account.Contacts)
FROM Account limit 2];
// Strip fields that are not readable
SObjectAccessDecision decision = Security.stripInaccessible(
AccessType.READABLE,
accountsWithContacts);
// Print stripped records
for (Integer i = 0; i < accountsWithContacts.size(); i++)
{
System.debug('Insecure record access: '+accountsWithContacts[i]);
System.debug('Secure record access: '+decision.getRecords()[i]);
}
// Print modified indexes
System.debug('Records modified by stripInaccessible: '+decision.getModifiedIndexes());
// Print removed fields
System.debug('Fields removed by stripInaccessible: '+decision.getRemovedFields());
[SELECT Name, AccountNumber,
(SELECT LastName, Phone FROM Account.Contacts)
FROM Account limit 2];
// Strip fields that are not readable
SObjectAccessDecision decision = Security.stripInaccessible(
AccessType.READABLE,
accountsWithContacts);
// Print stripped records
for (Integer i = 0; i < accountsWithContacts.size(); i++)
{
System.debug('Insecure record access: '+accountsWithContacts[i]);
System.debug('Secure record access: '+decision.getRecords()[i]);
}
// Print modified indexes
System.debug('Records modified by stripInaccessible: '+decision.getModifiedIndexes());
// Print removed fields
System.debug('Fields removed by stripInaccessible: '+decision.getRemovedFields());
This will remove the field on which user dont have access.
Use Case 4: DML.
What about if use dont have access on AccountNumber field and we will try to add value of AccountNumber by DML ?
public static void testDML(){
Account acc = new Account(Name='Test', AccountNumber ='TestRating');
insert acc ;
System.debug('---->'+acc );
}
This will insert the record with AccountNumber value in same user context even user dont have access on same field. How we can stop the same with Security.stripInaccessible. Let seeAccount acc = new Account(Name='Test', AccountNumber ='TestRating');
insert acc ;
System.debug('---->'+acc );
}
public static void testDML()
{
Account acc = new Account(Name='Test' ,AccountNumber ='Demo');
System.debug('---->'+acc );
List<Account> lstAcc = new List<Account>();
lstAcc.add(acc);
SObjectAccessDecision securityDecision = Security.stripInaccessible(
AccessType.CREATABLE,
lstAcc );
System.debug('---ecurityDecision.getRecords()->'+securityDecision.getRecords());
insert securityDecision.getRecords();
System.debug(securityDecision.getRemovedFields().get('Account'));
}
here is output{
Account acc = new Account(Name='Test' ,AccountNumber ='Demo');
System.debug('---->'+acc );
List<Account> lstAcc = new List<Account>();
lstAcc.add(acc);
SObjectAccessDecision securityDecision = Security.stripInaccessible(
AccessType.CREATABLE,
lstAcc );
System.debug('---ecurityDecision.getRecords()->'+securityDecision.getRecords());
insert securityDecision.getRecords();
System.debug(securityDecision.getRemovedFields().get('Account'));
}
You can also use the method to sanitize sObjects that have been deserialized from an untrusted source
Further Reading
- https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_with_security_stripInaccessible.htm
- https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_class_System_Security.htm#topic-title
Thank you so much for explaining it so clearly !!!
ReplyDeleteIn the last Execution Log, the debug statement [7]DEBUG ----> I am in inside insert event.
This Debug statement is not present here but may be some other class from where you might have invoked it or something ?
How to check for the delete DML ?
ReplyDeleteGenshin İmpact Benzeri Oyunlar
ReplyDeleteClash of Clans Benzeri Oyunlar
Mount and Blade Benzeri Oyunlar
CS GO Benzeri Oyunlar
7 Sins Benzeri Oyunlar
HYSAR