Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/@webex/contact-center/src/cc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,11 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
METRIC_EVENT_NAMES.STATION_LOGIN_FAILED,
]);

if (data.loginOption === LoginOption.AGENT_DN && !isValidDialNumber(data.dialNumber)) {
const dialPlanEntries = this.agentConfig?.dialPlan?.dialPlanEntity ?? [];
if (
data.loginOption === LoginOption.AGENT_DN &&
!isValidDialNumber(data.dialNumber, dialPlanEntries)
) {
const error = new Error('INVALID_DIAL_NUMBER');
// @ts-ignore - adding custom key to the error object
error.details = {data: {reason: 'INVALID_DIAL_NUMBER'}} as Failure;
Expand Down
35 changes: 30 additions & 5 deletions packages/@webex/contact-center/src/services/core/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Interaction,
} from '../task/types';
import {PARTICIPANT_TYPES, STATE_CONSULT} from './constants';
import {DialPlan} from '../config/types';

/**
* Extracts common error details from a Webex request payload.
Expand Down Expand Up @@ -48,11 +49,35 @@ const getAgentActionTypeFromTask = (taskData?: TaskData): 'DIAL_NUMBER' | '' =>
return isDialNumber || isEntryPointVariant ? 'DIAL_NUMBER' : '';
};

export const isValidDialNumber = (input: string): boolean => {
// This regex checks for a valid dial number format for only few countries such as US, Canada.
const regexForDn = /1[0-9]{3}[2-9][0-9]{6}([,]{1,10}[0-9]+){0,1}/;
// Fallback regex for US/Canada dial numbers when no dial plan entries are configured
const FALLBACK_DIAL_NUMBER_REGEX = /1[0-9]{3}[2-9][0-9]{6}([,]{1,10}[0-9]+){0,1}/;

return regexForDn.test(input);
/**
* Validates a dial number against the provided dial plan regex patterns.
* A number is valid if it matches at least one regex pattern in the dial plans.
* Falls back to US/Canada regex validation if no dial plan entries are configured.
*
* @param input - The dial number to validate
* @param dialPlanEntries - Array of dial plan entries containing regex patterns
* @returns true if the input matches at least one dial plan regex pattern, false otherwise
*/
export const isValidDialNumber = (
input: string,
dialPlanEntries: DialPlan['dialPlanEntity']
): boolean => {
if (!dialPlanEntries || dialPlanEntries.length === 0) {
return FALLBACK_DIAL_NUMBER_REGEX.test(input);
}

return dialPlanEntries.some((entry) => {
try {
const regex = new RegExp(entry.regex);

return regex.test(input);
} catch {
return false;
}
});
};

export const getStationLoginErrorData = (failure: Failure, loginOption: LoginOption) => {
Expand All @@ -74,7 +99,7 @@ export const getStationLoginErrorData = (failure: Failure, loginOption: LoginOpt
},
INVALID_DIAL_NUMBER: {
message:
'Enter a valid US dial number. For help, reach out to your administrator or support team.',
'Enter a valid dial number. For help, reach out to your administrator or support team.',
fieldName: loginOption,
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ describe('Utils', () => {
const result = Utils.getStationLoginErrorData(failure, LoginOption.AGENT_DN);
expect(result).toEqual({
message:
'Enter a valid US dial number. For help, reach out to your administrator or support team.',
'Enter a valid dial number. For help, reach out to your administrator or support team.',
fieldName: LoginOption.AGENT_DN,
});
});
Expand Down Expand Up @@ -557,4 +557,89 @@ describe('Utils', () => {
});
});

describe('isValidDialNumber', () => {
const anyFormatEntry = {
name: 'Any Format',
prefix: '',
regex: '([0-9a-zA-Z]+[-._])*[0-9a-zA-Z]+',
strippedChars: '( )-',
};

const usOnlyEntry = {
name: 'US',
prefix: '1',
regex: '1[0-9]{3}[2-9][0-9]{6}([,]{1,10}[0-9]+){0,1}',
strippedChars: '( )-',
};

describe('with multiple dial plan entries (Any Format + US)', () => {
const dialPlanEntries = [anyFormatEntry, usOnlyEntry];

it('should return true for a valid US phone number', () => {
const result = Utils.isValidDialNumber('12223334567', dialPlanEntries);
expect(result).toBe(true);
});

it('should return true for a UK phone number', () => {
const result = Utils.isValidDialNumber('+442030484377', dialPlanEntries);
expect(result).toBe(true);
});

it('should return true for alphanumeric format', () => {
const result = Utils.isValidDialNumber('user.name', dialPlanEntries);
expect(result).toBe(true);
});
});

describe('with US-only dial plan entry', () => {
const dialPlanEntries = [usOnlyEntry];

it('should return true for a valid US phone number', () => {
const result = Utils.isValidDialNumber('12223334567', dialPlanEntries);
expect(result).toBe(true);
});

it('should return false for a UK phone number', () => {
const result = Utils.isValidDialNumber('+442030484377', dialPlanEntries);
expect(result).toBe(false);
});

it('should return false for an invalid US number format', () => {
const result = Utils.isValidDialNumber('1234567890', dialPlanEntries);
expect(result).toBe(false);
});
});

describe('with empty dial plan entries (fallback to US regex)', () => {
it('should return true for a valid US phone number', () => {
const result = Utils.isValidDialNumber('12223334567', []);
expect(result).toBe(true);
});

it('should return false for a UK phone number', () => {
const result = Utils.isValidDialNumber('+442030484377', []);
expect(result).toBe(false);
});
});

describe('with invalid regex in dial plan entry', () => {
const invalidRegexEntry = {
name: 'Invalid',
prefix: '',
regex: '[invalid(regex',
strippedChars: '',
};

it('should return false when regex is invalid and no other entries match', () => {
const result = Utils.isValidDialNumber('12223334567', [invalidRegexEntry]);
expect(result).toBe(false);
});

it('should return true if another valid entry matches', () => {
const result = Utils.isValidDialNumber('12223334567', [invalidRegexEntry, usOnlyEntry]);
expect(result).toBe(true);
});
});
});

});
Loading