@webex/internal-plugin-ediscovery 2.59.2 → 2.59.3-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,496 +1,496 @@
1
- import EDiscovery from '@webex/internal-plugin-ediscovery';
2
- import Transforms from '@webex/internal-plugin-ediscovery/src/transforms';
3
- import ReportRequest from '@webex/internal-plugin-ediscovery/src/report-request';
4
- import MockWebex from '@webex/test-helper-mock-webex';
5
- import sinon from 'sinon';
6
- import {assert} from '@webex/test-helper-chai';
7
- import config from '@webex/internal-plugin-ediscovery/src/config';
8
-
9
- /* eslint-disable max-len */
10
- describe('EDiscovery Transform Tests', () => {
11
- const encryptedText = 'this text has been encrypted';
12
- const decryptedText = 'this text has been decrypted';
13
- const decryptedScr = 'this scr has been decrypted';
14
- const uuid = 'e20d6180-2b95-11e9-8f7a-59e7a3b4e375';
15
- const keyUri = 'kms://ciscospark.com/keys/32471db7-3d71-4fd1-b36c-0a1fe9efae2d';
16
-
17
- const ctx = {transform: sinon.stub().returns(Promise.resolve())};
18
- let object;
19
-
20
- beforeEach(() => {
21
- ctx.webex = new MockWebex({children: {ediscovery: EDiscovery}});
22
- ctx.webex.config.ediscovery = config.ediscovery;
23
- ctx.webex.internal = {
24
- device: {
25
- deviceType: 'FAKE_DEVICE',
26
- },
27
- encryption: {
28
- encryptText: sinon.stub().returns(Promise.resolve(encryptedText)),
29
- decryptText: sinon.stub().returns(Promise.resolve(decryptedText)),
30
- decryptScr: sinon.stub().returns(Promise.resolve(decryptedScr)),
31
- kms: {
32
- createUnboundKeys: sinon.stub().returns(Promise.resolve([{userIds: uuid, uri: keyUri}])),
33
- createResource: sinon.stub().returns(Promise.resolve()),
34
- },
35
- },
36
- };
37
- });
38
-
39
- afterEach(() => {
40
- ctx.transform.resetHistory();
41
- ctx.webex.internal.encryption.encryptText.resetHistory();
42
- ctx.webex.internal.encryption.decryptText.resetHistory();
43
- ctx.webex.internal.encryption.decryptScr.resetHistory();
44
- ctx.webex.internal.encryption.kms.createUnboundKeys.resetHistory();
45
- ctx.webex.internal.encryption.kms.createResource.resetHistory();
46
- });
47
-
48
- describe('Report Request Transforms', () => {
49
- let reportRequest;
50
-
51
- beforeEach(() => {
52
- reportRequest = new ReportRequest();
53
- reportRequest.name = 'test report';
54
- reportRequest.description = '';
55
- reportRequest.spaceNames = ['test space 1'];
56
- reportRequest.emails = ['email1@test.com', 'email2@test.com'];
57
- reportRequest.keywords = [];
58
- });
59
-
60
- describe('Encrypt ReportRequest Tests', () => {
61
- it('Calls the correct encrypt functions when transforming a report request', () => {
62
- // body IS a ReportRequest
63
- object = {body: reportRequest};
64
- const result = Transforms.encryptReportRequest(ctx, object).then(() => {
65
- assert.callCount(ctx.webex.internal.encryption.encryptText, 4);
66
- assert.equal(reportRequest.name, encryptedText);
67
- assert.equal(reportRequest.description, '');
68
- assert.equal(reportRequest.spaceNames[0], encryptedText);
69
- assert.equal(reportRequest.emails[0], encryptedText);
70
- assert.equal(reportRequest.emails[1], encryptedText);
71
- // unencryptedEmails should be copied from emails before decryption
72
- assert.equal(reportRequest.unencryptedEmails[0], 'email1@test.com');
73
- assert.equal(reportRequest.unencryptedEmails[1], 'email2@test.com');
74
- assert.empty(reportRequest.keywords);
75
- // this should be populated by request to kms
76
- assert.notEqual(reportRequest.encryptionKeyUrl, '');
77
- });
78
-
79
- return result;
80
- });
81
- });
82
-
83
- describe('Decrypt ReportRequest Tests', () => {
84
- it('Calls the correct decrypt functions when transforming a report request', () => {
85
- // body CONTAINS a ReportRequest
86
- object = {body: {reportRequest}};
87
- // object to be decrypted must have an encryption key
88
- reportRequest.encryptionKeyUrl = keyUri;
89
- const result = Transforms.decryptReportRequest(ctx, object).then(() => {
90
- assert.callCount(ctx.webex.internal.encryption.decryptText, 4);
91
- assert.equal(reportRequest.name, decryptedText);
92
- assert.equal(reportRequest.description, '');
93
- assert.equal(reportRequest.spaceNames[0], decryptedText);
94
- assert.equal(reportRequest.emails[0], decryptedText);
95
- assert.equal(reportRequest.emails[1], decryptedText);
96
- assert.empty(reportRequest.keywords);
97
- });
98
-
99
- return result;
100
- });
101
-
102
- it('Does not attempt to decrypt a report request if there is no encryption key url', () => {
103
- // body CONTAINS a ReportRequest
104
- object = {body: {reportRequest}};
105
- const result = Transforms.decryptReportRequest(ctx, object).then(() => {
106
- assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
107
- });
108
-
109
- return result;
110
- });
111
- });
112
- });
113
-
114
- describe('Report Content Transform', () => {
115
- describe('Decrypt Content Tests', () => {
116
- let activity;
117
- let contentContainer;
118
- const reportId = uuid;
119
-
120
- beforeEach(() => {
121
- activity = {};
122
- activity.activityId = uuid;
123
- activity.verb = 'post';
124
- activity.actorId = uuid;
125
- activity.actorDisplayName = 'user1';
126
- activity.targetId = uuid;
127
- activity.objectDisplayName = 'encrypted content';
128
- activity.encryptionKeyUrl = keyUri;
129
-
130
- object = {body: activity};
131
-
132
- contentContainer = {};
133
- contentContainer.containerId = '0';
134
- contentContainer.containerName = 'spaceName';
135
- contentContainer.isOneOnOne = false;
136
- contentContainer.participants = [
137
- {id: uuid, displayName: 'user1'},
138
- {id: uuid, displayName: 'user2'},
139
- {id: uuid, displayName: 'user3'},
140
- ];
141
- contentContainer.onBehalfOfUser = uuid;
142
- contentContainer.encryptionKeyUrl = keyUri;
143
-
144
- ctx.webex.internal.ediscovery = {
145
- getContentContainerByContainerId: sinon
146
- .stub()
147
- .returns(Promise.resolve({body: contentContainer})),
148
- };
149
- });
150
-
151
- afterEach(() =>
152
- ctx.webex.internal.ediscovery.getContentContainerByContainerId.resetHistory()
153
- );
154
-
155
- it('Calls the decrypt functions when extension type is customApp', () => {
156
- object.body.extension = {
157
- objectType: 'extension',
158
- extensionType: 'customApp',
159
- contentUrl: 'encrypted content',
160
- displayName: 'encrypted content',
161
- webUrl: 'encrypted content',
162
- appId: uuid,
163
- };
164
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
165
- assert.equal(object.body.extension.contentUrl, decryptedText);
166
- assert.equal(object.body.extension.webUrl, decryptedText);
167
- assert.equal(object.body.extension.appId, uuid);
168
- assert.equal(object.body.extension.displayName, decryptedText);
169
- assert.equal(activity.error, undefined);
170
- });
171
-
172
- return result;
173
- });
174
-
175
- it('Calls the decrypt functions when extension type is customApp along with the verb is update', () => {
176
- object.body.verb = 'update';
177
- object.body.extension = {
178
- objectType: 'extension',
179
- extensionType: 'customApp',
180
- contentUrl: 'encrypted content',
181
- displayName: 'encrypted content',
182
- previous: {contentUrl: 'encrypted content', displayName: 'encrypted content'},
183
- };
184
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
185
- assert.equal(object.body.extension.contentUrl, decryptedText);
186
- assert.equal(object.body.extension.displayName, decryptedText);
187
- assert.equal(object.body.extension.previous.contentUrl, decryptedText);
188
- assert.equal(object.body.extension.previous.displayName, decryptedText);
189
- assert.equal(activity.error, undefined);
190
- });
191
-
192
- return result;
193
- });
194
-
195
- it('Calls the correct decrypt functions when transforming post activities', () => {
196
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
197
- assert.equal(activity.objectDisplayName, decryptedText);
198
- assert.equal(activity.spaceName, contentContainer.containerName);
199
- });
200
-
201
- return result;
202
- });
203
-
204
- it('Creates spaceName from participantDisplayNames for one to one spaces', () => {
205
- contentContainer.isOneOnOne = true;
206
- // one to one conversations have only 2 participants
207
- contentContainer.participants = [
208
- {id: uuid, displayName: 'user1'},
209
- {id: uuid, displayName: 'user2'},
210
- ];
211
- // spacename should be undefined for one on one conversations
212
- contentContainer.containerName = undefined;
213
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
214
- assert.equal(activity.objectDisplayName, decryptedText);
215
- assert.equal(activity.spaceName, 'user1 & user2');
216
- });
217
-
218
- return result;
219
- });
220
-
221
- it('Does not call any decrypt functions when transforming add activities', () => {
222
- object.body.verb = 'add';
223
- // object display name for add activity is a uuid
224
- object.body.objectDisplayName = uuid;
225
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
226
- assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
227
- assert.equal(activity.objectDisplayName, uuid);
228
- assert.equal(activity.spaceName, contentContainer.containerName);
229
- });
230
-
231
- return result;
232
- });
233
-
234
- it('Does not call any decrypt functions when transforming leave activities', () => {
235
- object.body.verb = 'leave';
236
- // object display name for leave activity is a uuid
237
- object.body.objectDisplayName = uuid;
238
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
239
- assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
240
- assert.equal(activity.objectDisplayName, uuid);
241
- assert.equal(activity.spaceName, contentContainer.containerName);
242
- });
243
-
244
- return result;
245
- });
246
-
247
- it('Does not call any decrypt functions if encryption key url is empty', () => {
248
- object.body.encryptionKeyUrl = '';
249
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
250
- assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
251
- assert.equal(activity.objectDisplayName, 'encrypted content');
252
- assert.equal(activity.spaceName, contentContainer.containerName);
253
- });
254
-
255
- return result;
256
- });
257
-
258
- it('Does not call any decrypt functions if encryption key url is undefined', () => {
259
- object.body.encryptionKeyUrl = undefined;
260
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
261
- assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
262
- assert.equal(activity.objectDisplayName, 'encrypted content');
263
- assert.equal(activity.spaceName, contentContainer.containerName);
264
- });
265
-
266
- return result;
267
- });
268
-
269
- it('Does not call any decrypt functions if onBehalfOfUser is empty', () => {
270
- contentContainer.onBehalfOfUser = '';
271
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
272
- assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
273
- assert.equal(activity.objectDisplayName, 'encrypted content');
274
- assert.equal(activity.spaceName, contentContainer.containerName);
275
- });
276
-
277
- return result;
278
- });
279
-
280
- it('Does not call any decrypt functions if onBehalfOfUser is undefined', () => {
281
- contentContainer.onBehalfOfUser = undefined;
282
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
283
- assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
284
- assert.equal(activity.objectDisplayName, 'encrypted content');
285
- assert.equal(activity.spaceName, contentContainer.containerName);
286
- });
287
-
288
- return result;
289
- });
290
-
291
- it('Decrypt function throws an exception', () => {
292
- const expectedError = new Error('Failed to acquire a key');
293
- ctx.webex.internal.encryption.decryptText = sinon
294
- .stub()
295
- .returns(Promise.reject(expectedError));
296
-
297
- const result = Transforms.decryptReportContent(ctx, object, reportId)
298
- .then(() => {
299
- assert.fail('Decrypt did not fail as expected');
300
- })
301
- .catch(() => {
302
- assert.deepEqual(activity.error, expectedError);
303
- });
304
-
305
- return result;
306
- });
307
-
308
- it('Calls the correct decrypt functions when transforming file share activities', () => {
309
- object.body.verb = 'share';
310
- // there should be no other content for a share
311
- object.body.objectDisplayName = undefined;
312
- object.body.files = [{displayName: 'file name', scr: 'eyJhbGciOi...'}];
313
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
314
- assert.callCount(ctx.webex.internal.encryption.decryptText, 1);
315
- assert.callCount(ctx.webex.internal.encryption.decryptScr, 1);
316
- assert.equal(activity.objectDisplayName, undefined);
317
- assert.equal(activity.files[0].displayName, decryptedText);
318
- assert.equal(activity.files[0].scr, decryptedScr);
319
- });
320
-
321
- return result;
322
- });
323
-
324
- it('Calls the correct decrypt functions when transforming file share activities with Microsoft shared link info', () => {
325
- object.body.verb = 'share';
326
- // there should be no other content for a share
327
- object.body.objectDisplayName = undefined;
328
- object.body.files = [
329
- {
330
- displayName: 'file name',
331
- scr: 'eyJhbGciOi...',
332
- microsoftSharedLinkInfo: {driveId: '1', itemId: '2'},
333
- },
334
- ];
335
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
336
- assert.callCount(ctx.webex.internal.encryption.decryptText, 3);
337
- assert.callCount(ctx.webex.internal.encryption.decryptScr, 1);
338
- assert.equal(activity.objectDisplayName, undefined);
339
- assert.equal(activity.files[0].displayName, decryptedText);
340
- assert.equal(activity.files[0].scr, decryptedScr);
341
- assert.equal(activity.files[0].microsoftSharedLinkInfo.driveId, decryptedText);
342
- assert.equal(activity.files[0].microsoftSharedLinkInfo.itemId, decryptedText);
343
- });
344
-
345
- return result;
346
- });
347
-
348
- it('Adds warning to activity if warning found while retrieving space', () => {
349
- contentContainer.warning = 'warn';
350
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
351
- assert.equal(activity.warn, contentContainer.warn);
352
- });
353
-
354
- return result;
355
- });
356
-
357
- it('Calls the correct decrypt functions when transforming activity.meeting.title', () => {
358
- object.body.verb = 'add';
359
- object.body.objectDisplayName = undefined;
360
- object.body.meeting = {title: 'Encrypted Title'};
361
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
362
- assert.callCount(ctx.webex.internal.encryption.decryptText, 1);
363
- assert.equal(activity.error, undefined);
364
- });
365
-
366
- return result;
367
- });
368
-
369
- it('Calls the correct decrypt functions when transforming activity.recording.topic', () => {
370
- object.body.verb = 'add';
371
- object.body.objectDisplayName = undefined;
372
- object.body.recording = {topic: 'Encrypted Topic'};
373
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
374
- assert.callCount(ctx.webex.internal.encryption.decryptText, 1);
375
- assert.equal(activity.error, undefined);
376
- });
377
-
378
- return result;
379
- });
380
-
381
- it('Calls the correct decrypt functions when transforming activity.spaceInfo.name', () => {
382
- object.body.verb = 'update';
383
- object.body.spaceInfo = {name: 'Encrypted Name'};
384
- object.body.objectDisplayName = undefined;
385
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
386
- assert.callCount(ctx.webex.internal.encryption.decryptText, 1);
387
- assert.equal(activity.error, undefined);
388
- });
389
-
390
- return result;
391
- });
392
-
393
- it('Calls the correct decrypt functions when transforming activity.spaceInfo.name with previousValue', () => {
394
- object.body.verb = 'update';
395
- object.body.spaceInfo = {
396
- name: 'Encrypted Name',
397
- previousName: 'Previous Name',
398
- previousEncryptionKeyUrl: keyUri,
399
- };
400
- object.body.objectDisplayName = undefined;
401
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
402
- assert.callCount(ctx.webex.internal.encryption.decryptText, 2);
403
- assert.equal(activity.error, undefined);
404
- });
405
-
406
- return result;
407
- });
408
-
409
- it('Calls the correct decrypt functions when transforming activity.spaceInfo.description', () => {
410
- object.body.verb = 'update';
411
- object.body.spaceInfo = {description: 'Encrypted Description'};
412
- object.body.objectDisplayName = undefined;
413
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
414
- assert.callCount(ctx.webex.internal.encryption.decryptText, 1);
415
- assert.equal(activity.error, undefined);
416
- });
417
-
418
- return result;
419
- });
420
-
421
- it('Calls the correct decrypt functions when transforming both activity.spaceInfo.name and activity.spaceInfo.description', () => {
422
- object.body.verb = 'update';
423
- object.body.spaceInfo = {name: 'Encrypted Name', description: 'Encrypted description'};
424
- object.body.objectDisplayName = undefined;
425
- const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
426
- assert.callCount(ctx.webex.internal.encryption.decryptText, 2);
427
- assert.equal(activity.error, undefined);
428
- });
429
-
430
- return result;
431
- });
432
-
433
- it('Calls the correct decrypt functions when transforming activity.encryptedTextKeyValues', () => {
434
- object.body.verb = 'add';
435
- object.body.objectDisplayName = undefined;
436
- object.body.encryptedTextKeyValues = {
437
- CallingLineId: 'Encrypted Phone Number 1',
438
- CallingNumber: 'Encrypted Phone Number 2',
439
- RedirectingNumber: 'Encrypted Phone Number 3',
440
- };
441
- const result = Transforms.decryptReportContent(ctx, object, reportId)
442
- .then(() => {
443
- assert.callCount(ctx.webex.internal.encryption.decryptText, 3);
444
- assert.equal(activity.error, undefined);
445
- assert.equal(object.body.encryptedTextKeyValues.CallingLineId, decryptedText);
446
- assert.equal(object.body.encryptedTextKeyValues.CallingNumber, decryptedText);
447
- assert.equal(object.body.encryptedTextKeyValues.RedirectingNumber, decryptedText);
448
- });
449
-
450
- return result;
451
- });
452
-
453
- it('Calls the correct decrypt functions when transforming activity.encryptedTextKeyValues and no onBehalfOfUser user is present', () => {
454
- contentContainer.onBehalfOfUser = undefined;
455
- object.body.verb = 'add';
456
- object.body.objectDisplayName = undefined;
457
- object.body.encryptedTextKeyValues = {
458
- CallingLineId: 'Encrypted Phone Number 1',
459
- CallingNumber: 'Encrypted Phone Number 2',
460
- RedirectingNumber: 'Encrypted Phone Number 3',
461
- };
462
- const result = Transforms.decryptReportContent(ctx, object, reportId)
463
- .then(() => {
464
- assert.callCount(ctx.webex.internal.encryption.decryptText, 3);
465
- assert.equal(activity.error, undefined);
466
- assert.equal(object.body.encryptedTextKeyValues.CallingLineId, decryptedText);
467
- assert.equal(object.body.encryptedTextKeyValues.CallingNumber, decryptedText);
468
- assert.equal(object.body.encryptedTextKeyValues.RedirectingNumber, decryptedText);
469
- });
470
-
471
- return result;
472
- });
473
-
474
- it('Decrypt function throws an exception when processing activity.encryptedTextKeyValues', () => {
475
- const expectedError = new Error('Failed to acquire a key');
476
- ctx.webex.internal.encryption.decryptText = sinon.stub().returns(Promise.reject(expectedError));
477
- object.body.verb = 'add';
478
- object.body.objectDisplayName = undefined;
479
- object.body.encryptedTextKeyValues = {
480
- CallingLineId: 'Encrypted Phone Number 1',
481
- CallingNumber: 'Encrypted Phone Number 2',
482
- RedirectingNumber: 'Encrypted Phone Number 3',
483
- };
484
- const result = Transforms.decryptReportContent(ctx, object, reportId)
485
- .then(() => {
486
- assert.fail('Decrypt did not fail as expected');
487
- })
488
- .catch(() => {
489
- assert.deepEqual(activity.error, expectedError);
490
- });
491
-
492
- return result;
493
- });
494
- });
495
- });
496
- });
1
+ import EDiscovery from '@webex/internal-plugin-ediscovery';
2
+ import Transforms from '@webex/internal-plugin-ediscovery/src/transforms';
3
+ import ReportRequest from '@webex/internal-plugin-ediscovery/src/report-request';
4
+ import MockWebex from '@webex/test-helper-mock-webex';
5
+ import sinon from 'sinon';
6
+ import {assert} from '@webex/test-helper-chai';
7
+ import config from '@webex/internal-plugin-ediscovery/src/config';
8
+
9
+ /* eslint-disable max-len */
10
+ describe('EDiscovery Transform Tests', () => {
11
+ const encryptedText = 'this text has been encrypted';
12
+ const decryptedText = 'this text has been decrypted';
13
+ const decryptedScr = 'this scr has been decrypted';
14
+ const uuid = 'e20d6180-2b95-11e9-8f7a-59e7a3b4e375';
15
+ const keyUri = 'kms://ciscospark.com/keys/32471db7-3d71-4fd1-b36c-0a1fe9efae2d';
16
+
17
+ const ctx = {transform: sinon.stub().returns(Promise.resolve())};
18
+ let object;
19
+
20
+ beforeEach(() => {
21
+ ctx.webex = new MockWebex({children: {ediscovery: EDiscovery}});
22
+ ctx.webex.config.ediscovery = config.ediscovery;
23
+ ctx.webex.internal = {
24
+ device: {
25
+ deviceType: 'FAKE_DEVICE',
26
+ },
27
+ encryption: {
28
+ encryptText: sinon.stub().returns(Promise.resolve(encryptedText)),
29
+ decryptText: sinon.stub().returns(Promise.resolve(decryptedText)),
30
+ decryptScr: sinon.stub().returns(Promise.resolve(decryptedScr)),
31
+ kms: {
32
+ createUnboundKeys: sinon.stub().returns(Promise.resolve([{userIds: uuid, uri: keyUri}])),
33
+ createResource: sinon.stub().returns(Promise.resolve()),
34
+ },
35
+ },
36
+ };
37
+ });
38
+
39
+ afterEach(() => {
40
+ ctx.transform.resetHistory();
41
+ ctx.webex.internal.encryption.encryptText.resetHistory();
42
+ ctx.webex.internal.encryption.decryptText.resetHistory();
43
+ ctx.webex.internal.encryption.decryptScr.resetHistory();
44
+ ctx.webex.internal.encryption.kms.createUnboundKeys.resetHistory();
45
+ ctx.webex.internal.encryption.kms.createResource.resetHistory();
46
+ });
47
+
48
+ describe('Report Request Transforms', () => {
49
+ let reportRequest;
50
+
51
+ beforeEach(() => {
52
+ reportRequest = new ReportRequest();
53
+ reportRequest.name = 'test report';
54
+ reportRequest.description = '';
55
+ reportRequest.spaceNames = ['test space 1'];
56
+ reportRequest.emails = ['email1@test.com', 'email2@test.com'];
57
+ reportRequest.keywords = [];
58
+ });
59
+
60
+ describe('Encrypt ReportRequest Tests', () => {
61
+ it('Calls the correct encrypt functions when transforming a report request', () => {
62
+ // body IS a ReportRequest
63
+ object = {body: reportRequest};
64
+ const result = Transforms.encryptReportRequest(ctx, object).then(() => {
65
+ assert.callCount(ctx.webex.internal.encryption.encryptText, 4);
66
+ assert.equal(reportRequest.name, encryptedText);
67
+ assert.equal(reportRequest.description, '');
68
+ assert.equal(reportRequest.spaceNames[0], encryptedText);
69
+ assert.equal(reportRequest.emails[0], encryptedText);
70
+ assert.equal(reportRequest.emails[1], encryptedText);
71
+ // unencryptedEmails should be copied from emails before decryption
72
+ assert.equal(reportRequest.unencryptedEmails[0], 'email1@test.com');
73
+ assert.equal(reportRequest.unencryptedEmails[1], 'email2@test.com');
74
+ assert.empty(reportRequest.keywords);
75
+ // this should be populated by request to kms
76
+ assert.notEqual(reportRequest.encryptionKeyUrl, '');
77
+ });
78
+
79
+ return result;
80
+ });
81
+ });
82
+
83
+ describe('Decrypt ReportRequest Tests', () => {
84
+ it('Calls the correct decrypt functions when transforming a report request', () => {
85
+ // body CONTAINS a ReportRequest
86
+ object = {body: {reportRequest}};
87
+ // object to be decrypted must have an encryption key
88
+ reportRequest.encryptionKeyUrl = keyUri;
89
+ const result = Transforms.decryptReportRequest(ctx, object).then(() => {
90
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 4);
91
+ assert.equal(reportRequest.name, decryptedText);
92
+ assert.equal(reportRequest.description, '');
93
+ assert.equal(reportRequest.spaceNames[0], decryptedText);
94
+ assert.equal(reportRequest.emails[0], decryptedText);
95
+ assert.equal(reportRequest.emails[1], decryptedText);
96
+ assert.empty(reportRequest.keywords);
97
+ });
98
+
99
+ return result;
100
+ });
101
+
102
+ it('Does not attempt to decrypt a report request if there is no encryption key url', () => {
103
+ // body CONTAINS a ReportRequest
104
+ object = {body: {reportRequest}};
105
+ const result = Transforms.decryptReportRequest(ctx, object).then(() => {
106
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
107
+ });
108
+
109
+ return result;
110
+ });
111
+ });
112
+ });
113
+
114
+ describe('Report Content Transform', () => {
115
+ describe('Decrypt Content Tests', () => {
116
+ let activity;
117
+ let contentContainer;
118
+ const reportId = uuid;
119
+
120
+ beforeEach(() => {
121
+ activity = {};
122
+ activity.activityId = uuid;
123
+ activity.verb = 'post';
124
+ activity.actorId = uuid;
125
+ activity.actorDisplayName = 'user1';
126
+ activity.targetId = uuid;
127
+ activity.objectDisplayName = 'encrypted content';
128
+ activity.encryptionKeyUrl = keyUri;
129
+
130
+ object = {body: activity};
131
+
132
+ contentContainer = {};
133
+ contentContainer.containerId = '0';
134
+ contentContainer.containerName = 'spaceName';
135
+ contentContainer.isOneOnOne = false;
136
+ contentContainer.participants = [
137
+ {id: uuid, displayName: 'user1'},
138
+ {id: uuid, displayName: 'user2'},
139
+ {id: uuid, displayName: 'user3'},
140
+ ];
141
+ contentContainer.onBehalfOfUser = uuid;
142
+ contentContainer.encryptionKeyUrl = keyUri;
143
+
144
+ ctx.webex.internal.ediscovery = {
145
+ getContentContainerByContainerId: sinon
146
+ .stub()
147
+ .returns(Promise.resolve({body: contentContainer})),
148
+ };
149
+ });
150
+
151
+ afterEach(() =>
152
+ ctx.webex.internal.ediscovery.getContentContainerByContainerId.resetHistory()
153
+ );
154
+
155
+ it('Calls the decrypt functions when extension type is customApp', () => {
156
+ object.body.extension = {
157
+ objectType: 'extension',
158
+ extensionType: 'customApp',
159
+ contentUrl: 'encrypted content',
160
+ displayName: 'encrypted content',
161
+ webUrl: 'encrypted content',
162
+ appId: uuid,
163
+ };
164
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
165
+ assert.equal(object.body.extension.contentUrl, decryptedText);
166
+ assert.equal(object.body.extension.webUrl, decryptedText);
167
+ assert.equal(object.body.extension.appId, uuid);
168
+ assert.equal(object.body.extension.displayName, decryptedText);
169
+ assert.equal(activity.error, undefined);
170
+ });
171
+
172
+ return result;
173
+ });
174
+
175
+ it('Calls the decrypt functions when extension type is customApp along with the verb is update', () => {
176
+ object.body.verb = 'update';
177
+ object.body.extension = {
178
+ objectType: 'extension',
179
+ extensionType: 'customApp',
180
+ contentUrl: 'encrypted content',
181
+ displayName: 'encrypted content',
182
+ previous: {contentUrl: 'encrypted content', displayName: 'encrypted content'},
183
+ };
184
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
185
+ assert.equal(object.body.extension.contentUrl, decryptedText);
186
+ assert.equal(object.body.extension.displayName, decryptedText);
187
+ assert.equal(object.body.extension.previous.contentUrl, decryptedText);
188
+ assert.equal(object.body.extension.previous.displayName, decryptedText);
189
+ assert.equal(activity.error, undefined);
190
+ });
191
+
192
+ return result;
193
+ });
194
+
195
+ it('Calls the correct decrypt functions when transforming post activities', () => {
196
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
197
+ assert.equal(activity.objectDisplayName, decryptedText);
198
+ assert.equal(activity.spaceName, contentContainer.containerName);
199
+ });
200
+
201
+ return result;
202
+ });
203
+
204
+ it('Creates spaceName from participantDisplayNames for one to one spaces', () => {
205
+ contentContainer.isOneOnOne = true;
206
+ // one to one conversations have only 2 participants
207
+ contentContainer.participants = [
208
+ {id: uuid, displayName: 'user1'},
209
+ {id: uuid, displayName: 'user2'},
210
+ ];
211
+ // spacename should be undefined for one on one conversations
212
+ contentContainer.containerName = undefined;
213
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
214
+ assert.equal(activity.objectDisplayName, decryptedText);
215
+ assert.equal(activity.spaceName, 'user1 & user2');
216
+ });
217
+
218
+ return result;
219
+ });
220
+
221
+ it('Does not call any decrypt functions when transforming add activities', () => {
222
+ object.body.verb = 'add';
223
+ // object display name for add activity is a uuid
224
+ object.body.objectDisplayName = uuid;
225
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
226
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
227
+ assert.equal(activity.objectDisplayName, uuid);
228
+ assert.equal(activity.spaceName, contentContainer.containerName);
229
+ });
230
+
231
+ return result;
232
+ });
233
+
234
+ it('Does not call any decrypt functions when transforming leave activities', () => {
235
+ object.body.verb = 'leave';
236
+ // object display name for leave activity is a uuid
237
+ object.body.objectDisplayName = uuid;
238
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
239
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
240
+ assert.equal(activity.objectDisplayName, uuid);
241
+ assert.equal(activity.spaceName, contentContainer.containerName);
242
+ });
243
+
244
+ return result;
245
+ });
246
+
247
+ it('Does not call any decrypt functions if encryption key url is empty', () => {
248
+ object.body.encryptionKeyUrl = '';
249
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
250
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
251
+ assert.equal(activity.objectDisplayName, 'encrypted content');
252
+ assert.equal(activity.spaceName, contentContainer.containerName);
253
+ });
254
+
255
+ return result;
256
+ });
257
+
258
+ it('Does not call any decrypt functions if encryption key url is undefined', () => {
259
+ object.body.encryptionKeyUrl = undefined;
260
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
261
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
262
+ assert.equal(activity.objectDisplayName, 'encrypted content');
263
+ assert.equal(activity.spaceName, contentContainer.containerName);
264
+ });
265
+
266
+ return result;
267
+ });
268
+
269
+ it('Does not call any decrypt functions if onBehalfOfUser is empty', () => {
270
+ contentContainer.onBehalfOfUser = '';
271
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
272
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
273
+ assert.equal(activity.objectDisplayName, 'encrypted content');
274
+ assert.equal(activity.spaceName, contentContainer.containerName);
275
+ });
276
+
277
+ return result;
278
+ });
279
+
280
+ it('Does not call any decrypt functions if onBehalfOfUser is undefined', () => {
281
+ contentContainer.onBehalfOfUser = undefined;
282
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
283
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 0);
284
+ assert.equal(activity.objectDisplayName, 'encrypted content');
285
+ assert.equal(activity.spaceName, contentContainer.containerName);
286
+ });
287
+
288
+ return result;
289
+ });
290
+
291
+ it('Decrypt function throws an exception', () => {
292
+ const expectedError = new Error('Failed to acquire a key');
293
+ ctx.webex.internal.encryption.decryptText = sinon
294
+ .stub()
295
+ .returns(Promise.reject(expectedError));
296
+
297
+ const result = Transforms.decryptReportContent(ctx, object, reportId)
298
+ .then(() => {
299
+ assert.fail('Decrypt did not fail as expected');
300
+ })
301
+ .catch(() => {
302
+ assert.deepEqual(activity.error, expectedError);
303
+ });
304
+
305
+ return result;
306
+ });
307
+
308
+ it('Calls the correct decrypt functions when transforming file share activities', () => {
309
+ object.body.verb = 'share';
310
+ // there should be no other content for a share
311
+ object.body.objectDisplayName = undefined;
312
+ object.body.files = [{displayName: 'file name', scr: 'eyJhbGciOi...'}];
313
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
314
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 1);
315
+ assert.callCount(ctx.webex.internal.encryption.decryptScr, 1);
316
+ assert.equal(activity.objectDisplayName, undefined);
317
+ assert.equal(activity.files[0].displayName, decryptedText);
318
+ assert.equal(activity.files[0].scr, decryptedScr);
319
+ });
320
+
321
+ return result;
322
+ });
323
+
324
+ it('Calls the correct decrypt functions when transforming file share activities with Microsoft shared link info', () => {
325
+ object.body.verb = 'share';
326
+ // there should be no other content for a share
327
+ object.body.objectDisplayName = undefined;
328
+ object.body.files = [
329
+ {
330
+ displayName: 'file name',
331
+ scr: 'eyJhbGciOi...',
332
+ microsoftSharedLinkInfo: {driveId: '1', itemId: '2'},
333
+ },
334
+ ];
335
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
336
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 3);
337
+ assert.callCount(ctx.webex.internal.encryption.decryptScr, 1);
338
+ assert.equal(activity.objectDisplayName, undefined);
339
+ assert.equal(activity.files[0].displayName, decryptedText);
340
+ assert.equal(activity.files[0].scr, decryptedScr);
341
+ assert.equal(activity.files[0].microsoftSharedLinkInfo.driveId, decryptedText);
342
+ assert.equal(activity.files[0].microsoftSharedLinkInfo.itemId, decryptedText);
343
+ });
344
+
345
+ return result;
346
+ });
347
+
348
+ it('Adds warning to activity if warning found while retrieving space', () => {
349
+ contentContainer.warning = 'warn';
350
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
351
+ assert.equal(activity.warn, contentContainer.warn);
352
+ });
353
+
354
+ return result;
355
+ });
356
+
357
+ it('Calls the correct decrypt functions when transforming activity.meeting.title', () => {
358
+ object.body.verb = 'add';
359
+ object.body.objectDisplayName = undefined;
360
+ object.body.meeting = {title: 'Encrypted Title'};
361
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
362
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 1);
363
+ assert.equal(activity.error, undefined);
364
+ });
365
+
366
+ return result;
367
+ });
368
+
369
+ it('Calls the correct decrypt functions when transforming activity.recording.topic', () => {
370
+ object.body.verb = 'add';
371
+ object.body.objectDisplayName = undefined;
372
+ object.body.recording = {topic: 'Encrypted Topic'};
373
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
374
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 1);
375
+ assert.equal(activity.error, undefined);
376
+ });
377
+
378
+ return result;
379
+ });
380
+
381
+ it('Calls the correct decrypt functions when transforming activity.spaceInfo.name', () => {
382
+ object.body.verb = 'update';
383
+ object.body.spaceInfo = {name: 'Encrypted Name'};
384
+ object.body.objectDisplayName = undefined;
385
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
386
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 1);
387
+ assert.equal(activity.error, undefined);
388
+ });
389
+
390
+ return result;
391
+ });
392
+
393
+ it('Calls the correct decrypt functions when transforming activity.spaceInfo.name with previousValue', () => {
394
+ object.body.verb = 'update';
395
+ object.body.spaceInfo = {
396
+ name: 'Encrypted Name',
397
+ previousName: 'Previous Name',
398
+ previousEncryptionKeyUrl: keyUri,
399
+ };
400
+ object.body.objectDisplayName = undefined;
401
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
402
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 2);
403
+ assert.equal(activity.error, undefined);
404
+ });
405
+
406
+ return result;
407
+ });
408
+
409
+ it('Calls the correct decrypt functions when transforming activity.spaceInfo.description', () => {
410
+ object.body.verb = 'update';
411
+ object.body.spaceInfo = {description: 'Encrypted Description'};
412
+ object.body.objectDisplayName = undefined;
413
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
414
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 1);
415
+ assert.equal(activity.error, undefined);
416
+ });
417
+
418
+ return result;
419
+ });
420
+
421
+ it('Calls the correct decrypt functions when transforming both activity.spaceInfo.name and activity.spaceInfo.description', () => {
422
+ object.body.verb = 'update';
423
+ object.body.spaceInfo = {name: 'Encrypted Name', description: 'Encrypted description'};
424
+ object.body.objectDisplayName = undefined;
425
+ const result = Transforms.decryptReportContent(ctx, object, reportId).then(() => {
426
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 2);
427
+ assert.equal(activity.error, undefined);
428
+ });
429
+
430
+ return result;
431
+ });
432
+
433
+ it('Calls the correct decrypt functions when transforming activity.encryptedTextKeyValues', () => {
434
+ object.body.verb = 'add';
435
+ object.body.objectDisplayName = undefined;
436
+ object.body.encryptedTextKeyValues = {
437
+ CallingLineId: 'Encrypted Phone Number 1',
438
+ CallingNumber: 'Encrypted Phone Number 2',
439
+ RedirectingNumber: 'Encrypted Phone Number 3',
440
+ };
441
+ const result = Transforms.decryptReportContent(ctx, object, reportId)
442
+ .then(() => {
443
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 3);
444
+ assert.equal(activity.error, undefined);
445
+ assert.equal(object.body.encryptedTextKeyValues.CallingLineId, decryptedText);
446
+ assert.equal(object.body.encryptedTextKeyValues.CallingNumber, decryptedText);
447
+ assert.equal(object.body.encryptedTextKeyValues.RedirectingNumber, decryptedText);
448
+ });
449
+
450
+ return result;
451
+ });
452
+
453
+ it('Calls the correct decrypt functions when transforming activity.encryptedTextKeyValues and no onBehalfOfUser user is present', () => {
454
+ contentContainer.onBehalfOfUser = undefined;
455
+ object.body.verb = 'add';
456
+ object.body.objectDisplayName = undefined;
457
+ object.body.encryptedTextKeyValues = {
458
+ CallingLineId: 'Encrypted Phone Number 1',
459
+ CallingNumber: 'Encrypted Phone Number 2',
460
+ RedirectingNumber: 'Encrypted Phone Number 3',
461
+ };
462
+ const result = Transforms.decryptReportContent(ctx, object, reportId)
463
+ .then(() => {
464
+ assert.callCount(ctx.webex.internal.encryption.decryptText, 3);
465
+ assert.equal(activity.error, undefined);
466
+ assert.equal(object.body.encryptedTextKeyValues.CallingLineId, decryptedText);
467
+ assert.equal(object.body.encryptedTextKeyValues.CallingNumber, decryptedText);
468
+ assert.equal(object.body.encryptedTextKeyValues.RedirectingNumber, decryptedText);
469
+ });
470
+
471
+ return result;
472
+ });
473
+
474
+ it('Decrypt function throws an exception when processing activity.encryptedTextKeyValues', () => {
475
+ const expectedError = new Error('Failed to acquire a key');
476
+ ctx.webex.internal.encryption.decryptText = sinon.stub().returns(Promise.reject(expectedError));
477
+ object.body.verb = 'add';
478
+ object.body.objectDisplayName = undefined;
479
+ object.body.encryptedTextKeyValues = {
480
+ CallingLineId: 'Encrypted Phone Number 1',
481
+ CallingNumber: 'Encrypted Phone Number 2',
482
+ RedirectingNumber: 'Encrypted Phone Number 3',
483
+ };
484
+ const result = Transforms.decryptReportContent(ctx, object, reportId)
485
+ .then(() => {
486
+ assert.fail('Decrypt did not fail as expected');
487
+ })
488
+ .catch(() => {
489
+ assert.deepEqual(activity.error, expectedError);
490
+ });
491
+
492
+ return result;
493
+ });
494
+ });
495
+ });
496
+ });