Sharing & Security

Organization-Wide Defaults

Base Security Model

Best for:
  • Establishing baseline security for all objects
  • Default access levels for new records
  • Foundation for all other sharing mechanisms
Scope & Implementation:
organisation

Foundational access control that defines the baseline sharing behavior for each object

Setup: Setup > Security > Sharing Settings

Requirements
  • System Administrator permissions
  •  Understanding of object relationships
  •  Business requirements for data access
Important Notes
  • Cannot be more restrictive than field-level security
  • Affects all records of an object type
  • Changes can impact performance
Organization-Wide Defaults Example

// 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());

Role Hierarchy

Hierarchical Access

Best for:
  • Sales management hierarchy access
  • Executive reporting and visibility
  • Organizational management structure
Scope & Implementation:
Hierarchical

Automatic access inheritance where users higher in hierarchy can access records owned by subordinates

Setup: Setup > Users > Roles

Requirements
  •  Role hierarchy defined
  •  Users assigned to appropriate roles
  • OWD set to Private or Public Read Only
Role Hierarchy Example

// 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;
    }
}

Sharing Rules

Criteria-Based Sharing

Best for:
  • Sharing accounts by geography or industry
  • Cross-functional team access
  • Partner and channel partner access
Scope & Implementation:
Rule-Based

Automatic sharing based on record criteria or ownership, extending access beyond role hierarchy

Setup: Setup > Security > Sharing Settings > Sharing Rules

Requirements
  • Objects with Private or Public Read Only OWD
  • Public groups or roles defined
  • Clear sharing criteria
Important Notes
  • Maximum 300 sharing rules per object
  • Rules run in background batch jobs
  • Can impact performance with large data volumes
Sharing Example

// 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());
    }
}

Manual Sharing

User-Initiated Sharing

Best for:
  • Temporary project collaboration
  • Executive access to specific records
  • Ad-hoc sharing for special circumstances
Scope & Implementation:
Record-Level

Ad-hoc sharing where record owners or users with sharing permissions grant access to specific users

Setup: Record Detail Page > Sharing Button

Requirments
  • Sharing permissions on the object
  •  Valid user or group to share with
  • Appropriate access level permissions
Manual Sharing Example

// 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());
  }
}

Account Teams & Opportunity Teams

Team-Based Sharing

Best for:
  • Sales team collaboration on accounts
  • Multi-department opportunity management
  • Customer success team access
Scope & Implementation:
organisationTeam-Based

Predefined team structures that automatically share related records with team members

Setup: Setup > Account Teams / Opportunity Teams

Requirements
  • Account Teams or Opportunity Teams enabled
  •  Team roles defined
  • Default team templates (optional)
Account Teams & Opportunity Teams Example

// 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());

Sharing Method Comparison

Choose the right sharing method based on your data access requirements

Method Comparison Table

Decision Tree

What level of sharing control do you need?

Basic organization-wide access: Organization-Wide Defaults

Hierarchical management access: Role Hierarchy

Complex business rules: Sharing Rules or Territory Management

Is sharing based on geography or territories?

Yes:Territory Management

No: Role Hierarchy or Sharing Rules

Implementation Tips

Performance Considerations

  •  OWD Changes: Can impact system performance
  • Sharing Rules: Run in background batch jobs
  • Manual Sharing: Immediate but can accumulate
  • Territory Management: Complex calculations

Best Practices

  • Start with OWD as your foundation
  • Use role hierarchy for management access
  • Implement sharing rules for systematic sharing
  • Use manual sharing sparingly
  • Monitor sharing performance regularly