feat(dialout) check appId for permission to call outbound destination (#12871)
This commit is contained in:
parent
3e59359563
commit
84221c5c13
|
@ -1335,6 +1335,7 @@ var config = {
|
||||||
deploymentInfo
|
deploymentInfo
|
||||||
dialOutAuthUrl
|
dialOutAuthUrl
|
||||||
dialOutCodesUrl
|
dialOutCodesUrl
|
||||||
|
dialOutRegionUrl
|
||||||
disableRemoteControl
|
disableRemoteControl
|
||||||
displayJids
|
displayJids
|
||||||
externalConnectUrl
|
externalConnectUrl
|
||||||
|
|
|
@ -35,6 +35,11 @@ export type Props = {
|
||||||
*/
|
*/
|
||||||
_dialOutAuthUrl: string,
|
_dialOutAuthUrl: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL for validating if an outbound destination is allowed.
|
||||||
|
*/
|
||||||
|
_dialOutRegionUrl: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not to show Dial Out functionality.
|
* Whether or not to show Dial Out functionality.
|
||||||
*/
|
*/
|
||||||
|
@ -235,7 +240,9 @@ export default class AbstractAddPeopleDialog<P: Props, S: State>
|
||||||
_query(query = '') {
|
_query(query = '') {
|
||||||
const {
|
const {
|
||||||
_addPeopleEnabled: addPeopleEnabled,
|
_addPeopleEnabled: addPeopleEnabled,
|
||||||
|
_appId: appId,
|
||||||
_dialOutAuthUrl: dialOutAuthUrl,
|
_dialOutAuthUrl: dialOutAuthUrl,
|
||||||
|
_dialOutRegionUrl: dialOutRegionUrl,
|
||||||
_dialOutEnabled: dialOutEnabled,
|
_dialOutEnabled: dialOutEnabled,
|
||||||
_jwt: jwt,
|
_jwt: jwt,
|
||||||
_peopleSearchQueryTypes: peopleSearchQueryTypes,
|
_peopleSearchQueryTypes: peopleSearchQueryTypes,
|
||||||
|
@ -244,8 +251,10 @@ export default class AbstractAddPeopleDialog<P: Props, S: State>
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const options = {
|
const options = {
|
||||||
addPeopleEnabled,
|
addPeopleEnabled,
|
||||||
|
appId,
|
||||||
dialOutAuthUrl,
|
dialOutAuthUrl,
|
||||||
dialOutEnabled,
|
dialOutEnabled,
|
||||||
|
dialOutRegionUrl,
|
||||||
jwt,
|
jwt,
|
||||||
peopleSearchQueryTypes,
|
peopleSearchQueryTypes,
|
||||||
peopleSearchUrl,
|
peopleSearchUrl,
|
||||||
|
@ -275,14 +284,17 @@ export function _mapStateToProps(state: Object) {
|
||||||
const {
|
const {
|
||||||
callFlowsEnabled,
|
callFlowsEnabled,
|
||||||
dialOutAuthUrl,
|
dialOutAuthUrl,
|
||||||
|
dialOutRegionUrl,
|
||||||
peopleSearchQueryTypes,
|
peopleSearchQueryTypes,
|
||||||
peopleSearchUrl
|
peopleSearchUrl
|
||||||
} = state['features/base/config'];
|
} = state['features/base/config'];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_addPeopleEnabled: isAddPeopleEnabled(state),
|
_addPeopleEnabled: isAddPeopleEnabled(state),
|
||||||
|
_appId: state['features/base/jwt']?.tenant,
|
||||||
_callFlowsEnabled: callFlowsEnabled,
|
_callFlowsEnabled: callFlowsEnabled,
|
||||||
_dialOutAuthUrl: dialOutAuthUrl,
|
_dialOutAuthUrl: dialOutAuthUrl,
|
||||||
|
_dialOutRegionUrl: dialOutRegionUrl,
|
||||||
_dialOutEnabled: isDialOutEnabled(state),
|
_dialOutEnabled: isDialOutEnabled(state),
|
||||||
_jwt: state['features/base/jwt'].jwt,
|
_jwt: state['features/base/jwt'].jwt,
|
||||||
_peopleSearchQueryTypes: peopleSearchQueryTypes,
|
_peopleSearchQueryTypes: peopleSearchQueryTypes,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { isJwtFeatureEnabled } from '../base/jwt/functions';
|
||||||
import { JitsiRecordingConstants } from '../base/lib-jitsi-meet';
|
import { JitsiRecordingConstants } from '../base/lib-jitsi-meet';
|
||||||
import { getLocalParticipant, isLocalParticipantModerator } from '../base/participants/functions';
|
import { getLocalParticipant, isLocalParticipantModerator } from '../base/participants/functions';
|
||||||
import { toState } from '../base/redux/functions';
|
import { toState } from '../base/redux/functions';
|
||||||
|
import { doGetJSON } from '../base/util/httpUtils';
|
||||||
import { parseURLParams } from '../base/util/parseURLParams';
|
import { parseURLParams } from '../base/util/parseURLParams';
|
||||||
import {
|
import {
|
||||||
StatusCode,
|
StatusCode,
|
||||||
|
@ -55,6 +56,34 @@ export function checkDialNumber(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends an ajax request to check if the outbound call is permitted.
|
||||||
|
*
|
||||||
|
* @param {string} dialOutRegionUrl - The config endpoint.
|
||||||
|
* @param {string} jwt - The jwt token.
|
||||||
|
* @param {string} appId - The customer id.
|
||||||
|
* @param {string} phoneNumber - The destination phone number.
|
||||||
|
* @returns {Promise} - The promise created by the request.
|
||||||
|
*/
|
||||||
|
export function checkOutboundDestination(
|
||||||
|
dialOutRegionUrl: string,
|
||||||
|
jwt: string,
|
||||||
|
appId: string,
|
||||||
|
phoneNumber: string
|
||||||
|
): Promise<any> {
|
||||||
|
return doGetJSON(dialOutRegionUrl, true, {
|
||||||
|
body: JSON.stringify({
|
||||||
|
appId,
|
||||||
|
phoneNumber
|
||||||
|
}),
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${jwt}`,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all non-numeric characters from a string.
|
* Removes all non-numeric characters from a string.
|
||||||
*
|
*
|
||||||
|
@ -76,6 +105,11 @@ export type GetInviteResultsOptions = {
|
||||||
*/
|
*/
|
||||||
addPeopleEnabled: boolean;
|
addPeopleEnabled: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The customer id.
|
||||||
|
*/
|
||||||
|
appId: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The endpoint to use for checking phone number validity.
|
* The endpoint to use for checking phone number validity.
|
||||||
*/
|
*/
|
||||||
|
@ -86,6 +120,11 @@ export type GetInviteResultsOptions = {
|
||||||
*/
|
*/
|
||||||
dialOutEnabled: boolean;
|
dialOutEnabled: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The endpoint to use for checking dial permission to an outbound destination.
|
||||||
|
*/
|
||||||
|
dialOutRegionUrl: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The jwt token to pass to the search service.
|
* The jwt token to pass to the search service.
|
||||||
*/
|
*/
|
||||||
|
@ -123,8 +162,10 @@ export function getInviteResultsForQuery(
|
||||||
const text = query.trim();
|
const text = query.trim();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
dialOutAuthUrl,
|
|
||||||
addPeopleEnabled,
|
addPeopleEnabled,
|
||||||
|
appId,
|
||||||
|
dialOutAuthUrl,
|
||||||
|
dialOutRegionUrl,
|
||||||
dialOutEnabled,
|
dialOutEnabled,
|
||||||
peopleSearchQueryTypes,
|
peopleSearchQueryTypes,
|
||||||
peopleSearchUrl,
|
peopleSearchUrl,
|
||||||
|
@ -187,7 +228,7 @@ export function getInviteResultsForQuery(
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all([ peopleSearchPromise, phoneNumberPromise ])
|
return Promise.all([ peopleSearchPromise, phoneNumberPromise ])
|
||||||
.then(([ peopleResults, phoneResults ]) => {
|
.then(async ([ peopleResults, phoneResults ]) => {
|
||||||
const results: any[] = [
|
const results: any[] = [
|
||||||
...peopleResults
|
...peopleResults
|
||||||
];
|
];
|
||||||
|
@ -203,14 +244,26 @@ export function getInviteResultsForQuery(
|
||||||
= peopleResults.find(result => result.type === INVITE_TYPES.PHONE);
|
= peopleResults.find(result => result.type === INVITE_TYPES.PHONE);
|
||||||
|
|
||||||
if (!hasPhoneResult && typeof phoneResults.allow === 'boolean') {
|
if (!hasPhoneResult && typeof phoneResults.allow === 'boolean') {
|
||||||
results.push({
|
const result = {
|
||||||
allowed: phoneResults.allow,
|
allowed: phoneResults.allow,
|
||||||
country: phoneResults.country,
|
country: phoneResults.country,
|
||||||
type: INVITE_TYPES.PHONE,
|
type: INVITE_TYPES.PHONE,
|
||||||
number: phoneResults.phone,
|
number: phoneResults.phone,
|
||||||
originalEntry: text,
|
originalEntry: text,
|
||||||
showCountryCodeReminder: !hasCountryCode
|
showCountryCodeReminder: !hasCountryCode
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (!phoneResults.allow) {
|
||||||
|
try {
|
||||||
|
const response = await checkOutboundDestination(dialOutRegionUrl, jwt, appId, text);
|
||||||
|
|
||||||
|
result.allowed = response.allowed;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error checking permission to dial to outbound destination', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
results.push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sipInviteEnabled && isASipAddress(text)) {
|
if (sipInviteEnabled && isASipAddress(text)) {
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
"include": ["react/features/**/*.ts", "react/features/**/*.tsx", "./custom.d.ts", "./globals.native.d.ts"],
|
"include": ["react/features/**/*.ts", "react/features/**/*.tsx", "./custom.d.ts", "./globals.native.d.ts"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"target": "ESNext",
|
"target": "es2020",
|
||||||
"jsx": "react-native",
|
"jsx": "react-native",
|
||||||
"lib": [ "ES2017"],
|
"lib": [ "es2020"],
|
||||||
"types": [ "react-native" ],
|
"types": [ "react-native" ],
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"moduleResolution": "Node",
|
"moduleResolution": "Node",
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
"include": ["react/features/**/*.ts", "react/features/**/*.tsx", "./custom.d.ts", "./globals.d.ts"],
|
"include": ["react/features/**/*.ts", "react/features/**/*.tsx", "./custom.d.ts", "./globals.d.ts"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"module": "es6",
|
"module": "es2020",
|
||||||
"target": "es6",
|
"target": "es2020",
|
||||||
"jsx": "react",
|
"jsx": "react",
|
||||||
"lib": [ "webworker", "ES2020", "DOM" ],
|
"lib": [ "webworker", "ES2020", "DOM" ],
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|
Loading…
Reference in New Issue