5

I'm going through CRUD and Field-Level Security (FLS) from Lightning Components Developer Guide, and the following code for Field-Level Security validation doesn't make any sense for me in terms of good development practices:

// Obtain the field name/token map for the Expense object
Map<String,Schema.SObjectField> m = Schema.SObjectType.ns__Expense__c.fields.getMap();

for (String fieldToCheck : expenseAccessFields) {

    // Check if the user has access to view field
    if (!m.get(fieldToCheck).getDescribe().isAccessible()) {

        // Pass error to client
        throw new System.NoAccessException()

       // Suppress editor logs
       return null;
    }
}

Isn't an ultimate goal is to hide ONLY the fields that the current user shouldn't have access to? And another question - what do you use to control Field-Level Security [in Apex for Lightning] as the most efficient/convenient method?

  • Definitely not the way I would go, they are going through the lazy mode haha. In their example they are checking for the whole object and not only the fields used on the component. I would still want the end user to have access to the page and display at least the fields he has access to. However in terms of development it will be more challenging, that's for sure. 1) build query based on the fields the current has access to. 2) display the fields dynamically in your component based on their accessbility. – Cloud Ninja Jan 25 '17 at 0:52
  • @CloudNinja This is exactly what I'm asking - in Visualforce pages this was done automatically, and now it seems like not so trivial task, especially when you are supposed to do CRUD and FLS on everything, as recommended best practice. Was wondering if ppl had developed some techniques since Lightning is being pushed for long enough... – o-lexi Jan 25 '17 at 1:11
2

The ultimate goal depends on the business needs .One of below can be adopted

1.You can collect only those fields that user has and ignore the other fields user does not have access to

2.You can throw exception and asking user to reach out to admin to explicitly assign permission set

To manage CRUD FLS you can use some library to reduce code rewrite

The one that's commonly used and open source is ESAPI

https://code.google.com/archive/p/force-dot-com-esapi/wikis/GettingStarted.wiki

  • 2 is what actually thye do in their example, 1 is more preferable, but I'm not so sure how would you (A) do inline SOQL, and (B) how to hide fields in Lightning component that current user can't access? From what I've read about ESAPI, it lets you to "allows apex classes execute statements such as insert object; as if operating in user context.". But this is not what I'm asking. – o-lexi Jan 25 '17 at 1:06
  • 1
    ESAPI has built in logic to do all CRUDFLS for you .You use the same logic as in 2 but instead of error you write a dynamic soql with only field that user has access . – Mohith Shrivastava Jan 25 '17 at 1:08
  • 4
    It's ok to get dynamically the right SOQL with only the accessible fields, the challenge is how to display that dynamically on the page ? Because you will build the page based on full access. So your method shouldn't return only a list of object but also the list of (not) accessible fields, then on the component you could check if field is accessible then display it, otherwise skip, could probably do it using a wrapper class. – Cloud Ninja Jan 25 '17 at 1:34
2

Since Winter 20 release we have Security.stripInaccessible() method which strips the fields that the current user can’t access from query and subquery results.

You can use it to remove inaccessible fields from sObjects before a DML operation to avoid exceptions. You can also use the method to sanitize sObjects that have been deserialized from an untrusted source.

For example (taken from apexdocs) the user doesn’t have permission to read the ActualCost field of a Campaign:

List<Campaign> campaigns = new List<Campaign>{
    new Campaign(Name='Campaign1', BudgetedCost=1000, ActualCost=2000),
    new Campaign(Name='Campaign2', BudgetedCost=4000, ActualCost=1500)
};
insert campaigns;
// Strip fields that are not readable
SObjectAccessDecision decision = Security.stripInaccessible(
    AccessType.READABLE,
    [SELECT Name, BudgetedCost, ActualCost FROM Campaign]
);
// Print stripped records
for (SObject strippedCampaign : decision.getRecords()) {
    System.debug(strippedCampaign); // Does not display ActualCost
}
// Print modified indexes
System.debug(decision.getModifiedIndexes());
// Print removed fields
System.debug(decision.getRemovedFields());
//Lines from output log
//|DEBUG|Campaign:{Name=Campaign1, BudgetedCost=1000, Id=701xx00000011nhAAA}
//|DEBUG|Campaign:{Name=Campaign2, BudgetedCost=4000, Id=701xx00000011niAAA}
//|DEBUG|{0, 1}
//|DEBUG|{Campaign={ActualCost}}

Disclaimer:

As a beta feature, stripInaccessible method is a preview and isn’t part of the “Services” under your master subscription agreement with Salesforce. Use this feature at your sole discretion, and make your purchase decisions only on the basis of generally available products and features. Salesforce doesn’t guarantee general availability of this feature within any particular time frame or at all, and we can discontinue it at any time. This feature is for evaluation purposes only, not for production use. It’s offered as is and isn’t supported, and Salesforce has no liability for any harm or damage arising out of or in connection with it.`

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.