You are on page 1of 19

3- Programmatic Sharing

Enforcing Object and Field level permissions in Programmatic Solutions

Copyright © Walid El Horr 1


Enforcing Object and Field level permissions in Programmatic Apex
Sharing

• Topics covered in this lecture:

• System Mode

• Enforcing Object-Level Permissions in Apex Classes

• Enforcing Field-Level Permissions in Apex Classes

• Enabling Field and Object Level Permissions checking for SOQL using the WITH SECURITY_ENFORCED keyword

• Enforcing Permissions in Visualforce pages

• Enforcing Permissions in Custom Controllers

Copyright © Walid El Horr 2


Apex runs in System mode
• Apex generally runs in system context. This means that the current user's:

• Permissions

• Field-level security

• Record access and Sharing rules

• Are NOT taken into account during code execution

Copyright © Walid El Horr 3


“With Sharing” keyword
• The With Sharing keyword on class definition public class ContactClass {
public List<Contact> getContacts () {
forces the use of the security sharing permissions
return [SELECT id FROM Contact];
of the user currently logged in }
}
• In the 1st example, all contact records are returned,
even if the currently logged-in user does not have
access to all contact records public class with sharing ContactClass {
public List<Contact> getContacts () {
• This keyword only feature record access, and does return [SELECT id FROM Contact];
not include field-level security or CRED. }
}
• But what about CRED and FLS?

Copyright © Walid El Horr 4


Object-Level Permissions in Apex Classes
• You can enforce object-level permissions in your code by explicitly calling the sObject describe result methods
(of Schema.DescribeSObjectResult class) that checks the current user's object access permission levels

• This way, you can verify if the current user has the necessary permissions, and only if he or she has sufficient
permissions, you can then perform a specific operation like DML or query

• You can call the isAccessible, isCreateable, isUpdateable or isDeleteable methods of


Schema.DescribeSObjectResult to verify whether the current user has read, create, update or delete access to an
sObject

Copyright © Walid El Horr 5


DescribeSObjectResult Class Methods
DescribeSObjectResult Description
Class Method
isAccessible() Returns true if the current user can see this object, false otherwise.
isCreateable() Returns true if the object can be created by the current user, false otherwise.
isUpdateable() Returns true if the object can be updated by the current user, false otherwise.
isDeletable() Returns true if the object can be deleted by the current user, false otherwise.

if (Schema.sObjectType.Contact.isAccessible()) { if (Schema.sObjectType.Contact.isUpdateable()) {
// Access contact // Update contact
} }

if (Schema.sObjectType.Contact.isCreateable()) { if (Schema.sObjectType.Contact.isDeletable()) {
// Create contact // Delete contact
} }
6
Field-Level Permissions in Apex Classes
• You can also enforce field-level permissions in your code by explicitly calling the field describe result methods (of
Schema.DescribeFieldResult) that check the current user's field access permission levels

• This way, you can verify if the current user has the necessary permissions, and only if he or she has sufficient
permissions, you can then perform a specific operation like DML or query

• You can call the isAccessible, isCreateable, isUpdateable methods of Schema.DescribeFieldResult to verify
whether the current user has read, create or update access to a field

Copyright © Walid El Horr 7


DescribeFieldResult Class Methods
DescribeFieldResult Description
Class Method
isAccessible() Returns true if the current user can see this field, false otherwise..
isCreateable() Returns true if the field can be created by the current user, false otherwise.
isUpdateable() Returns true if the field can be edited by the current user, false otherwise.

if (Schema.sObjectType.Contact.fields.Email.isAccessible()) {
Contact c = [SELECT Email FROM Contact WHERE Id= :Id];
}

if (Schema.sObjectType.Contact.fields.Phone.isUpdateable()) {
// Update contact phone number
}

Copyright © Walid El Horr 8


Using the WITH SECURITY_ENFORCED keyword in SOQL
• Use the WITH SECURITY_ENFORCED clause to enable field and object level security permissions checking for
SOQL SELECT queries in Apex code including subqueries and cross-object relationships

• This keyword applies field and object level security checks only to fields and objects referenced in SELECT or
FROM SOQL clauses and not clauses like WHERE or ORDER BY.

9
Using the WITH SECURITY_ENFORCED keyword in SOQL
• If field access for Website is hidden, this List<Account> act1 = [SELECT Id, parent.Website
FROM Account
query throws an exception indicating
WITH SECURITY_ENFORCED];
insufficient permissions.

• If field access for either LastName or List<Account> act2 = [SELECT Id,


(SELECT LastName FROM Contacts),
Type is hidden, this query throws an
(SELECT Type FROM Opportunities)
exception indicating insufficient FROM Account
permissions. WITH SECURITY_ENFORCED];

10
Enforcing Permissions in Visualforce pages
• Visualforce Standard Controller gets executed in User mode: user's permissions enforced

• FLS is enforced: Fields not accessed through FLS will not be displayed

• Visualforce Custom Controller and Controller Extension always run in System mode: user's permissions ignored

• Adding the “with sharing” keywords on the class definition respects record access, but not Object-Level and Field-
Level permissions

11
Enforcing Permissions in Visualforce pages
• Using some tags enforces CRED and FLS, like: <apex:outputField />

• Manual CRED/FLS checks using the DescribeSObjectResult and DescribeFieldResult Class Method can be used

12
Enforcing Permissions in Visualforce pages
• The tag <apex:outputField /> will enforce FLS

<apex:page controller="CRUDTestController">
<apex:form>
<apex:pageBlock title="My Content" mode="edit">
<apex:pageBlockSection title="My Content Section" columns="2">
<apex:outputField value="{!myAccount.Name}" label="Account Name:"/>
<apex:outputField value="{!myContact.Name}" label="Contact Name:"/>
<apex:outputField value="{!myContact.Title}" label="Contact Title:"/>
<apex:outputField value="{!myLead.Name}" label="Lead Name:"/>
<apex:pageBlockSection>
<apex:pageBlock>
<apex:form>
<apex:page>

13
Enforcing Permissions in Visualforce pages
• The tag <apex:outputField /> will enforce FLS

public class CRUDTestController {


public Account myAccount {get; set;}
public Contact myContact {get; set;}
public Lead myLead {get; set;}

public CRUDTestController() {
myAccount = [SELECT Name FROM Account LIMIT 1];
myContact = [SELECT Name, Title FROM Contact LIMIT 1];
myLead = [SELECT Name FROM Lead LIMIT 1];
}
}

14
Enforcing Permissions in Custom Controllers
• With the tag <apex:outputText /> CRUD & FLS are not automatically enforced

<apex:page controller="CRUDTestController2">
<apex:form >
<apex:pageBlock title="My Content" mode="edit">
<apex:pageBlockSection title="My Content Section" columns="2">
<apex:outputText value="{!myAccountName}" label="Account Name:"/>
<apex:outputText value="{!myContactName}" label="Contact Name:"/>
<apex:outputText value="{!myContactTitle}" label="Contact Title:"/>
<apex:outputText value="{!myLeadName}" label="Lead Name:"/>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>

15
Enforcing Permissions in Custom Controllers
• With the tag <apex:outputText /> CRUD & FLS are not automatically enforced

public class CRUDTestController2 {


public String myAccountName {get; set;}
public String myContactName {get; set;}
public String myContactTitle {get; set;}
public String myLeadName {get; set;}

public CRUDTestController2() {
myAccountName = [SELECT Name FROM Account LIMIT 1].Name;
Contact myContact = [SELECT Name, Title FROM Contact LIMIT 1];
myContactName = myContact.Name;
myContactTitle = myContact.Title;
myLeadName = [SELECT Name FROM Lead LIMIT 1].Name;
}
}

16
Enforcing Permissions in Custom Controllers
• Fix the controller by using the DescribeFieldResult Class Methods

public class CRUDTestController3 {


public String myAccountName {get; set;}
public String myContactName {get; set;}
public String myContactTitle {get; set;}
public String myLeadName {get; set;}

public CRUDTestController3() {
if (Schema.sObjectType.Account.fields.Name.isAccessible())
myAccountName = [SELECT Name FROM Account LIMIT 1].Name;
Contact myContact = [SELECT Name, Title FROM Contact LIMIT 1];
if (Schema.sObjectType.Contact.fields.Name.isAccessible())
myContactName = myContact.Name;
if (Schema.sObjectType.Contact.fields.Title.isAccessible())
myContactTitle = myContact.Title;
if (Schema.sObjectType.Lead.fields.Name.isAccessible())
myLeadName = [SELECT Name FROM Lead LIMIT 1].Name;
}
}
17
Summary
Subject Description
System Mode Apex runs in System Mode, the current user's Permissions, Field-level security
Record access and Sharing rules are NOT enforced during code execution
“With Sharing” keyword Used to enforce record access level, but not Object or Field level security
Object-Level Permissions Schema.sObjectType.Contact.isAccessible() returns true or false
in Apex Classes Schema.sObjectType.Contact.isCreateable() returns true or false
Schema.sObjectType.Contact.isUpdateable() returns true or false
Schema.sObjectType.Contact.isDeletable() returns true or false
Field-Level Permissions in Schema.sObjectType.Contact.fields.Email.isAccessible() returns true or false
Apex Classes Schema.sObjectType.Contact.fields.Phone.isUpdateable() returns true or false
WITH Used in SOQL in Apex to enable field and object level security permissions
SECURITY_ENFORCED checking
Enforcing Permissions in The tag <apex:outputField /> will enforce CRUD and FLS
Visualforce pages
Enforcing Permissions in With the tag <apex:outputText /> CRUD & FLS are not automatically enforced
Custom Controllers - Fix the controller by using the DescribeFieldResult Class Methods
18
Enforcing Object and Field level permissions in Programmatic Solutions

Thanks for Watching! ☺

Copyright © Walid El Horr 19

You might also like