Lightning Best Practice: Handling FLS Exceptions Gracefully

If you are a Visualforce developer, then you may be surprised to learn that FLS (Field Level Security) and CRUD (Create Access Delete and Update) permissions are NOT handled automatically in your Aura-enabled code.

And in case you do not know, Aura-enabled code is the code used for Lightning components and most of this code is used to access the data in your Salesforce org. The gotcha here is that unless you are specifically checking permissions in this code, then it is possible your Lightning components could be unintentionally exposing sensitive data from your Salesforce org. 

Ouch!!!

The Problem

While there are code examples out there (such as this one on in the Lightning Developer Guide), I think there is a fundamental flaw in most of these examples. And that flaw is that they do not handle exceptions gracefully.

To demonstrate, let’s see take a look at some code that is very similar to the code used in the official Lightning docs. This code is used in the Controller of a Lightning component which lists data from a custom object called Race.

String [] raceFields = new String [] {'Id','Name','DateTime__c',
'Location__c','Attended__c','Type__c','Results__c' };

Map raceMap =
        Schema.SObjectType.Race__c.fields.getMap();

for (String field : raceFields) {
   if (!raceMap.get(field).getDescribe().isAccessible()) {
      throw new System.NoAccessException();
         return null;
   }
}

res.races = [SELECT Id, Name, DateTime__c, Location__c,
               Attended__c, Type__c, Results__c FROM Race__c
            ORDER BY DateTime__c desc
            LIMIT :pSize OFFSET :offset]; 
return res;

This code will first check to see if all the fields that need to be queried are accessible and if any one of the fields is not accessible, it will throw a NoAccessException.

Seems ok, right?

Well to begin, let’s take a look at what you would see in the browser if this code is run and the user does NOT have access to one of the fields:

NoAccessException.png

YUK!!!!

Not only is this message ugly, it is extremely unhelpful.  Surely, there must be something better?

Option 1 – a Better Error Message

Well, the first option you have is to simply replace the code that throws a System.NoAccessException, with code that throws an AuraHandledException, such as this:


 for (String field : raceFields) {
    if (!raceMap.get(field).getDescribe().isAccessible()) {
        throw new AuraHandledException(
            'Were sorry, but you do not have access to this field: ' 
            + raceMap.get(field).getDescribe().getName());
        return null;
    }
 } 

The message you will see now when one of the fields is not accessible is this:

BetterException

Much better, don’t you think?

Option 2 – Handling the Exception Gracefully

But wait, it can get EVEN better…

Instead of returning null when a field is not accessible, we can instead make a few more changes to the code, such as this:


String [] raceFields = new String [] {'Id','Name','DateTime__c',
            'Location__c','Attended__c','Type__c','Results__c' };
  
Map raceMap = 
      Schema.SObjectType.Race__c.fields.getMap();

List fields = new List();
String query = '';
for (String field : raceFields) {
    if (raceMap.get(field).getDescribe().isAccessible()) {
        fields.add(field.trim());
    }
}
if(fields.Size() > 0) {
    query = 'SELECT ' + String.join(fields, ',') + ' FROM Race__c';
    query+= ' ORDER BY DateTime__c desc LIMIT ' + pSize;
    query+= ' OFFSET ' + offset;
}
res.races = Database.query(query);
      
return res;

 
In this version, I am still looping through all the fields to see if they are accessible, but rather than throwing an exception when even one field is not accessible, I am instead adding the accessible field to a list I created called fields. I am then building a dynamic query string using only the fields that are accessible and finally just executing the query using the database.query method instead.

The result is that when the component renders, rather than seeing any error message at all, the user sees the list of races. But, any fields that are not accessible are just left blank.

Now, I happen to think this is the best solution. What do you think?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s