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
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 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});
}

getActiveMeetingId() {
// @ts-ignore
return this.webex.meetings.meetingCollection.getActiveWebrtcMeeting()?.id;
}

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

return Promise.resolve(response);
}

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

return Promise.resolve(options);
}

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

/**
* Get the meeting route token
* @param {string} meetingId
* @returns {string|undefined}
*/
getToken(meetingId) {
return ROUTE_TOKEN[meetingId];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*!
* 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_MEETING_ID = 'test-meeting-id';
beforeEach(() => {
webex = new MockWebex({
children: {
meetings: Meetings,
},
});
webex.meetings.meetingCollection.getActiveWebrtcMeeting = () => ({id: TEST_MEETING_ID});
interceptor = Reflect.apply(LocusRouteTokenInterceptor.create, webex, []);
});

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({}, response);
assert.equal(result, response);
assert.equal(interceptor.getToken(TEST_MEETING_ID), 'test-token');
});

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

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

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

const options = {headers: {}};
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_MEETING_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_MEETING_ID, 'abc456');
assert.equal(interceptor.getToken(TEST_MEETING_ID), 'abc456');
});
});
Loading