Base Security Model
Foundational access control that defines the baseline sharing behavior for each object
Setup: Setup > Security > Sharing Settings
// Query Organization-Wide Defaults via Tooling API
SELECT Id, SobjectType, DefaultAccess, DefaultAccessPiiRestricted
FROM EntityDefinition
WHERE SobjectType IN ('Account', 'Contact', 'Opportunity')
// Example OWD Settings:
// Account: Public Read/Write
// Contact: Controlled by Parent
// Opportunity: Private
// Case: Public Read Only
// Apex: Check sharing access programmatically
Schema.DescribeSObjectResult accountDescribe = Account.sObjectType.getDescribe();
System.debug('Account OWD supports sharing: ' + accountDescribe.isAccessible());
Hierarchical Access
Automatic access inheritance where users higher in hierarchy can access records owned by subordinates
Setup: Setup > Users > Roles
// Query Role Hierarchy
SELECT Id, Name, ParentRoleId, RollupDescription
FROM UserRole
WHERE ParentRoleId != NULL
ORDER BY Name
// Apex: Get users in role hierarchy
public class RoleHierarchyUtil {
public static Set<Id> getUsersInHierarchy(Id roleId) {
Set<Id> userIds = new Set<Id>();
// Get all roles below this role in hierarchy
Set<Id> roleIds = new Set<Id>{roleId};
Set<Id> allSubordinateRoles = getAllSubordinateRoles(roleIds);
allSubordinateRoles.add(roleId);
// Get all users in these roles
for(User u : [SELECT Id FROM User WHERE UserRoleId IN :allSubordinateRoles AND IsActive = true]) {
userIds.add(u.Id);
}
return userIds;
}
private static Set<Id> getAllSubordinateRoles(Set<Id> parentRoleIds) {
Set<Id> allRoles = new Set<Id>();
List<UserRole> childRoles = [SELECT Id FROM UserRole WHERE ParentRoleId IN :parentRoleIds];
for(UserRole role : childRoles) {
allRoles.add(role.Id);
}
if(!childRoles.isEmpty()) {
allRoles.addAll(getAllSubordinateRoles(allRoles));
}
return allRoles;
}
}
Criteria-Based Sharing
Automatic sharing based on record criteria or ownership, extending access beyond role hierarchy
Setup: Setup > Security > Sharing Settings > Sharing Rules
// Example Sharing Rules (Setup Configuration)
// 1. Criteria-Based Sharing Rule: "West Coast Accounts"
// Object: Account
// Criteria: Billing_State__c = 'CA', 'OR', 'WA'
// Share with: West Coast Sales Team (Public Group)
// Access Level: Read/Write
// 2. Owner-Based Sharing Rule: "Manager Account Access"
// Object: Account
// Owner: Users in "Sales Rep" Role
// Share with: Users in "Sales Manager" Role
// Access Level: Read Only
// Apex: Query sharing rules and their shares
List<AccountShare> manualShares = [
SELECT Id, AccountId, UserOrGroupId, AccountAccessLevel, RowCause
FROM AccountShare
WHERE RowCause = 'Manual' OR RowCause LIKE '%Rule%'
];
// Apex: Create manual sharing programmatically
public static void shareAccountWithUser(Id accountId, Id userId, String accessLevel) {
AccountShare share = new AccountShare();
share.AccountId = accountId;
share.UserOrGroupId = userId;
share.AccountAccessLevel = accessLevel; // 'Read', 'Edit'
share.OpportunityAccessLevel = 'Read';
try {
insert share;
System.debug('Account shared successfully');
} catch(DmlException e) {
System.debug('Error sharing account: ' + e.getMessage());
}
}
User-Initiated Sharing
Ad-hoc sharing where record owners or users with sharing permissions grant access to specific users
Setup: Record Detail Page > Sharing Button
// Manual Sharing via Apex
public class ManualSharingService {
// Share record with user
public static void shareRecordWithUser(Id recordId, Id userId, String accessLevel, String objectType) {
SObject shareRecord;
// Determine share object type
switch on objectType {
when 'Account' {
shareRecord = new AccountShare(
AccountId = recordId,
UserOrGroupId = userId,
AccountAccessLevel = accessLevel,
OpportunityAccessLevel = 'Read'
);
}
when 'Contact' {
shareRecord = new ContactShare(
ContactId = recordId,
UserOrGroupId = userId,
ContactAccessLevel = accessLevel
);
}
when 'Opportunity' {
shareRecord = new OpportunityShare(
OpportunityId = recordId,
UserOrGroupId = userId,
OpportunityAccessLevel = accessLevel
);
}
}
if (shareRecord != null) {
insert shareRecord;
}
}
// Remove manual sharing
public static void removeSharing(Id recordId, Id userId, String objectType) {
String query = 'SELECT Id FROM ' + objectType + 'Share WHERE ' +
objectType + 'Id = :recordId AND UserOrGroupId = :userId AND RowCause = \'Manual\'';
List<SObject> sharesToDelete = Database.query(query);
if (!sharesToDelete.isEmpty()) {
delete sharesToDelete;
}
}
}
// Lightning Component Controller
@AuraEnabled
public static void shareWithUser(Id recordId, Id userId, String accessLevel) {
try {
// Get object type from record Id
String objectType = recordId.getSObjectType().getDescribe().getName();
ManualSharingService.shareRecordWithUser(recordId, userId, accessLevel, objectType);
} catch(Exception e) {
throw new AuraHandledException('Error sharing record: ' + e.getMessage());
}
}
Team-Based Sharing
Predefined team structures that automatically share related records with team members
Setup: Setup > Account Teams / Opportunity Teams
// Query Organization-Wide Defaults via Tooling API
SELECT Id, SobjectType, DefaultAccess, DefaultAccessPiiRestricted
FROM EntityDefinition
WHERE SobjectType IN ('Account', 'Contact', 'Opportunity')
// Example OWD Settings:
// Account: Public Read/Write
// Contact: Controlled by Parent
// Opportunity: Private
// Case: Public Read Only
// Apex: Check sharing access programmatically
Schema.DescribeSObjectResult accountDescribe = Account.sObjectType.getDescribe();
System.debug('Account OWD supports sharing: ' + accountDescribe.isAccessible());
Choose the right sharing method based on your data access requirements
Basic organization-wide access: Organization-Wide Defaults
Hierarchical management access: Role Hierarchy
Yes:Territory Management
No: Role Hierarchy or Sharing Rules