[SalesForce] Data Access restrictions to Salesforce objects via Apex Web Service

I'm going through this article :

https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_web_services_methods_exposing.htm

Have few questions regarding access to field/objects/record by Apex web services and triggers:
First Apex Webservices : ( for e.g say used to update Account records and Account is private)

  1. can an Apex webservice update a particular 'field' in SFDC which is hidden from profile of user(FLS), which is used to connect to Saleforce ? MY answer is yes – please confirm
  2. Can it update a field in 'object' on which API user doesn't have any access ? My answer is yes – please confirm
  3. Can it update 'record' in SFDC on which it doesn't have access ? ( my answer- no, if 'with sharing' is enforced on class with webservice method

I think same is applicable for Triggers also in all 3 cases. Please confirm

In other words: Apex can always access and update fields/objects on which context user don't have access . With Sharing and Without sharing , as name suggest, impact only record level security

thanks !

Best Answer

An Apex Web Service behaves pretty much as any Apex class does.

First of all, Profile and Permission Set restrictions on Object security or Field security are not enforced. And that is that.

The access level, if set to without sharing will ignore sharing rules (giving the code access to any record in the system, regardless of ownership, sharing, etc). If set to with sharing, sharing rules, ownership, and all the rest of the sharing model and record access rules will apply.

Triggers are always without sharing. Triggers aren't actually classes either (can't be instantiated, invoked directly, subclassed, can't be a subclass, can't be a superclass, etc.). The code that is directly in the trigger code block executes as without sharing. Always.

The only way to get my code to run as with sharing in the context of a trigger is to create a class that is set to with sharing, and invoke it from your trigger.

A Trigger:

trigger MyTrigger on Contact (before insert){
//this is without sharing
    MyWithSharingClass.doStuff(Trigger.new); //<--the code in here can be made to execute as with sharing
}

Invokes a Class:

public with sharing class MyWithSharingClass{

    public static void doStuff(List<Contact> triggerContacts){
      //anything I do in here will respect sharing rules

    }

}

In most circumstances, you will want trigger code to execute as without sharing anyway. For instance, say I wanted my trigger to block entry of a record if some other value existed in another record. If I did that trigger as with sharing and the object was set to private, my trigger code would not be operating with a full picture of whether that other piece of data were out there. Same thing with doing an aggregate calculation.

Conversely, an Apex web service, especially if intended for a client app, like a mobile app, you'd want to be with sharing, otherwise you risk the user having access to data through the client app you didn't intend them to.

Finally, if you need a service class to do some discrete calculation, act as without sharing and pass back data after that calculation, your web service can always be with sharing, but then invoke a class that is without sharing, which returns the aggregate value, without exposing too much data directly to the end point.

Related Topic