I know the differences between declaring a class inherited sharing, or leave it omitted, and between it and with sharing or without sharing, however I decided to test all the theory in the documentation in a real scenario.
-I have a trigger on account (API VERSION 45), it calls Account handler(API VERSION 45), which is with sharing.
-Account handler calls AccountUtil (API VERSION 48):
-AccountHandler relevant code:
public with sharing class AccountHandler implements ITrigger
{
public void beforeInsert(list<SObject> newList)
{
AccountUtil.queryAccounts();
}
-AccountUtil relevant code:
public inherited sharing class AccountUtil
{
public static void queryAccounts()
{
//When called from trigger, no sharing specified = without sharing, and inherited sharing specified = without sharing too (WHY IS THIS IF IT IS CALLED FROM AccountHandler WHICH IS with sharing?)
//When called as custom controller or controller extension for a vf page, no sharing specified = without sharing, and inherited sharing specified = with sharing
//With sharing is respected, from a trigger, even if security is not enforced in anyway in any other place in the class
for (Account acc : [SELECT Id, Name, SLASerialNumber__c FROM Account]) {
System.debug('acc: ' + acc);
if (String.isNotBlank(acc.SLASerialNumber__c)) {
acc1 = acc;
acc1Serial = acc.SLASerialNumber__c;
}
}
I have written down my conclusions as comments, however, my question is, why it runs as without sharing when it has inherited sharing (either specified or omitted) if it is called from AccountHandler, which is with sharing?
UPDATE:
I wanted to Test the possibility of AccountUtil being inheriting the sharing from the top level class, instead of doing it from the class that direcly called it.
To do that:
-I put AccountHandler (WITH SHARING) as a custom controller for a VF page, that calls Intermediary.cls
-I created Intermediary.cls class (WITHOUT SHARING, API VERSION 48) that calls AccountUtil
-AccountUtil, with inherited sharing, either splicitly declared or omitted, runs without sharing, following previous immediate previous class sharing. If Intermediary.cls is changed to be WITH SHARING, AccountUtil will runs under WITH SHARING too.
Basically:
-Class a with sharing is custom controller and call class b
-Class b is without sharing and call class c
-Class c has inherithed sharing, either declared explicitly or omitted, and runs as without sharing
-If b is changed to with sharing, then c runs as with sharing too
So class c does not actually follow class a top level class sharing, but b, where is it called from.
Update:
I just checked that, if a user is using a with sharing class and trying to update a record that he does not have record level access to, it will run in a insufficient access record, while this will not happen if the class is without sharing.