Over the last few years, there have been a lot of changes around enforcing the CRUD (create, read, update, and delete) and FLS (field-level security) securities in Apex.
The diagram above depicts the evolution of Apex security best practices. It dates back to 2006 when Salesforce developers used to do manual checks on objects to check for CRUD/FLS permission.
To address most (if not all) of the issues encountered in the past, Salesforce announced user mode database operations.
Let’s see what it is all about.
Apex, by default, runs in a system mode with elevated permissions, meaning that developers can bypass security controls, such as CRUD, FLS, or record sharing, when writing code.
With user mode database operations, developers can run Apex in the user’s context and enforce the user’s CRUD/FLS and sharing rules access.
Account[] accList = [
SELECT
Id, Name
FROM Account
WITH USER_MODE
]; // User Mode SOQL
Account[] accList = [
SELECT
Id, Name
FROM Account
WITH SYSTEM_MODE
]; // System Mode SOQL
Using the keyword “WITH USER_MODE,” the query respects the CRUD, FLS, and record level sharing security constraints.
String query = 'SELECT Id, Name FROM Account';
Account[] accList = Database.query(query, AccessLevel.USER_MODE);
A database class has new overloaded methods, which now support an “AccessLevel” parameter.
String keyword = 'Test';
List<List<SObject>> searchResults = [
FIND :keyword
IN Name FIELDS
RETURNING
Account(Name),
Contact(LastName, Account.Name)
WITH USER_MODE
];
String query = 'FIND \'Test*\' IN ALL FIELDS RETURNING Account(Name), Contact, Lead';
List<List<SObject>> searchResults = Search.query(query, AccessLevel.USER_MODE);
Like the database class, a search class also has new overloaded methods, which now support an “AccessLevel” parameter.
//Creating an account in user mode.
insert as user new Account(
Name = 'Test Account'
);
//Creating an account in System mode.
insert as system new Account(
Name = 'Test Account'
);
For Dynamic DML, developers can use the “AccessLevel” parameter to run database operations in the user or system mode.
Database.insert(
new Account(
Name = 'Test Account'
),
true, /*All or Nothing*/
AccessLevel.USER_MODE
);
public without sharing Example {
public Account[] getAccounts() {
String query = 'SELECT Id FROM Account';
return Database.query(query, AccessLevel.USER_MODE);
}
}
The new Salesforce release introduced numerous exciting updates for Apex, and we can anticipate even more enhancements in the upcoming Summer 2023 release.
Check out the 2023 release notes for a comprehensive overview of all the new Apex features.