Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(conversation): config encrypt decrypt payload transforms #3977

Open
wants to merge 4 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
10 changes: 10 additions & 0 deletions packages/@webex/internal-plugin-conversation/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,15 @@ export default {
*/
keepEncryptedProperties: false,
decryptionFailureMessage: 'This message cannot be decrypted',

/**
* config value to perform decryption on inbound conversations and activities
*/
includeDecryptionTransforms: true,

/**
* config value to perform decryption on outbound conversations and activities
*/
includeEncryptionTransforms: true,
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import {
} from 'lodash';
import {readExifData} from '@webex/helper-image';
import uuid from 'uuid';
import {transforms as encryptionTransforms} from './encryption-transforms';
import {transforms as decryptionTransforms} from './decryption-transforms';

import {InvalidUserCreation} from './convo-error';
import ShareActivity from './share-activity';
Expand Down Expand Up @@ -77,6 +79,16 @@ const getConvoLimit = (options = {}) => {

const Conversation = WebexPlugin.extend({
namespace: 'Conversation',
initialize() {
this.listenToOnce(this.webex, 'ready', () => {
if (Array.isArray(this.webex.config.payloadTransformer?.transforms)) {
this.webex.config.payloadTransformer.transforms =
this.webex.config.payloadTransformer.transforms
.concat(this.config.includeDecryptionTransforms ? decryptionTransforms : [])
.concat(this.config.includeEncryptionTransforms ? encryptionTransforms : []);
}
});
},

/**
* @param {String} cluster the cluster containing the id
Expand Down
6 changes: 1 addition & 5 deletions packages/@webex/internal-plugin-conversation/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import {capitalize, get, has} from 'lodash';

import Conversation from './conversation';
import config from './config';
import {transforms as encryptionTransforms} from './encryption-transforms';
import {transforms as decryptionTransforms} from './decryption-transforms';

registerInternalPlugin('conversation', Conversation, {
payloadTransformer: {
Expand Down Expand Up @@ -315,9 +313,7 @@ registerInternalPlugin('conversation', Conversation, {
});
},
},
]
.concat(decryptionTransforms)
.concat(encryptionTransforms),
],
},
config,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
activityManager,
} from '../../../src/activity-thread-ordering';
import {ACTIVITY_TYPES, getActivityType, OLDER, NEWER} from '../../../src/activities';
import {transforms as encryptionTransforms} from '../../../src/encryption-transforms';
import {transforms as decryptionTransforms} from '../../../src/decryption-transforms';

describe('plugin-conversation', () => {
describe('Conversation', () => {
Expand All @@ -38,39 +40,36 @@ describe('plugin-conversation', () => {
it('should add recipients to the payload if provided', () => {
const {conversation} = webex.internal;
const recipientId = 'example-recipient-id';
const expected = {items: [{id: recipientId, objectType: 'person'}]}
conversation.sendReaction = sinon.stub().returns(Promise.resolve())
conversation.createReactionHmac = sinon.stub().returns(Promise.resolve('hmac'))

return conversation.addReaction({}, 'example-display-name', {}, recipientId)
.then(() => {
assert.deepEqual(conversation.sendReaction.args[0][1].recipients, expected);
});
const expected = {items: [{id: recipientId, objectType: 'person'}]};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

most of these changes are just whitespace/formatting changes, except for the added new describe block

conversation.sendReaction = sinon.stub().returns(Promise.resolve());
conversation.createReactionHmac = sinon.stub().returns(Promise.resolve('hmac'));

return conversation.addReaction({}, 'example-display-name', {}, recipientId).then(() => {
assert.deepEqual(conversation.sendReaction.args[0][1].recipients, expected);
});
});
});

describe('deleteReaction()', () => {
it('should add recipients to the payload if provided', () => {
const {conversation} = webex.internal;
const recipientId = 'example-recipient-id';
const expected = {items: [{id: recipientId, objectType: 'person'}]}
conversation.sendReaction = sinon.stub().returns(Promise.resolve())

return conversation.deleteReaction({}, 'example-reaction-id', recipientId)
.then(() => {
assert.deepEqual(conversation.sendReaction.args[0][1].recipients, expected);
});
const expected = {items: [{id: recipientId, objectType: 'person'}]};
conversation.sendReaction = sinon.stub().returns(Promise.resolve());

return conversation.deleteReaction({}, 'example-reaction-id', recipientId).then(() => {
assert.deepEqual(conversation.sendReaction.args[0][1].recipients, expected);
});
});
});

describe('prepare()', () => {
it('should ammend activity recipients to the returned object', () => {
const {conversation} = webex.internal;
const activity = { recipients: 'example-recipients' };
const activity = {recipients: 'example-recipients'};

return conversation.prepare(activity)
.then((results) => {
assert.deepEqual(results.recipients, activity.recipients);
return conversation.prepare(activity).then((results) => {
assert.deepEqual(results.recipients, activity.recipients);
});
});
});
Expand All @@ -79,39 +78,36 @@ describe('plugin-conversation', () => {
it('should add recipients to the payload if provided', () => {
const {conversation} = webex.internal;
const recipientId = 'example-recipient-id';
const expected = {items: [{id: recipientId, objectType: 'person'}]}
conversation.sendReaction = sinon.stub().returns(Promise.resolve())
conversation.createReactionHmac = sinon.stub().returns(Promise.resolve('hmac'))

return conversation.addReaction({}, 'example-display-name', {}, recipientId)
.then(() => {
assert.deepEqual(conversation.sendReaction.args[0][1].recipients, expected);
});
const expected = {items: [{id: recipientId, objectType: 'person'}]};
conversation.sendReaction = sinon.stub().returns(Promise.resolve());
conversation.createReactionHmac = sinon.stub().returns(Promise.resolve('hmac'));

return conversation.addReaction({}, 'example-display-name', {}, recipientId).then(() => {
assert.deepEqual(conversation.sendReaction.args[0][1].recipients, expected);
});
});
});

describe('deleteReaction()', () => {
it('should add recipients to the payload if provided', () => {
const {conversation} = webex.internal;
const recipientId = 'example-recipient-id';
const expected = {items: [{id: recipientId, objectType: 'person'}]}
conversation.sendReaction = sinon.stub().returns(Promise.resolve())

return conversation.deleteReaction({}, 'example-reaction-id', recipientId)
.then(() => {
assert.deepEqual(conversation.sendReaction.args[0][1].recipients, expected);
});
const expected = {items: [{id: recipientId, objectType: 'person'}]};
conversation.sendReaction = sinon.stub().returns(Promise.resolve());

return conversation.deleteReaction({}, 'example-reaction-id', recipientId).then(() => {
assert.deepEqual(conversation.sendReaction.args[0][1].recipients, expected);
});
});
});

describe('prepare()', () => {
it('should ammend activity recipients to the returned object', () => {
const {conversation} = webex.internal;
const activity = { recipients: 'example-recipients' };
const activity = {recipients: 'example-recipients'};

return conversation.prepare(activity)
.then((results) => {
assert.deepEqual(results.recipients, activity.recipients);
return conversation.prepare(activity).then((results) => {
assert.deepEqual(results.recipients, activity.recipients);
});
});
});
Expand Down Expand Up @@ -220,13 +216,17 @@ describe('plugin-conversation', () => {
it('should convert a "us" cluster to WEBEX_CONVERSATION_DEFAULT_CLUSTER cluster', async () => {
await webex.internal.conversation.getUrlFromClusterId({cluster: 'us'});

sinon.assert.calledWith(webex.internal.services.getServiceUrlFromClusterId, {cluster: 'us'});
sinon.assert.calledWith(webex.internal.services.getServiceUrlFromClusterId, {
cluster: 'us',
});
});

it('should add the cluster service when missing', async () => {
await webex.internal.conversation.getUrlFromClusterId({cluster: 'urn:TEAM:us-west-2_r'});

sinon.assert.calledWith(webex.internal.services.getServiceUrlFromClusterId, {cluster: 'urn:TEAM:us-west-2_r'});
sinon.assert.calledWith(webex.internal.services.getServiceUrlFromClusterId, {
cluster: 'urn:TEAM:us-west-2_r',
});
});
});

Expand Down Expand Up @@ -902,4 +902,59 @@ describe('plugin-conversation', () => {
});
});
});
describe('#payloadTransform encrypt/decrypt', () => {
let webex;
let conversation;

const setup = (options = {}) => {
const {includeDecryptionTransforms, includeEncryptionTransforms} = options;
webex = new MockWebex({
children: {
conversation: Conversation,
},
});
webex.config.payloadTransformer = {transforms: []};
conversation = webex.internal.conversation;
conversation.config.includeDecryptionTransforms = !!includeDecryptionTransforms;
conversation.config.includeEncryptionTransforms = !!includeEncryptionTransforms;
};

const checkTransforms = (receivedTransforms, expectedTransforms) =>
receivedTransforms
.map((transform) => transform.name)
.every((name) => expectedTransforms.map((transform) => transform.name).includes(name));

it.each([
{
includeDecryptionTransforms: false,
includeEncryptionTransforms: false,
expectedTransforms: [],
},
{
includeDecryptionTransforms: false,
includeEncryptionTransforms: true,
expectedTransforms: encryptionTransforms,
},
{
includeDecryptionTransforms: true,
includeEncryptionTransforms: false,
expectedTransforms: decryptionTransforms,
},
{
includeDecryptionTransforms: true,
includeEncryptionTransforms: true,
expectedTransforms: encryptionTransforms.concat(decryptionTransforms),
},
])(
'%s sets initFailed to true when collectPreauthCatalog errors',
async ({includeDecryptionTransforms, includeEncryptionTransforms, expectedTransforms}) => {
robstax marked this conversation as resolved.
Show resolved Hide resolved
setup({includeDecryptionTransforms, includeEncryptionTransforms});
webex.trigger('ready');
assert.isTrue(
checkTransforms(webex.config.payloadTransformer.transforms, expectedTransforms),
'transforms should match expected configuration'
);
}
);
});
});
Loading