[SalesForce] How to check CRUD and FLS in apex

Please help me solving this Issue.

I'm new to the salesforce, I worte an Controller which do get list of objects values from contact, Cases and also inserts New cases and Case comments to, During the submittion of Security review, I got a response stating

Insert: Scanning File: K:……..\classes\contact_list_controller.cls
145 insert newcases; 167 insert case_comment;

Select: Scanning File: K:…….\classes\contact_list_controller.cls
121 detailscase=[select casenumber,Description,isclosed,
isdeleted,priority,status,subject,type,reason,origin,CreatedDate from
case where casenumber= :Case_ID];

public with sharing class contact_list_controller {

//variable Initialization 

  // URL parameter variables
  public String user_contact_EmailID{get; set;}
  public String contact_guid{get; set;}

  //variable for storing the date retrived from the Database
  public List<Contact> contacts;
  public List<Case> cases;
  public String Case_ID;

  // flags for internal popup
  public boolean displayPopup {get;set;}
  public boolean case_comment_popup {get; set;}

  // variable for submitting the data into the salesforce Database
  public Case newcases {get; set;} 
  public Case detailsCase{get;set;}
  public CaseComment case_comment {get; set;}


// Retriving the details for the standard Object (contact) 

  public contact_list_controller(ApexPages.StandardController controller) {
     contact_guid = ApexPages.currentPage().getParameters().get('guid') ;
     user_contact_EmailID = ApexPages.currentPage().getParameters().get('contid');
     contacts = [Select ID,name,phone,mobilephone,fax,email,birthdate,mailingcity,mailingstate,mailingcountry,homephone,PhotoUrl,Lastname from contact where email = :user_contact_EmailID]; 
     newcases = new Case();
     case_comment = new CaseComment(); 
     detailsCase = new Case();  
  }

  // function for storing the Contact details in contacts variable

  public List<Contact> getContacts() {
    return contacts;
  }

  // Code for retriving the details of the Cases and checking the accessible for the user  

  public List<Case> getCases(){
   if(cases == null) {
      String [] caseUpdateFields = new String [] {'casenumber','Description','isclosed','isdeleted','priority','status','subject','type','reason','origin','CreatedDate'};

      // Obtaining the field name/token map for the case object
      Map<String,Schema.SObjectField> caseAccessable = Schema.SObjectType.Case.fields.getMap();
      for (String fieldToCheck : caseUpdateFields) {
        // Check if the user has create access on the each field
        if (!caseAccessable.get(fieldToCheck).getDescribe().isAccessible()) {
          return null;
        }
      }
        cases=[Select casenumber,Description,isclosed, isdeleted,priority,status,subject,type,reason,origin,CreatedDate from Case where case.contactid =: contacts[0].ID ORDER BY casenumber DESC limit 5];
    }
  return cases;
  } 

  public void case_detail(){
    try{
        Case_ID = Apexpages.currentPage().getParameters().get('myParam');

        String [] singleCaseDetailFields = new String [] {'casenumber','Description','isclosed','isdeleted','priority','status','subject','type','reason','origin','CreatedDate'};
          // Obtaining the field name/token map for the case object
        Map<String,Schema.SObjectField> singleCaseDetailAccessable = Schema.SObjectType.Case.fields.getMap();
        for (String singleCaseDetailfieldToCheck : singleCaseDetailFields) {
            // Check if the user has create access on the each field
            if (!singleCaseDetailAccessable.get(singleCaseDetailfieldToCheck).getDescribe().isAccessible() ) {
            }
        }
    if(Case_ID !=null){
        detailscase=[select casenumber,Description,isclosed,isdeleted,priority,status,subject,type,reason,origin,CreatedDate from case where casenumber= :Case_ID];
      }
    }
    catch (Exception ex) {
      System.debug(LoggingLevel.Error, 'contact_list_controller.case_detail() Exception: ' + ex);
    }
    finally{
      displayPopup = true;
      detailsCase = new Case(); 
    }
  }

  // Function for inserting the newcases
  public void Save(){
    try{
      String [] newCaseCreateFields = new String [] {'Priority','Origin','Type','Status','reason','subject','Description'};
  // Obtaining the field name/token map for the case object
        Map<String,Schema.SObjectField> NewCaseCreateisCreateable = Schema.SObjectType.Case.fields.getMap();
        for (String NewCaseCreatefieldToCheck : newCaseCreateFields) {
            // Check if the user has create access on the each field
            if (!NewCaseCreateisCreateable.get(NewCaseCreatefieldToCheck).getDescribe().isCreateable() ) {

            }
        }
      newcases.contactid = contacts[0].Id; 
      insert newcases;      
    } 
    catch (Exception ex) {
      System.debug(LoggingLevel.Error, 'contact_list_controller.Save() Exception: ' + ex);
    }
    finally{
      displayPopup=false;
    }    
  }

// Function for adding the comment for each single case using the CaseID
  public void save_casecomment(){
    try{ 
      String [] newCaseCommentCreateFields = new String [] {'parentid','commentbody'};
  // Obtaining the field name/token map for the case object
        Map<String,Schema.SObjectField>newCaseCommentCreateisCreateable = Schema.SObjectType.CaseComment.fields.getMap();
        for (String newCaseCommentCreatefieldToCheck : newCaseCommentCreateFields) {
            // Check if the user has create access on the each field
            if (!newCaseCommentCreateisCreateable.get(newCaseCommentCreatefieldToCheck).getDescribe().isCreateable() ) {
            }
        } 
      case_comment.parentid = [Select ID from Case where casenumber= :Case_ID].Id;
      insert case_comment;
    }
    catch (Exception ex) {
      System.debug(LoggingLevel.Error, ' save_casecomment() Exception: ' + ex);
    }
    finally{
      case_comment_popup = false;
      case_comment = new CaseComment();
    }
  } 



  // Functions for Closing the popup inside the chatpopup page
  // function to close the popup    
  public void ClosePopup(){
    displayPopup=false;
  } 
  //function to close casecomment
  public void Casecomment_close(){
    case_comment_popup = false;
  }

  // function to show the popup    
  public void showPopup() {        
    displayPopup = true;     
  }  

  public void casecomment(){
    case_comment_popup = true;   
  }                      
}

Test method class

@isTest
public class ContactlistController {      
  static testMethod void testContactList (){
    List<Contact> contacts = new List<Contact>();
    for (Integer count = 0; count < 2; count++) {
        contacts.add(new Contact (FirstName = 'John'+count, LastName ='Doe'+count));
    }
    insert contacts;
    String contactId = contacts[0].Id;

    List<Case> cases = new List<Case>();
    for (Integer count = 0; count < 2; count++) {  
        cases.add(new Case (Description = 'Testing'+count, reason ='Testing'+count));
    }
    cases[0].contactid = contactId;
    cases[1].contactid = contactId;
    insert cases;
    String caseId = cases[0].Id;

    CaseComment case_comment =(new CaseComment (commentbody = 'Testing'));
    case_comment.parentid = caseId;
    insert case_comment;
    if(caseId != null){
    List<Case> detailscase=[select casenumber,Description,isclosed, isdeleted,priority,status,subject,type,reason,origin,CreatedDate from case where casenumber= :caseId];
    }
    contact_list_controller cc = new contact_list_controller(new ApexPages.StandardController(contacts[0]));
        cc.getContacts();
        cc.ClosePopup();
        cc.Casecomment_close();
        cc.showPopup();
        cc.casecomment();
        cc.getCases();
        cc.getUserdevice();
        cc.save();
        cc.case_detail();
        cc.chatdetaillist();    
        cc.save_casecomment();
  } 
}

Best Answer

Please refer to this knowledge article.

Basically you just need to add some checks like

    if (!Schema.sObjectType.Contact.fields.Name.isAccessible()){
      return '';
    }

or

if (!Schema.sObjectType.Contact.fields.Name.isUpdateable()){
  return null;
}

For dynamic check you could use Describe functionality.

Basically you need to use several methods from DescribeFieldResult class and from DescribeSObjectResult class.

DescribeFieldResult class

  • isAccessible()

  • isCreateable()

  • isUpdateable()

DescribeSObjectResult class

  • isAccessible()

  • isCreateable()

  • isDeletable()

  • isMergeable()

  • isUndeletable()

  • isUpdateable()

=================================

In your case, you can do this:

public void Save(){
    try{
        String [] newCaseCreateFields = new String [] {'Priority','Origin','Type','Status','reason','subject','Description'};

        newcases.contactid = contacts[0].Id; 
        if ( !Schema.sObjectType.Case.isCreateable() ) {
            System.debug(LoggingLevel.Error, 'you don\'t have access to create case');
        } else if ( !Schema.sObjectType.Case.fields.ContactId.isUpdateable() ) {
            System.debug(LoggingLevel.Error, 'you don\'t have access to update case ContactId');
        } else {
            insert newcases; 
        }     
    } 
    catch (Exception ex) {
        System.debug(LoggingLevel.Error, 'contact_list_controller.Save() Exception: ' + ex);
    }
    finally{
        displayPopup=false;
    }    
}

for inserting case comment you should follow the same logic to pass security review to honor CRUD\FLS

public void save_casecomment(){
    try{ 

        case_comment.parentid = [Select ID from Case where casenumber= :Case_ID].Id;

        if ( !Schema.sObjectType.CaseComment.isCreateable() ) {
            System.debug(LoggingLevel.Error, 'you don\'t have access to create CaseComment');
        } else if ( !Schema.sObjectType.CaseComment.fields.ParentId.isUpdateable() ) {
            System.debug(LoggingLevel.Error, 'you don\'t have access to update CaseComment ParentId');
        } else {
            insert case_comment; 
        }     
    }
    catch (Exception ex) {
        System.debug(LoggingLevel.Error, ' save_casecomment() Exception: ' + ex);
    }
    finally{
        case_comment_popup = false;
        case_comment = new CaseComment();
    }
} 
Related Topic