RestrictCallHandlers
What It Does
Controls which call handlers — and therefore which calls — the running user is allowed to see.
The handler restriction is evaluated at the start of every timeline request and applied as a SOQL filter. It restricts visibility by the Salesforce User linked to each PhoneCallHandler__c record (PhoneCallHandler__c.User__c).
The default implementation allows users with the CallCore_ViewAllCalls permission to see all handlers. Users without that permission can only see calls where they are the matched handler.
Implement RestrictCallHandlers.IStrategy to introduce team-based, role-based, or any other custom restriction logic.
Interface
global interface IStrategy {
void getAllowed(Context context);
}
Context
Input
The Context has no input fields. Use UserInfo.getUserId(), UserInfo.getProfileId(), or SOQL queries to determine what the running user is allowed to see.
Write Methods
Call exactly one of these before returning. If you call none, the default is allowAll().
| Method | Description |
|---|---|
allowAll() |
No restriction — all handlers are visible. |
allowSingle(Id id) |
Allow exactly one handler user ID. Throws if id is null. |
allowSet(Set<Id> ids) |
Allow a specific set of handler user IDs. Throws if ids is null. An empty set means no handlers are allowed. |
excludeAll() |
Allow no handlers — no calls will be visible to the user. |
The Id values passed to allowSingle and allowSet are User IDs (the linked Salesforce user), not PhoneCallHandler__c record IDs.
Discriminator
This strategy has no SObject discriminator. There is one global implementation per org. Use default as the discriminator value.
Default Behaviour
- If the user has
CallCore_ViewAllCalls(or any permission that implies it):allowAll(). - Otherwise:
allowSingle(UserInfo.getUserId())— the user sees only their own calls.
Example: Restrict by Salesforce Role
Allow users to see calls handled by anyone in their role or below in the role hierarchy.
public class RestrictHandlersToRoleHierarchy
implements callcoreio.RestrictCallHandlers.IStrategy {
public void getAllowed(callcoreio.RestrictCallHandlers.Context context) {
if (hasViewAllPermission()) {
context.allowAll();
return;
}
Id roleId = UserInfo.getUserRoleId();
if (roleId == null) {
context.allowSingle(UserInfo.getUserId());
return;
}
Set<Id> subordinateRoleIds = getSubordinateRoleIds(roleId);
subordinateRoleIds.add(roleId);
List<User> users = [
SELECT Id FROM User
WHERE IsActive = true AND UserRoleId IN :subordinateRoleIds
];
Set<Id> allowedUserIds = new Set<Id>();
for (User u : users) allowedUserIds.add(u.Id);
context.allowSet(allowedUserIds);
}
private Boolean hasViewAllPermission() {
return FeatureManagement.checkPermission('CallCore_ViewAllCalls');
}
private Set<Id> getSubordinateRoleIds(Id rootRoleId) {
Set<Id> result = new Set<Id>();
List<UserRole> roles = [SELECT Id FROM UserRole WHERE ParentRoleId = :rootRoleId];
for (UserRole r : roles) {
result.add(r.Id);
result.addAll(getSubordinateRoleIds(r.Id));
}
return result;
}
}
Example: Restrict by Custom Group Membership
Allow users to see calls handled by members of a custom CallTeam__c object that links to User.
public class RestrictHandlersToCallTeam
implements callcoreio.RestrictCallHandlers.IStrategy {
public void getAllowed(callcoreio.RestrictCallHandlers.Context context) {
if (FeatureManagement.checkPermission('CallCore_ViewAllCalls')) {
context.allowAll();
return;
}
List<CallTeamMember__c> teammates = [
SELECT TeamUser__c
FROM CallTeamMember__c
WHERE Team__r.Members__r.User__c = :UserInfo.getUserId()
];
if (teammates.isEmpty()) {
context.allowSingle(UserInfo.getUserId());
return;
}
Set<Id> teamUserIds = new Set<Id>();
for (CallTeamMember__c m : teammates) teamUserIds.add(m.TeamUser__c);
teamUserIds.add(UserInfo.getUserId());
context.allowSet(teamUserIds);
}
}
Notes
- Fail safely: if your query fails or returns unexpected results, consider whether
allowSingle(own calls only) orexcludeAllis the right fallback. The framework defaults toexcludeAllon unhandled exceptions to prevent accidental over-exposure. - The restriction is evaluated once per timeline request, not once per call record. Keep the implementation efficient — avoid nested loops and limit SOQL queries.
- The
allowSetandallowSinglevalues are User IDs. There is no way to allow aPhoneCallHandler__crecord that has no linked User — unlinking a handler from a User removes them from all restricted views. - If both
RestrictCallHandlersandRestrictSourcesare configured, both filters are applied. A call must pass both restrictions to appear in the timeline.