Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion packages/@webex/plugin-meetings/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {registerPlugin} from '@webex/webex-core';

import Meetings from './meetings';
import config from './config';
import {LocusRetryStatusInterceptor} from './interceptors';
import {LocusRetryStatusInterceptor, LocusRouteTokenInterceptor} from './interceptors';
import CaptchaError from './common/errors/captcha-error';
import IntentToJoinError from './common/errors/intent-to-join';
import PasswordError from './common/errors/password-error';
Expand All @@ -23,6 +23,7 @@ registerPlugin('meetings', Meetings, {
config,
interceptors: {
LocusRetryStatusInterceptor: LocusRetryStatusInterceptor.create,
LocusRouteTokenInterceptor: LocusRouteTokenInterceptor.create,
},
});

Expand Down
3 changes: 2 additions & 1 deletion packages/@webex/plugin-meetings/src/interceptors/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import LocusRetryStatusInterceptor from './locusRetry';
import LocusRouteTokenInterceptor from './locusRouteToken';

export {LocusRetryStatusInterceptor};
export {LocusRetryStatusInterceptor, LocusRouteTokenInterceptor};
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*!
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
*/

import {Interceptor} from '@webex/http-core';
import {has} from 'lodash';

const LOCUS_ID_REGEX = /\/locus\/api\/v1\/loci\/([a-f0-9-]{36})/i;
const X_CISCO_PART_ROUTE_TOKEN = 'X-Cisco-Part-Route-Token';
const ROUTE_TOKEN = {};

/**
* @class LocusRouteTokenInterceptor
*/
export default class LocusRouteTokenInterceptor extends Interceptor {
/**
* @returns {LocusRouteTokenInterceptor}
*/
static create() {
// @ts-ignore
return new LocusRouteTokenInterceptor({webex: this});
}

getLocusIdByRequestUrl(url: string) {
return url?.match(LOCUS_ID_REGEX)?.[1];
}

/**
* @param {Object} options
* @param {HttpResponse} response
* @returns {Promise<HttpResponse>}
*/
onResponse(options, response) {
const locusId = this.getLocusIdByRequestUrl(options.uri);
if (locusId) {
const hasRouteToken = has(response.headers, X_CISCO_PART_ROUTE_TOKEN);
const token = response.headers[X_CISCO_PART_ROUTE_TOKEN];
if (hasRouteToken) {
this.updateToken(locusId, token);
}
}

return Promise.resolve(response);
}

/**
* @param {Object} options
* @returns {Promise<Object>} options
*/
onRequest(options) {
const locusId = this.getLocusIdByRequestUrl(options.uri);
if (locusId) {
const token = this.getToken(locusId);
if (token) {
options.headers[X_CISCO_PART_ROUTE_TOKEN] = token;
}
}

return Promise.resolve(options);
}

/**
* Update the meeting route token
* @param {string} locusId
* @param {string} token
* @returns {void}
*/
updateToken(locusId, token) {
ROUTE_TOKEN[locusId] = token;
}

/**
* Get the meeting route token
* @param {string} locusId
* @returns {string|undefined}
*/
getToken(locusId) {
return ROUTE_TOKEN[locusId];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*!
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
*/

/* eslint-disable camelcase */
import 'jsdom-global/register';
import {assert} from '@webex/test-helper-chai';
import MockWebex from '@webex/test-helper-mock-webex';
import {LocusRouteTokenInterceptor} from '@webex/plugin-meetings/src/interceptors';
import Meetings from '@webex/plugin-meetings';

const X_CISCO_PART_ROUTE_TOKEN = 'X-Cisco-Part-Route-Token';

describe('LocusRouteTokenInterceptor', () => {
let interceptor, webex;
const TEST_LOCUS_ID = '0f1eba56-91e2-2a11-9b2b-1e2da077f066';
beforeEach(() => {
webex = new MockWebex({
children: {
meetings: Meetings,
},
});
interceptor = Reflect.apply(LocusRouteTokenInterceptor.create, webex, []);
});

it('getLocusIdByRequestUrl should return locusId from url', () => {
const url = `https://locus-test.webex.com/locus/api/v1/loci/${TEST_LOCUS_ID}/foo`;
assert.equal(interceptor.getLocusIdByRequestUrl(url), TEST_LOCUS_ID);
});

it('getLocusIdByRequestUrl should return undefined when no locusId in url', () => {
const url = 'https://locus-test.webex.com/locus/api/v1/foo';
assert.isUndefined(interceptor.getLocusIdByRequestUrl(url));
});

it('getLocusIdByRequestUrl should return undefined when url is undefined', () => {
assert.isUndefined(interceptor.getLocusIdByRequestUrl(undefined));
});

it('onResponse should store route token when header exists', async () => {
const response = {
headers: {
[X_CISCO_PART_ROUTE_TOKEN]: 'test-token',
},
};

const result = await interceptor.onResponse(
{
uri: `https://locus-test.webex.com/locus/api/v1/loci/${TEST_LOCUS_ID}/foo`,
},
response
);
assert.equal(result, response);
assert.equal(interceptor.getToken(TEST_LOCUS_ID), 'test-token');
});

it('onResponse should not store token when header missing', async () => {
interceptor.updateToken(TEST_LOCUS_ID);
const response = {headers: {}};

await interceptor.onResponse({}, response);
assert.isUndefined(interceptor.getToken(TEST_LOCUS_ID));
});

it('onRequest should attach token to headers when token exists', async () => {
interceptor.updateToken(TEST_LOCUS_ID, 'abc123');

const options = {
headers: {},
uri: `https://locus-test.webex.com/locus/api/v1/loci/${TEST_LOCUS_ID}/foo`,
};
const result = await interceptor.onRequest(options);
assert.equal(result.headers[X_CISCO_PART_ROUTE_TOKEN], 'abc123');
});

it('onRequest should not attach token if none is stored', async () => {
interceptor.updateToken(TEST_LOCUS_ID);
const options = {headers: {}};
const result = await interceptor.onRequest(options);
assert.isUndefined(result.headers[X_CISCO_PART_ROUTE_TOKEN]);
});

it('updateToken & getToken should work as pair', () => {
interceptor.updateToken(TEST_LOCUS_ID, 'abc456');
assert.equal(interceptor.getToken(TEST_LOCUS_ID), 'abc456');
});
});
Loading