Prevent CRUD/FLS violation - isAccessible()
There are certain security tests which salesforce recommends before allowing an application to be used. These tests include permissions, XXS vulnerabilities, etc. One of these is regarding the accessibility of the fields which are being retrieved in your code.
This code snippet will help you check the accessibility of your fields included in a SOQL query.
IsAccessible()
This function of DescribeSObjectResult class, verifies that the logged-in user has permission to access the field before your code retrieves the field from an object via query.
Code Snippet :
public static Boolean isFieldsAccessible(Map<String, Set<String>> objectFields) {
Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
Integer globalFlag = 0;
for (String objectName : objectFields.keySet()) {
Integer flag = 0;
Map<String, Schema.SObjectField> fieldMap = schemaMap.get(objectName).getDescribe().fields.getMap();
for (String fieldName : objectFields.get(objectName)) {
for (Schema.SObjectField field : fieldMap.values()) {
Schema.DescribeFieldResult fieldDetail = field.getDescribe();
if (fieldDetail.getName() == fieldName && fieldDetail.isAccessible()) {
flag++;
break;
}
}
if (flag == objectFields.get(objectName).size()) {
globalFlag++;
}
}
}
if (globalFlag == objectFields.size())
return true;
return false;
}
Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
Integer globalFlag = 0;
for (String objectName : objectFields.keySet()) {
Integer flag = 0;
Map<String, Schema.SObjectField> fieldMap = schemaMap.get(objectName).getDescribe().fields.getMap();
for (String fieldName : objectFields.get(objectName)) {
for (Schema.SObjectField field : fieldMap.values()) {
Schema.DescribeFieldResult fieldDetail = field.getDescribe();
if (fieldDetail.getName() == fieldName && fieldDetail.isAccessible()) {
flag++;
break;
}
}
if (flag == objectFields.get(objectName).size()) {
globalFlag++;
}
}
}
if (globalFlag == objectFields.size())
return true;
return false;
}
This code can be used for multiple SOQL queries at once.
Add this code to your utility class and use as below :
1. For a single SOQL Query :
List<Profile> pObj=new List<Profile>();
1. For a single SOQL Query :
List<Profile> pObj=new List<Profile>();
if (myUtility.isFieldsAccessible(new Map<String, Set<String>>
{
'Profile' => new Set<String> { 'Id', 'Name' }
}))
{
{
pObj= [SELECT Id, Name FROM Profile where Id = :UserInfo.getProfileId()];
}
2. For multiple SOQL queries :
Account accObj;
List<Contact> contactList = new List<Contact>();
3. For relationship fields, Please pass the related objects also as the parameters with their respective fields :
Contact contactObj;
This also applies to relationship fields used in WHERE clause.
This method can be extended to check isCreateable(), isUpdateable(), isDeletable() and other DescribeSObjectResult methods as per your requirement.
2. For multiple SOQL queries :
Account accObj;
List<Contact> contactList = new List<Contact>();
if (myUtility.isFieldsAccessible(new Map<String, Set<String>>
{
{
'Account' => new Set<String> { 'Id', 'Name' },
'Contact' => new Set<String>{'Id','LastName'}
'Contact' => new Set<String>{'Id','LastName'}
}))
{
{
accObj= [SELECT Id, Name FROM Account where CreatedById = :UserInfo.getUserId()];
contactList=[SELECT Id, LastName FROM Contact where AccountId=:accObj.Id];
contactList=[SELECT Id, LastName FROM Contact where AccountId=:accObj.Id];
}
3. For relationship fields, Please pass the related objects also as the parameters with their respective fields :
Contact contactObj;
if (myUtility.isFieldsAccessible(new Map<String, Set<String>>
{
'Contact' => new Set<String>{'Id','LastName'},
'User' => new Set<String>{'Name'}
'User' => new Set<String>{'Name'}
}))
{
{
contactObj=[SELECT Id, LastName,ReportsToId.Name FROM Contact LIMIT 1];
}
This also applies to relationship fields used in WHERE clause.
This method can be extended to check isCreateable(), isUpdateable(), isDeletable() and other DescribeSObjectResult methods as per your requirement.
Good information on security access
ReplyDelete