RestrictSources

What It Does

Controls which call sources (phone lines / Source__c records) the running user is allowed to see.

The source restriction is evaluated at the start of every timeline request and applied as a SOQL filter alongside the handler restriction. A call only appears if both the source restriction and the handler restriction are satisfied.

The default implementation allows all sources. Implement RestrictSources.IStrategy to restrict users to a subset of sources — for example, to the lines associated with their department or office.

Interface

global interface IStrategy {
    void getAllowed(Context context);
}

Context

Input

The Context has no input fields. Use UserInfo.getUserId(), custom metadata, custom settings, or SOQL queries against your own org data to determine which sources the running user may access.

Write Methods

Call one of these before returning. If you call none, the default is allow-all (all sources visible).

Method Description
allowSingle(Id id) Allow exactly one Source__c record ID. Throws if id is null.
allowSet(Set<Id> ids) Allow a specific set of Source__c record IDs. Throws if ids is null. An empty set means no sources are allowed.
excludeAll() Allow no sources — no calls will be visible to the user.

Unlike RestrictCallHandlers, there is no explicit allowAll() method. Simply do not call any write method and the framework treats the result as allow-all.

The Id values must be Source__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

Allow all sources (AnySource implementation — no filtering applied).

Example: Restrict Sources by Custom Metadata Mapping

Use custom metadata to map each Salesforce Profile to a set of allowed source routes.

public class RestrictSourcesByProfile
    implements callcoreio.RestrictSources.IStrategy {

    public void getAllowed(callcoreio.RestrictSources.Context context) {
        Id profileId = UserInfo.getProfileId();

        // SourceProfileAccess__mdt has fields: ProfileId__c, SourceRoute__c
        List<SourceProfileAccess__mdt> rules = [
            SELECT SourceRoute__c
            FROM SourceProfileAccess__mdt
            WHERE ProfileId__c = :profileId
        ];

        if (rules.isEmpty()) {
            // No rules configured for this profile — allow all
            return;
        }

        Set<String> allowedRoutes = new Set<String>();
        for (SourceProfileAccess__mdt r : rules) allowedRoutes.add(r.SourceRoute__c);

        List<Source__c> sources = [
            SELECT Id FROM callcoreio__Source__c
            WHERE callcoreio__Route__c IN :allowedRoutes
        ];

        Set<Id> allowedIds = new Set<Id>();
        for (Source__c s : sources) allowedIds.add(s.Id);

        if (allowedIds.isEmpty()) {
            context.excludeAll();
        } else {
            context.allowSet(allowedIds);
        }
    }
}

Example: Restrict to a Single Named Source

Allow only calls that came through a specific phone line, identified by its Route__c external ID.

public class RestrictToSalesLine
    implements callcoreio.RestrictSources.IStrategy {

    private static final String SALES_ROUTE = 'sales.main';

    public void getAllowed(callcoreio.RestrictSources.Context context) {
        List<Source__c> sources = [
            SELECT Id FROM callcoreio__Source__c
            WHERE callcoreio__Route__c = :SALES_ROUTE
            LIMIT 1
        ];

        if (sources.isEmpty()) {
            context.excludeAll();
        } else {
            context.allowSingle(sources[0].Id);
        }
    }
}

Notes

  • Fail closed. If your implementation throws an unhandled exception, the framework calls excludeAll() and the user sees no calls. Design your logic to be defensive.
  • Sources are identified by their Source__c record ID (not by Route__c or any other field). You will typically need a SOQL query to translate route names or metadata values into record IDs.
  • In the subscriber org, the Source__c object API name is callcoreio__Source__c and the Route__c field is callcoreio__Route__c. Adjust your queries accordingly.
  • If both RestrictSources and RestrictCallHandlers are configured, both must pass. A call on an allowed source handled by a restricted handler will not appear.
  • A warning is logged if your strategy results in an allow-none state. If the timeline is empty for all users and debug mode is off, check whether RestrictSources or RestrictCallHandlers is returning an empty restriction.