Apex sharing keywords

Do you know how Apex sharing keywords work?

Apex code works based on the closest sharing keyword. This means that for every class you can define different behavior, and even run multiple scenarios from a single start point!

Apex code works based on the closest sharing keyword. This means that for every class you can define different behavior, and even run multiple scenarios from a single start point!

Let’s check an example:

apex
public with sharing class Parent {
    public static List<Account> getRecords(String sharingModel) {
        switch on sharingModel {
            when 'without' {
                return WithoutSharing.getRecords();
            }
            when 'with' {
                return WithSharing.getRecords();
            }
            when 'inherited' {
                return InheritedSharing.getRecords();
            }
            when else {
                return DefaultSharing.getRecords();
            }
        }
    }
}

Now, we will test how it works:

apex
System.runAs(creator) {
    insert creatorRecords;
}

System.runAs(reader) {
    insert readerRecords();
}

List<Account> readerList;

Test.startTest();
System.runAs(reader) {
    readerList = Parent.getAccounts(SHARING_KEYWORD);
}
Test.stopTest();

Assert.areEqual(EXPECTED_SIZE, readerList.Size());

Assumptions: Creator User: 2 records with Reader User: 1 record with private sharing private sharing Results:

bash
TEST NAME                        OUTCOME  MESSAGE                 RUNTIME (MS)

ParentTest.testDefaultSharing    Pass     Reader got 3 records    316
ParentTest.testInheritedSharing  Pass     Reader got 2 records    204
ParentTest.testWithSharing       Pass     Reader got 2 records    208
ParentTest.testWithoutSharing    Pass     Reader got 3 records    199

Last question, what when a class doesn’t have an access keyword?

Don't do this
public class DefaultSharing {
    public static List<Record> getRecords() {
        return [SELECT Id, Name FROM Record];
    }
}

By default, Apex runs in system mode, so the above code runs the same as the class with “without sharing” defined. It is a good practice to always define what sharing class should use!

Do this
public without sharing class DefaultSharing {
    public static List<Record> getRecords() {
        return [SELECT Id, Name FROM Record];
    }
}

Text and code were extracted from the original slide. Plain-text version of the whole catalog