In Apex, there are two types of execution contexts such as system execution context and user execution context. User execution context is when a user clicks a button or link, for example, that executes Apex code. When a system event or process executes Apex code, a system execution context is created. Apex does not enforce object-level and field-level permissions in system mode by default, but the new AccessLevel class represents the two modes in which Apex runs database operations. You can use this class to define the execution mode as user mode or system mode. The key difference between the previously used WITH SECURITY_ENFORCED keyword and the new AccessLevel class is that the AccessLevel class allows you to specify the mode of execution as either user mode or system mode. In user mode, the code respects the field-level security (FLS), object permissions, and sharing rules of the running user. On the other hand, in system mode, the class sharing keywords control the sharing rules.
The WITH SECURITY_ENFORCED keyword, introduced earlier, allows you to enforce field-level security (FLS) and object permissions in SOQL queries. It ensures that the query results only include the fields and records that the running user has access to. However, it does not provide the ability to run the code in user mode or system mode.
With the new AccessLevel class, you can explicitly define the execution mode as user mode or system mode for database operations. This allows you to run the code with the appropriate permissions and sharing rules based on the context in which it is being executed.
User Context:
AccessLevel userMode = AccessLevel.USER_MODE; List<Opportunity> opportunitiesUserMode = Database.query (‘SELECT Name, Amount FROM Opportunity WITH USER_MODE’); System.debug(‘Opportunities in User Mode: ‘ + opportunitiesUserMode);
System Context:
AccessLevel systemMode = AccessLevel.SYSTEM_MODE; List<Opportunity> opportunitiesSystemMode = Database.query (‘SELECT Name, Amount FROM Opportunity WITH SYSTEM_MODE’); System.debug(‘Opportunities in System Mode: ‘ + opportunitiesSystemMode);
The preceding code, you can check in Developer Console. But when you try to execute systemMode code in Developer Console will get an error “System. SecurityException: Cannot use SYSTEM_MODE access level in anonymous execution of Apex.” That is because you would need to execute the code within a proper context, such as a deployed Apex class or a trigger, where security checks and access controls are in place.
Please note that the debug output will depend on the specific data available in your Salesforce organization. Make sure to check the debug logs to see the actual results returned by the queries.
To enforce object and field-level permissions, you can call the isAccessible(), isCreateable(), isUpdateable(), or isDeletable() methods of the Schema. DescribeSObjectResult class to verify whether the current user has read, create, or update access to an object. These methods can be used in any context and are not limited to the system execution context. They are commonly used in scenarios where you need dynamically adapt your code based on the permissions of the running user has specific on a field or object. You use them to make decisions based on individual permissions. Like to check if the current user has access to an object, you can use the isAccessible method. This method returns a value indicating whether the object is accessible to the user.
However, it is important to note that you need to include all the fields you want to access in your SOQL query.
Here’s an example that demonstrates how to check field accessibility and retrieve the necessary fields in a query:
List<Opportunity> opportunities = [SELECT Name, Amount, StageName FROM Opportunity];
List<Opportunity> sanitizedOpportunities = new List<Opportunity>();
for (Opportunity opp : opportunities) { if (Schema.sObjectType.Opportunity.fields.StageName.isAccessible () && opp.StageName == ‘Prospecting’) {
Opportunity sanitizedOpp = new Opportunity(); sanitizedOpp.Name = opp.Name; sanitizedOpp.Amount = opp.Amount; sanitizedOpportunities.add(sanitizedOpp);
}
}
System.debug(‘Sanitized Opportunities: ‘ + sanitizedOpportunities);
In the given code snippet, we start by querying Opportunities from Salesforce, specifically selecting the Name, Amount, and StageName fields.
To ascertain the accessibility of the StageName field, we utilize the isAccessible() method from the Schema.DescribeFieldResult class. This method helps confirm whether the current user has read access to the StageName field.
The condition opp.StageName == ‘Prospecting’ is employed to identify Opportunities that are in the “Prospecting” stage. If the StageName field is accessible and the Opportunity is in the specified stage, we proceed to create a new Opportunity object called sanitizedOpp. This new object is then populated with the Name and Amount fields from the original Opportunity (opp).
The Opportunities meeting the “Prospecting” stage criteria are accumulated in the sanitizedOpportunities list. To conclude, we utilize the System.debug() statement to display the contents of the sanitizedOpportunities list, providing visibility into Opportunities that fulfill the specified condition.