A blog dedicated to Salesforce Ohana

Dynamic Apex - Playing with CRUD and FLS


Security is one of the important things in today's world. And when we talk about cloud, Security is the top most priority items. No doubt. Salesforce is not an exception and they are also considering Security really seriously.

In Salesforce, we have different types of Security controls - starting from org level security to object level, followed by record level and field level. This post focuses on methods for controlling data at the object and field level.

As always I always believe explaining concept with examples is the best and effective way. Today also I will do the same thing.

For this post, I have prepared a small object called Book and below is the detail -


Important Note -

In Visualforce, when you use any sObject or sObject field, the platform will enforce CRUD and FLS automatically. If the user is not having FLS to a field, Salesforce will automatically remove the field from the Visualforce page. For example, apex:inputField tag will be rendered as read-only for those fields having FLS set as read-only. But the exception here are the tags apex:inputText, apex:inputTextArea. Using these tags tells Visualforce to not treat them as sObject field, thus platform will not automatically enforce FLS for those  fields.

Apex Code to check CRUD manually:
Requirement:
Write a Visualforce page with controller behind which should display all Books present in the org in the form of Picklist. When we will execute the page with user having access to Book object, it should work fine, but when we will execute the same page with user having no access to Book object, we want the page to display an error message - "SORRY!!! USER IS NOT HAVING ACCESS.."(Instead of some Salesforce error message).

Implementation:
To implement this one, in my developer org, I have two profiles. One having CRUD access to Book object and another having no access at all. Below are the details -


VisualForce Page:
<apex:page controller="BookSelector">
    <apex:form >
        <apex:outputLabel rendered="{IF(hasAccess==false,true,false)}" value="{!errorMessage}"/> 
        <apex:pageBlock rendered="{IF(hasAccess==true,true,false)}">
            <apex:pageBlockSection title="Book Selector" collapsible="true" columns="1">
                <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Select the book here: "/>
                    <apex:selectList value="{!selectedBook}" size="1" multiselect="false">
                        <apex:selectOptions value="{!allBooks}"/>
                    </apex:selectList>
                </apex:pageBlockSectionItem>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>
Controller:
public with sharing class BookSelector {
    public String selectedBook{get;set;}
    public String errorMessage{get;set;}
    public Boolean hasAccess{get;set;}
    
    public BookSelector(){
        //Check if user is having access to the object
        if(!sudipta__Book__c.sObjectType.getDescribe().isAccessible()){
            errorMessage = 'SORRY!!! USER IS NOT HAVING ACCESS..';
            hasAccess=false;
        }else{
            hasAccess=true;
        }
    }
    
    public List<SelectOption> getAllBooks(){
        List<SelectOption> options = new List<SelectOption>();
        if(hasAccess){
            List<sudipta__Book__c> allBooks = [SELECT 
                                                    ID,
                                                    NAME,
                                                    sudipta__Author__c,
                                                    sudipta__Price__c,
                                                    sudipta__Type__c
                                               FROM sudipta__Book__c ];
            for(sudipta__Book__c singleBook : allBooks){
                options.add(new SelectOption(singleBook.Name, singleBook.Name));
            }
        }
        return options;
    }
}

Explanation:
In the controller, I am using sudipta__Book__c.sObjectType.getDescribe().isAccessible() method to find out whether the current user is having read access to the Book object. If not, I am setting up the custom error message (Ideally this message should come from Custom Label).

Take away:
The method sObjectName.sObjecType.getDescribe().isAccessible() will return whether the user is having read access to this object.
Similarly we can use isCreateable(), isDeletable(), isUpdateable() methods to find out create, delete and edit permission.
You can find the all the methods @
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_sobject_describe.htm

CRUD and FLS check manually in Visualforce Page:
You can check whether you have CRUD permission for sObject or FLS permission for sObjectField
in Visualforce page as well. You can do that with the help of $ObjectType element.

For example, below Visualforce statement will not execute if the running user is not having View permission to see the Contact Name field.

<apex:outputText value="{!contactName}" rendered="{!$ObjectType.Contact.fields.Name.Accessible}" />
Similarly, the below command button will not even render if  the running user is not having Updateable permission on custom book object.

<apex:commandButton action="{!CustomUpdate}" rendered="{!$ObjectType.sudipta__Book__c.Updateable}" />

Please provide your feedback. Thanks.

Reference:

Share:

No comments:

Post a Comment

Follow Me

Enter your email address:

Delivered by FeedBurner

Popular Posts

Labels

Salesforce (99) Apex (43) admin (27) ADM (20) visualforce (20) dev 501 (19) integration (18) learn salesforce (17) 501 (16) SOAP (13) tutorial (11) Certification. (9) lightning (8) Trigger (7) test class (7) unit testing (7) design pattern (6) report (6) security (6) trailhead (6) Advanced Admin (5) New Features (5) SOQL (5) css (5) dashboard (5) debug (5) developer (5) formula (5) javascript (5) mobile (5) salesforce release (5) service cloud (5) solution management (5) use case (5) JSON (4) Lightning Experience (4) WebSphere (4) best practice (4) cast iron (4) component (4) github (4) html (4) polymer (4) profiles (4) responsive (4) tdd (4) ui (4) Certification (3) Live Chat (3) Performance (3) Products (3) Sales Cloud (3) Study Notes. (3) Summer15 (3) Tips (3) deployment (3) dynamic apex (3) event (3) license (3) map (3) mapbox (3) singleton (3) version controlling (3) Advanced Apex (2) Bulkify (2) Data Architecture and Management Certification (2) Distributed Version Controlling (2) Eclipse (2) Einstein (2) Force.com IDE (2) Governor Limit (2) IBM (2) Kitchener Developer Group (2) Lightning Design System (2) Live Agent (2) Online Event (2) Price Book (2) REST (2) SOSL (2) Spring 15 (2) Summer17 (2) ant (2) automation tool (2) basic (2) chatter (2) coding (2) communication (2) console (2) controller (2) documentation (2) flow (2) git (2) jquery (2) logging (2) permission (2) process builder (2) release (2) salesforce1 (2) strategy (2) xml (2) Agent Productivity (1) Analytics (1) Architect (1) Asynchronous callout (1) Bots (1) Browser (1) Bulk data load (1) CTA (1) Calendar (1) Canon (1) Case Management (1) Classic (1) Contact Center (1) Continuation (1) Continuous Integration (1) Cookie (1) Custom Metadata (1) Custom Object (1) Decorator Design Pattern (1) Diwali (1) Email (1) FSC (1) Financial Services Cloud (1) Goals (1) Groups (1) Guide (1) Household (1) Ideas (1) Implicit Sharing (1) Improvement (1) JourneyToCTA (1) KPIs (1) Kitchener User Group (1) Large Data Volume (1) LastModifiedDate (1) Metadata (1) Metrics (1) Omni-Channel (1) Opportunity (1) Person Account (1) Photo (1) Platform Developer I (1) Presentation (1) Product Schedule (1) Profile (1) Public Site (1) Query Plan (1) QuickReference (1) Reports (1) Role (1) SFDX (1) Salesforce DX (1) Salesforce Optimizer (1) Scratch Org (1) Session (1) Sharing (1) Site (1) Skills (1) Snap-ins (1) Spring 17 (1) Summer14 (1) Summer16 (1) Switch (1) SystemModStamp (1) Users (1) Webservice (1) Winter'15 (1) Winter'17 (1) access (1) agile (1) app (1) approval process (1) aura (1) awesome (1) backup (1) bitbucket (1) book (1) campaign (1) change set (1) code (1) code coverage (1) configuration (1) csv (1) custom button (1) custom settings (1) customization (1) data loader (1) database (1) delegate Admin (1) describe (1) dom (1) dreamforce (1) duplicate (1) dynamic (1) equals (1) error (1) field-level security (1) folder (1) ftp (1) generic (1) gift (1) global describe (1) hashcode (1) import wizard (1) jenkins (1) keynote (1) long running requests (1) monitoring (1) mysql (1) object (1) page layout (1) personal (1) power of one (1) record type (1) relationship (1) request (1) review (1) sub-tab (1) tab (1) username (1) visual workflow (1) workflow (1)

Total Subscribers

Total Pageviews