What is sharing context in Salesforce apex?

What is sharing context in Salesforce apex?

On April 18, 2024, Posted by , In Salesforce, With Comments Off on What is sharing context in Salesforce apex?

Table of Content

With Sharing:

When you define your classes with the with sharing keyword, it operates in the user context, respecting applicable sharing rules for the user. Consider a scenario where a sales representative needs access to their own opportunities:

public with sharing class OpportunityController {
    public List<Opportunity> getOpportunities() {
        return [SELECT Name, CloseDate FROM Opportunity WHERE OwnerId = :UserInfo.getUserId()];
    }
}

Read more: Latest Salesforce interview questions and answers.

In this example, the OpportunityController class is defined with with sharing to ensure that the sales representative only sees opportunities that they own, respecting Salesforce’s sharing rules.

Without Sharing:

In contrast, when you define your class as without sharing, it operates in the system context, without applying sharing rules of the current user. Consider a scenario where a system process needs access to all opportunities for reporting purposes:

public without sharing class OpportunityReporting {
    public List<Opportunity> getAllOpportunities() {
        return [SELECT Name, CloseDate FROM Opportunity];
    }
}

Checkout: Variables in Salesforce Apex

In this example, the OpportunityReporting class is defined with without sharing to ensure that it can access all opportunities in the system, regardless of the current user’s permissions. This is useful for system processes that require unrestricted access to data.

Inherited Sharing:

By defining a class as “inherited sharing,” you inherit the sharing rules from the class that calls it, dynamically determining the sharing mode at runtime. This approach requires careful consideration to ensure that your class is secure in both “with sharing” and “without sharing” modes.

Checkout: Data types in Salesforce Apex

Key Points:

  • Assumes the sharing rules from the class that calls it (the parent class).
  • Sharing mode is determined dynamically at runtime.
  • It’s essential to write your class to be secure in both “with sharing” and “without sharing” modes.
  • When the entry point is the same class that is defined as “inherited sharing,” the class works in “with sharing” mode by default.
  • When used as a controller for Aura/VF pages or REST services, it operates in “with sharing” mode.
  • Helps to pass the AppExchange security review.

Example: Consider two classes, ClassA and ClassB, where ClassA is defined as “with sharing” and ClassB is defined as “inherited sharing.” If ClassB is called from ClassA, ClassB will run in user mode, as the initiator class (ClassA) is defined to run in user mode.

Sample Class Definition:

// Class defined as inherited sharing
public inherited sharing class ExampleClassC {
    // Your logic here.
}

Read more: Salesforce apex programming examples

In this example, ExampleClassC will inherit the sharing mode from the class that calls it, providing flexibility in sharing settings based on the context in which it is used.

In Apex, sharing context refers to the setting which determines the level of access users have to records. Apex provides two main ways to enforce record-level access: with or without sharing.

  1. With Sharing: When you use with sharing in your Apex class, the sharing rules and security settings of the current user are enforced. This means that the user can only access records they are permitted to view or modify according to the organization’s sharing policies.
  2. Without Sharing: Using without sharing means that the Apex class does not respect the organization’s sharing rules and security settings. The code runs in system context, and it has access to all objects and fields. This access level is necessary for certain administrative tasks but should be used cautiously to avoid exposing sensitive data.

It’s crucial to choose the appropriate sharing context based on the specific needs of your application and to ensure that data security is maintained. If no sharing keyword is declared, the class defaults to without sharing. However, it’s best practice to always explicitly specify the sharing behavior to make the code’s behavior clear and intentional.

User Mode vs System Mode:

User Mode in Salesforce refers to the execution context of Apex code where the permissions and sharing settings of the current user are taken into consideration. This includes the user’s profile permissions, field-level security settings, and sharing rules. When code is running in user mode, it respects these permissions and rules, ensuring that data access is restricted based on the user’s privileges.

Read more: Array methods in Salesforce Apex

On the other hand, System Mode in Salesforce is the execution context where Apex code runs without considering the permissions and sharing settings of the current user. In this mode, Apex code has access to all objects, fields, and records, regardless of the user’s permissions. This means that the user’s sharing rules, field-level security settings, and profile permissions are not respected during code execution.

Enforcing Sharing Rules:

By default, Apex code runs in system mode, which means that the current logged-in user’s permissions and field-level security settings are not respected. To ensure that sharing rules are enforced, you can declare a class using the “with sharing” keyword. This enforces the sharing rules of the current user, ensuring that data access is restricted based on the user’s sharing settings.

Without Sharing:

On the other hand, if you declare a class using the “without sharing” keyword, the class is executed in system mode. This means that the sharing rules for the current user are not enforced, and the class has access to all data, regardless of the user’s sharing settings.

Inherited Sharing: To inherit the sharing settings from the parent class (i.e., the class that calls it), you can declare the class with the “inherited sharing” keyword. This allows the class to run in the sharing mode of the class that called it, ensuring that the sharing settings of the parent class are applied.

Considerations:

  • It’s important to always specify a sharing clause in your Apex classes to ensure that data access is restricted based on the user’s permissions.
  • If a class is the entry point into an Apex transaction and you do not specify a sharing clause, it defaults to “without sharing.”
  • If a class is the entry point into an Apex transaction and you specify “inherited sharing,” it defaults to “with sharing.”
  • Classes inherit the sharing settings from a parent class when one class extends or implements another.

Enforce Object & Field Permissions: By default, Apex does not enforce object-level and field-level permissions. However, you can enforce these permissions by calling the sObject describe result methods (of Schema.DescribeSObjectResult) and the field describe result method (of Schema.DescribeFieldResult). These methods allow you to verify whether the logged-in user has permissions to perform DML operations or queries on objects and fields.

Read more: Loops in Salesforce Apex

Using these methods requires more effort on your part as a developer and may result in more lines of code. The following methods from the Schema.DescribeSObjectResult can be called to verify whether the user has read, create, delete, or update access on the object:

  • isAccessible
  • isCreateable
  • isUpdateable
  • isDeletable

Sample program

// Get the describe result for the Custom_Object__c object
Schema.DescribeSObjectResult describeResult = Custom_Object__c.SObjectType.getDescribe();

// Check if the object is accessible
if (describeResult.isAccessible()) {
    System.debug('Custom_Object__c is accessible');
} else {
    System.debug('Custom_Object__c is not accessible');
}

// Check if the object is createable
if (describeResult.isCreateable()) {
    System.debug('Custom_Object__c is createable');
} else {
    System.debug('Custom_Object__c is not createable');
}

// Check if the object is updateable
if (describeResult.isUpdateable()) {
    System.debug('Custom_Object__c is updateable');
} else {
    System.debug('Custom_Object__c is not updateable');
}

// Check if the object is deletable
if (describeResult.isDeletable()) {
    System.debug('Custom_Object__c is deletable');
} else {
    System.debug('Custom_Object__c is not deletable');
}

Using WITH USER_MODE or WITH SYSTEM_MODE

When fetching data from a SOQL query, it’s important to handle user permissions and field-level security (FLS) appropriately. In the past, this was typically done using Describe-based checks to ensure that the user had access to the required fields and objects. For example, consider the following code snippet:

if (Schema.SObjectType.Account.isAccessible() &&
     Schema.SObjectType.Account.fields.Name.isAccessible() &&
     Schema.SObjectType.Account.fields.OwnerId.isAccessible() &&
     Schema.SObjectType.Account.fields.Support__c.isAccessible() &&
     Schema.SObjectType.Account.fields.OwnerId.getReferenceTo()[0].getDescribe().isAccessible()) {
 return [SELECT Name, Owner.Name FROM Account WHERE Support__C = 'Supreme'];
} else {
 throw new AuraHandledException('Access Denied');
}

Read more: Methods – Salesforce Apex

This approach checks each field and object for accessibility before executing the SOQL query. However, with the introduction of USER_MODE, handling user permissions has become more straightforward. Now, you can achieve the same result more efficiently:

return [SELECT Name, Owner.Name FROM Account WHERE Support__C = 'Supreme' WITH USER_MODE];

This statement ensures that the query respects the current user’s permissions and FLS settings, providing a simpler and more efficient way to handle data access control in Salesforce Apex.”

Feel free to adjust the content to better fit your needs or add more specific details related to your projects or programming languages of interest.

Read more: Classes – Salesforce Apex

Comments are closed.