@webex/internal-plugin-ediscovery 3.0.0-beta.9 → 3.0.0-beta.91

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.
package/src/transforms.js CHANGED
@@ -16,18 +16,21 @@ class Transforms {
16
16
  }
17
17
  const reportRequest = object.body;
18
18
 
19
- return ctx.webex.internal.encryption.kms.createUnboundKeys({count: 1})
19
+ return ctx.webex.internal.encryption.kms
20
+ .createUnboundKeys({count: 1})
20
21
  .then((keys) => {
21
22
  if (keys && keys.length > 0 && keys[0]) {
22
23
  reportRequest.encryptionKeyUrl = keys[0].uri;
23
24
 
24
- return ctx.webex.internal.encryption.kms.createResource({userIds: [keys[0].userId], keys})
25
+ return ctx.webex.internal.encryption.kms
26
+ .createResource({userIds: [keys[0].userId], keys})
25
27
  .then(() => {
26
28
  const promises = [];
27
29
 
28
30
  if (reportRequest.name) {
29
31
  promises.push(
30
- ctx.webex.internal.encryption.encryptText(keys[0], reportRequest.name)
32
+ ctx.webex.internal.encryption
33
+ .encryptText(keys[0], reportRequest.name)
31
34
  .then((encryptedName) => {
32
35
  reportRequest.name = encryptedName;
33
36
  })
@@ -36,7 +39,8 @@ class Transforms {
36
39
 
37
40
  if (reportRequest.description) {
38
41
  promises.push(
39
- ctx.webex.internal.encryption.encryptText(keys[0], reportRequest.description)
42
+ ctx.webex.internal.encryption
43
+ .encryptText(keys[0], reportRequest.description)
40
44
  .then((encryptedDescription) => {
41
45
  reportRequest.description = encryptedDescription;
42
46
  })
@@ -45,19 +49,25 @@ class Transforms {
45
49
 
46
50
  if (reportRequest.spaceNames) {
47
51
  promises.push(
48
- Promise.all(reportRequest.spaceNames.map((spaceName) => ctx.webex.internal.encryption.encryptText(keys[0], spaceName)))
49
- .then((encryptedSpaceNames) => {
50
- reportRequest.spaceNames = encryptedSpaceNames;
51
- })
52
+ Promise.all(
53
+ reportRequest.spaceNames.map((spaceName) =>
54
+ ctx.webex.internal.encryption.encryptText(keys[0], spaceName)
55
+ )
56
+ ).then((encryptedSpaceNames) => {
57
+ reportRequest.spaceNames = encryptedSpaceNames;
58
+ })
52
59
  );
53
60
  }
54
61
 
55
62
  if (reportRequest.keywords) {
56
63
  promises.push(
57
- Promise.all(reportRequest.keywords.map((keyword) => ctx.webex.internal.encryption.encryptText(keys[0], keyword)))
58
- .then((encryptedKeywords) => {
59
- reportRequest.keywords = encryptedKeywords;
60
- })
64
+ Promise.all(
65
+ reportRequest.keywords.map((keyword) =>
66
+ ctx.webex.internal.encryption.encryptText(keys[0], keyword)
67
+ )
68
+ ).then((encryptedKeywords) => {
69
+ reportRequest.keywords = encryptedKeywords;
70
+ })
61
71
  );
62
72
  }
63
73
 
@@ -65,10 +75,13 @@ class Transforms {
65
75
  // store unencrypted emails for ediscovery service to convert to user ids
66
76
  reportRequest.unencryptedEmails = reportRequest.emails;
67
77
  promises.push(
68
- Promise.all(reportRequest.emails.map((email) => ctx.webex.internal.encryption.encryptText(keys[0], email)))
69
- .then((encryptedEmails) => {
70
- reportRequest.emails = encryptedEmails;
71
- })
78
+ Promise.all(
79
+ reportRequest.emails.map((email) =>
80
+ ctx.webex.internal.encryption.encryptText(keys[0], email)
81
+ )
82
+ ).then((encryptedEmails) => {
83
+ reportRequest.emails = encryptedEmails;
84
+ })
72
85
  );
73
86
  }
74
87
 
@@ -79,7 +92,9 @@ class Transforms {
79
92
  return Promise.resolve(object);
80
93
  })
81
94
  .catch((reason) => {
82
- ctx.webex.logger.error(`Error while encrypting report request: ${reportRequest} : ${reason}`);
95
+ ctx.webex.logger.error(
96
+ `Error while encrypting report request: ${reportRequest} : ${reason}`
97
+ );
83
98
 
84
99
  return Promise.reject(reason);
85
100
  });
@@ -92,7 +107,12 @@ class Transforms {
92
107
  * @returns {Promise} - Returns a transform promise
93
108
  */
94
109
  static decryptReportRequest(ctx, object) {
95
- if (!object || !object.body || !object.body.reportRequest || !object.body.reportRequest.encryptionKeyUrl) {
110
+ if (
111
+ !object ||
112
+ !object.body ||
113
+ !object.body.reportRequest ||
114
+ !object.body.reportRequest.encryptionKeyUrl
115
+ ) {
96
116
  return Promise.resolve(object);
97
117
  }
98
118
  const {reportRequest} = object.body;
@@ -100,55 +120,77 @@ class Transforms {
100
120
  let reportNamePromise;
101
121
 
102
122
  if (reportRequest.name) {
103
- reportNamePromise = ctx.webex.internal.encryption.decryptText(reportRequest.encryptionKeyUrl, reportRequest.name)
123
+ reportNamePromise = ctx.webex.internal.encryption
124
+ .decryptText(reportRequest.encryptionKeyUrl, reportRequest.name)
104
125
  .then((decryptedName) => {
105
126
  reportRequest.name = decryptedName;
106
127
  })
107
128
  .catch((reason) => {
108
- ctx.webex.logger.error(`Error decrypting report name for report ${object.body.id}: ${reason}`);
129
+ ctx.webex.logger.error(
130
+ `Error decrypting report name for report ${object.body.id}: ${reason}`
131
+ );
109
132
  });
110
133
  }
111
134
 
112
135
  let reportDescriptionPromise;
113
136
 
114
137
  if (reportRequest.description) {
115
- reportDescriptionPromise = ctx.webex.internal.encryption.decryptText(reportRequest.encryptionKeyUrl, reportRequest.description)
138
+ reportDescriptionPromise = ctx.webex.internal.encryption
139
+ .decryptText(reportRequest.encryptionKeyUrl, reportRequest.description)
116
140
  .then((decryptedDescription) => {
117
141
  reportRequest.description = decryptedDescription;
118
142
  })
119
143
  .catch((reason) => {
120
- ctx.webex.logger.error(`Error decrypting description for report ${object.body.id}: ${reason}`);
144
+ ctx.webex.logger.error(
145
+ `Error decrypting description for report ${object.body.id}: ${reason}`
146
+ );
121
147
  });
122
148
  }
123
149
 
124
150
  let spaceNamePromises = [];
125
151
 
126
152
  if (reportRequest.spaceNames) {
127
- spaceNamePromises = Promise.all(reportRequest.spaceNames.map((spaceName) => ctx.webex.internal.encryption.decryptText(reportRequest.encryptionKeyUrl, spaceName)))
153
+ spaceNamePromises = Promise.all(
154
+ reportRequest.spaceNames.map((spaceName) =>
155
+ ctx.webex.internal.encryption.decryptText(reportRequest.encryptionKeyUrl, spaceName)
156
+ )
157
+ )
128
158
  .then((decryptedSpaceNames) => {
129
159
  reportRequest.spaceNames = decryptedSpaceNames;
130
160
  })
131
161
  .catch((reason) => {
132
- ctx.webex.logger.error(`Error decrypting space name for report ${object.body.id}: ${reason}`);
162
+ ctx.webex.logger.error(
163
+ `Error decrypting space name for report ${object.body.id}: ${reason}`
164
+ );
133
165
  });
134
166
  }
135
167
 
136
168
  let keywordPromises = [];
137
169
 
138
170
  if (reportRequest.keywords) {
139
- keywordPromises = Promise.all(reportRequest.keywords.map((keyword) => ctx.webex.internal.encryption.decryptText(reportRequest.encryptionKeyUrl, keyword)))
171
+ keywordPromises = Promise.all(
172
+ reportRequest.keywords.map((keyword) =>
173
+ ctx.webex.internal.encryption.decryptText(reportRequest.encryptionKeyUrl, keyword)
174
+ )
175
+ )
140
176
  .then((decryptedKeywords) => {
141
177
  reportRequest.keywords = decryptedKeywords;
142
178
  })
143
179
  .catch((reason) => {
144
- ctx.webex.logger.error(`Error decrypting keywords for report ${object.body.id}: ${reason}`);
180
+ ctx.webex.logger.error(
181
+ `Error decrypting keywords for report ${object.body.id}: ${reason}`
182
+ );
145
183
  });
146
184
  }
147
185
 
148
186
  let emailPromises = [];
149
187
 
150
188
  if (reportRequest.emails) {
151
- emailPromises = Promise.all(reportRequest.emails.map((email) => ctx.webex.internal.encryption.decryptText(reportRequest.encryptionKeyUrl, email)))
189
+ emailPromises = Promise.all(
190
+ reportRequest.emails.map((email) =>
191
+ ctx.webex.internal.encryption.decryptText(reportRequest.encryptionKeyUrl, email)
192
+ )
193
+ )
152
194
  .then((decryptedEmails) => {
153
195
  reportRequest.emails = decryptedEmails;
154
196
  })
@@ -157,7 +199,13 @@ class Transforms {
157
199
  });
158
200
  }
159
201
 
160
- return Promise.all([reportNamePromise, reportDescriptionPromise].concat(spaceNamePromises, keywordPromises, emailPromises));
202
+ return Promise.all(
203
+ [reportNamePromise, reportDescriptionPromise].concat(
204
+ spaceNamePromises,
205
+ keywordPromises,
206
+ emailPromises
207
+ )
208
+ );
161
209
  }
162
210
 
163
211
  /**
@@ -175,7 +223,8 @@ class Transforms {
175
223
 
176
224
  const promises = [];
177
225
 
178
- return ctx.webex.internal.ediscovery.getContentContainerByContainerId(reportId, activity.targetId)
226
+ return ctx.webex.internal.ediscovery
227
+ .getContentContainerByContainerId(reportId, activity.targetId)
179
228
  .then((res) => {
180
229
  const container = res.body;
181
230
 
@@ -198,34 +247,45 @@ class Transforms {
198
247
  if (container.containerName) {
199
248
  activity.spaceName = container.containerName; // Remove this property once all clients are using the content container model
200
249
  activity.containerName = container.containerName;
201
- }
202
- else if (container.isOneOnOne) {
203
- const displayNames = (container.participants || []).concat(container.formerParticipants || []).map((p) => p.displayName).join(' & ');
250
+ } else if (container.isOneOnOne) {
251
+ const displayNames = (container.participants || [])
252
+ .concat(container.formerParticipants || [])
253
+ .map((p) => p.displayName)
254
+ .join(' & ');
204
255
 
205
256
  // One to One spaces have no space name, use participant names as 'Subject' instead
206
257
  activity.spaceName = displayNames; // Remove this property once all clients are using the content container model
207
258
  activity.containerName = displayNames;
208
- }
209
- else {
259
+ } else {
210
260
  activity.spaceName = ''; // Remove this property once all clients are using the content container model
211
261
  activity.containerName = '';
212
262
  }
213
263
 
214
264
  // post and share activities have content which needs to be decrypted
215
265
  // as do meeting, recording activities, customApp extensions, and space information updates
216
- if (!['post', 'share'].includes(activity.verb) && !activity.meeting && !activity.recording && !(activity.extension && activity.extension.extensionType === 'customApp') &&
217
- !activity.spaceInfo?.name && !activity.spaceInfo?.description) {
266
+ if (
267
+ !['post', 'share'].includes(activity.verb) &&
268
+ !activity.meeting &&
269
+ !activity.recording &&
270
+ !(activity.extension && activity.extension.extensionType === 'customApp') &&
271
+ !activity.spaceInfo?.name &&
272
+ !activity.spaceInfo?.description &&
273
+ !activity.encryptedTextKeyValues
274
+ ) {
218
275
  return Promise.resolve(object);
219
276
  }
220
277
 
221
278
  if (!activity.encryptionKeyUrl) {
222
279
  // If the encryptionKeyUrl is empty we assume the activity is unencrypted
223
- ctx.webex.logger.info(`Activity ${activity.activityId} cannot be decrypted due to a missing encryption key url`);
280
+ ctx.webex.logger.info(
281
+ `Activity ${activity.activityId} cannot be decrypted due to a missing encryption key url`
282
+ );
224
283
 
225
284
  return Promise.resolve(object);
226
285
  }
227
286
 
228
- if (!container.onBehalfOfUser) {
287
+ // CDR Compliance uses org key and does depend on an onBehalfOfUser
288
+ if (activity.encryptedTextKeyValues === undefined && !container.onBehalfOfUser) {
229
289
  const reason = `No user available with which to decrypt activity ${activity.activityId} in container ${activity.targetId}`;
230
290
 
231
291
  ctx.webex.logger.error(reason);
@@ -236,159 +296,308 @@ class Transforms {
236
296
 
237
297
  // Decrypt activity message if present
238
298
  if (activity.objectDisplayName) {
239
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
240
- [activity.encryptionKeyUrl, activity.objectDisplayName, {onBehalfOf: container.onBehalfOfUser}])
241
- .then((decryptedMessage) => {
242
- activity.objectDisplayName = decryptedMessage;
243
- })
244
- .catch((reason) => {
245
- ctx.webex.logger.error(`Decrypt message error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`);
246
- // add error property to activity - this error will be recorded in the downloader and the activity omitted from the report
247
- activity.error = reason;
248
-
249
- return Promise.resolve(object);
250
- }));
299
+ promises.push(
300
+ requestWithRetries(
301
+ ctx.webex.internal.encryption,
302
+ ctx.webex.internal.encryption.decryptText,
303
+ [
304
+ activity.encryptionKeyUrl,
305
+ activity.objectDisplayName,
306
+ {onBehalfOf: container.onBehalfOfUser},
307
+ ]
308
+ )
309
+ .then((decryptedMessage) => {
310
+ activity.objectDisplayName = decryptedMessage;
311
+ })
312
+ .catch((reason) => {
313
+ ctx.webex.logger.error(
314
+ `Decrypt message error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`
315
+ );
316
+ // add error property to activity - this error will be recorded in the downloader and the activity omitted from the report
317
+ activity.error = reason;
318
+
319
+ return Promise.resolve(object);
320
+ })
321
+ );
251
322
  }
252
323
 
253
324
  // If the activity is a space information update, decrypt the name and description if present
254
325
  if (activity.spaceInfo?.name) {
255
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
256
- [activity.encryptionKeyUrl, activity.spaceInfo.name, {onBehalfOf: container.onBehalfOfUser}])
257
- .then((decryptedMessage) => {
258
- activity.spaceInfo.name = decryptedMessage;
259
- })
260
- .catch((reason) => {
261
- ctx.webex.logger.error(`Decrypt activity.spaceInfo.name error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`);
262
- activity.error = reason;
263
-
264
- return Promise.resolve(object);
265
- }));
326
+ promises.push(
327
+ requestWithRetries(
328
+ ctx.webex.internal.encryption,
329
+ ctx.webex.internal.encryption.decryptText,
330
+ [
331
+ activity.encryptionKeyUrl,
332
+ activity.spaceInfo.name,
333
+ {onBehalfOf: container.onBehalfOfUser},
334
+ ]
335
+ )
336
+ .then((decryptedMessage) => {
337
+ activity.spaceInfo.name = decryptedMessage;
338
+ })
339
+ .catch((reason) => {
340
+ ctx.webex.logger.error(
341
+ `Decrypt activity.spaceInfo.name error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`
342
+ );
343
+ activity.error = reason;
344
+
345
+ return Promise.resolve(object);
346
+ })
347
+ );
266
348
  }
267
349
  if (activity.spaceInfo?.description) {
268
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
269
- [activity.encryptionKeyUrl, activity.spaceInfo.description, {onBehalfOf: container.onBehalfOfUser}])
270
- .then((decryptedMessage) => {
271
- activity.spaceInfo.description = decryptedMessage;
272
- })
273
- .catch((reason) => {
274
- ctx.webex.logger.error(`Decrypt activity.spaceInfo.description error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`);
275
- activity.error = reason;
276
-
277
- return Promise.resolve(object);
278
- }));
350
+ promises.push(
351
+ requestWithRetries(
352
+ ctx.webex.internal.encryption,
353
+ ctx.webex.internal.encryption.decryptText,
354
+ [
355
+ activity.encryptionKeyUrl,
356
+ activity.spaceInfo.description,
357
+ {onBehalfOf: container.onBehalfOfUser},
358
+ ]
359
+ )
360
+ .then((decryptedMessage) => {
361
+ activity.spaceInfo.description = decryptedMessage;
362
+ })
363
+ .catch((reason) => {
364
+ ctx.webex.logger.error(
365
+ `Decrypt activity.spaceInfo.description error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`
366
+ );
367
+ activity.error = reason;
368
+
369
+ return Promise.resolve(object);
370
+ })
371
+ );
279
372
  }
280
373
  if (activity.spaceInfo?.previousName && activity.spaceInfo.previousEncryptionKeyUrl) {
281
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
282
- [activity.spaceInfo.previousEncryptionKeyUrl, activity.spaceInfo.previousName, {onBehalfOf: container.onBehalfOfUser}])
283
- .then((decryptedMessage) => {
284
- activity.spaceInfo.previousName = decryptedMessage;
285
- })
286
- .catch((reason) => {
287
- ctx.webex.logger.error(`Decrypt activity.spaceInfo.previousName error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`);
288
- activity.error = reason;
289
-
290
- return Promise.resolve(object);
291
- }));
374
+ promises.push(
375
+ requestWithRetries(
376
+ ctx.webex.internal.encryption,
377
+ ctx.webex.internal.encryption.decryptText,
378
+ [
379
+ activity.spaceInfo.previousEncryptionKeyUrl,
380
+ activity.spaceInfo.previousName,
381
+ {onBehalfOf: container.onBehalfOfUser},
382
+ ]
383
+ )
384
+ .then((decryptedMessage) => {
385
+ activity.spaceInfo.previousName = decryptedMessage;
386
+ })
387
+ .catch((reason) => {
388
+ ctx.webex.logger.error(
389
+ `Decrypt activity.spaceInfo.previousName error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`
390
+ );
391
+ activity.error = reason;
392
+
393
+ return Promise.resolve(object);
394
+ })
395
+ );
292
396
  }
293
397
 
294
398
  // Decrypt content url and display name if extension is present
295
- if (activity.extension && activity.extension.objectType === 'extension' && activity.extension.extensionType === 'customApp') {
296
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
297
- [activity.encryptionKeyUrl, activity.extension.contentUrl, {onBehalfOf: container.onBehalfOfUser}])
298
- .then((decryptedContentUrl) => {
299
- activity.extension.contentUrl = decryptedContentUrl;
300
- })
301
- .catch((reason) => {
302
- ctx.webex.logger.error(`Decrypt activity.extension.contentUrl error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`);
303
- activity.error = reason;
304
-
305
- return Promise.resolve(object);
306
- }));
307
-
308
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
309
- [activity.encryptionKeyUrl, activity.extension.displayName, {onBehalfOf: container.onBehalfOfUser}])
310
- .then((decryptedDisplayName) => {
311
- activity.extension.displayName = decryptedDisplayName;
312
- })
313
- .catch((reason) => {
314
- ctx.webex.logger.error(`Decrypt activity.extension.displayName error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`);
315
- activity.error = reason;
316
-
317
- return Promise.resolve(object);
318
- }));
399
+ if (
400
+ activity.extension &&
401
+ activity.extension.objectType === 'extension' &&
402
+ activity.extension.extensionType === 'customApp'
403
+ ) {
404
+ promises.push(
405
+ requestWithRetries(
406
+ ctx.webex.internal.encryption,
407
+ ctx.webex.internal.encryption.decryptText,
408
+ [
409
+ activity.encryptionKeyUrl,
410
+ activity.extension.contentUrl,
411
+ {onBehalfOf: container.onBehalfOfUser},
412
+ ]
413
+ )
414
+ .then((decryptedContentUrl) => {
415
+ activity.extension.contentUrl = decryptedContentUrl;
416
+ })
417
+ .catch((reason) => {
418
+ ctx.webex.logger.error(
419
+ `Decrypt activity.extension.contentUrl error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`
420
+ );
421
+ activity.error = reason;
319
422
 
320
- // Decrypt webUrl.
321
- if (activity.extension.webUrl) {
322
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
323
- [activity.encryptionKeyUrl, activity.extension.webUrl, {onBehalfOf: container.onBehalfOfUser}])
324
- .then((decryptedWebUrl) => {
325
- activity.extension.webUrl = decryptedWebUrl;
423
+ return Promise.resolve(object);
424
+ })
425
+ );
426
+
427
+ promises.push(
428
+ requestWithRetries(
429
+ ctx.webex.internal.encryption,
430
+ ctx.webex.internal.encryption.decryptText,
431
+ [
432
+ activity.encryptionKeyUrl,
433
+ activity.extension.displayName,
434
+ {onBehalfOf: container.onBehalfOfUser},
435
+ ]
436
+ )
437
+ .then((decryptedDisplayName) => {
438
+ activity.extension.displayName = decryptedDisplayName;
326
439
  })
327
440
  .catch((reason) => {
328
- ctx.webex.logger.error(`Decrypt activity.extension.webUrl error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`);
441
+ ctx.webex.logger.error(
442
+ `Decrypt activity.extension.displayName error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`
443
+ );
329
444
  activity.error = reason;
330
445
 
331
446
  return Promise.resolve(object);
332
- }));
333
- }
334
- if (activity.verb === 'update' && activity.extension.previous) {
335
- if (activity.extension.previous.contentUrl) {
336
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
337
- [activity.encryptionKeyUrl, activity.extension.previous.contentUrl, {onBehalfOf: container.onBehalfOfUser}])
338
- .then((decryptedPreviousContentUrl) => {
339
- activity.extension.previous.contentUrl = decryptedPreviousContentUrl;
447
+ })
448
+ );
449
+
450
+ // Decrypt webUrl.
451
+ if (activity.extension.webUrl) {
452
+ promises.push(
453
+ requestWithRetries(
454
+ ctx.webex.internal.encryption,
455
+ ctx.webex.internal.encryption.decryptText,
456
+ [
457
+ activity.encryptionKeyUrl,
458
+ activity.extension.webUrl,
459
+ {onBehalfOf: container.onBehalfOfUser},
460
+ ]
461
+ )
462
+ .then((decryptedWebUrl) => {
463
+ activity.extension.webUrl = decryptedWebUrl;
340
464
  })
341
465
  .catch((reason) => {
342
- ctx.webex.logger.error(`Decrypt activity.extension.previous.contentUrl error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`);
466
+ ctx.webex.logger.error(
467
+ `Decrypt activity.extension.webUrl error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`
468
+ );
343
469
  activity.error = reason;
344
470
 
345
471
  return Promise.resolve(object);
346
- }));
472
+ })
473
+ );
474
+ }
475
+ if (activity.verb === 'update' && activity.extension.previous) {
476
+ if (activity.extension.previous.contentUrl) {
477
+ promises.push(
478
+ requestWithRetries(
479
+ ctx.webex.internal.encryption,
480
+ ctx.webex.internal.encryption.decryptText,
481
+ [
482
+ activity.encryptionKeyUrl,
483
+ activity.extension.previous.contentUrl,
484
+ {onBehalfOf: container.onBehalfOfUser},
485
+ ]
486
+ )
487
+ .then((decryptedPreviousContentUrl) => {
488
+ activity.extension.previous.contentUrl = decryptedPreviousContentUrl;
489
+ })
490
+ .catch((reason) => {
491
+ ctx.webex.logger.error(
492
+ `Decrypt activity.extension.previous.contentUrl error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`
493
+ );
494
+ activity.error = reason;
495
+
496
+ return Promise.resolve(object);
497
+ })
498
+ );
347
499
  }
348
500
  if (activity.extension.previous.displayName) {
349
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
350
- [activity.encryptionKeyUrl, activity.extension.previous.displayName, {onBehalfOf: container.onBehalfOfUser}])
351
- .then((decryptedPreviousDisplayName) => {
352
- activity.extension.previous.displayName = decryptedPreviousDisplayName;
501
+ promises.push(
502
+ requestWithRetries(
503
+ ctx.webex.internal.encryption,
504
+ ctx.webex.internal.encryption.decryptText,
505
+ [
506
+ activity.encryptionKeyUrl,
507
+ activity.extension.previous.displayName,
508
+ {onBehalfOf: container.onBehalfOfUser},
509
+ ]
510
+ )
511
+ .then((decryptedPreviousDisplayName) => {
512
+ activity.extension.previous.displayName = decryptedPreviousDisplayName;
513
+ })
514
+ .catch((reason) => {
515
+ ctx.webex.logger.error(
516
+ `Decrypt activity.extension.previous.displayName error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`
517
+ );
518
+ activity.error = reason;
519
+
520
+ return Promise.resolve(object);
521
+ })
522
+ );
523
+ }
524
+ }
525
+ }
526
+
527
+ // Decrypt encrypted text map if present
528
+ if (activity.encryptedTextKeyValues !== undefined) {
529
+ for (const [key, value] of Object.entries(activity.encryptedTextKeyValues)) {
530
+ promises.push(
531
+ requestWithRetries(
532
+ ctx.webex.internal.encryption,
533
+ ctx.webex.internal.encryption.decryptText,
534
+ [activity.encryptionKeyUrl, value]
535
+ )
536
+ .then((decryptedMessage) => {
537
+ activity.encryptedTextKeyValues[key] = decryptedMessage;
353
538
  })
354
539
  .catch((reason) => {
355
- ctx.webex.logger.error(`Decrypt activity.extension.previous.displayName error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`);
540
+ ctx.webex.logger.error(
541
+ `Decrypt activity.encryptedTextKeyValues error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`
542
+ );
356
543
  activity.error = reason;
357
544
 
358
545
  return Promise.resolve(object);
359
- }));
360
- }
546
+ })
547
+ );
361
548
  }
362
549
  }
363
550
 
364
551
  // Decrypt meeting title if present
365
552
  if (activity?.meeting?.title) {
366
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
367
- [activity.encryptionKeyUrl, activity.meeting.title, {onBehalfOf: container.onBehalfOfUser}])
368
- .then((decryptedMessage) => {
369
- activity.meeting.title = decryptedMessage;
370
- })
371
- .catch((reason) => {
372
- ctx.webex.logger.error(`Decrypt activity.meeting.title error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`);
373
- activity.error = reason;
374
-
375
- return Promise.resolve(object);
376
- }));
553
+ promises.push(
554
+ requestWithRetries(
555
+ ctx.webex.internal.encryption,
556
+ ctx.webex.internal.encryption.decryptText,
557
+ [
558
+ activity.encryptionKeyUrl,
559
+ activity.meeting.title,
560
+ {onBehalfOf: container.onBehalfOfUser},
561
+ ]
562
+ )
563
+ .then((decryptedMessage) => {
564
+ activity.meeting.title = decryptedMessage;
565
+ })
566
+ .catch((reason) => {
567
+ ctx.webex.logger.error(
568
+ `Decrypt activity.meeting.title error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`
569
+ );
570
+ activity.error = reason;
571
+
572
+ return Promise.resolve(object);
573
+ })
574
+ );
377
575
  }
378
576
 
379
577
  // Decrypt meeting recording topic if present
380
578
  if (activity?.recording?.topic) {
381
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
382
- [activity.encryptionKeyUrl, activity.recording.topic, {onBehalfOf: container.onBehalfOfUser}])
383
- .then((decryptedMessage) => {
384
- activity.recording.topic = decryptedMessage;
385
- })
386
- .catch((reason) => {
387
- ctx.webex.logger.error(`Decrypt activity.recording.topic error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`);
388
- activity.error = reason;
389
-
390
- return Promise.resolve(object);
391
- }));
579
+ promises.push(
580
+ requestWithRetries(
581
+ ctx.webex.internal.encryption,
582
+ ctx.webex.internal.encryption.decryptText,
583
+ [
584
+ activity.encryptionKeyUrl,
585
+ activity.recording.topic,
586
+ {onBehalfOf: container.onBehalfOfUser},
587
+ ]
588
+ )
589
+ .then((decryptedMessage) => {
590
+ activity.recording.topic = decryptedMessage;
591
+ })
592
+ .catch((reason) => {
593
+ ctx.webex.logger.error(
594
+ `Decrypt activity.recording.topic error for activity ${activity.activityId} in container ${activity.targetId}: ${reason}`
595
+ );
596
+ activity.error = reason;
597
+
598
+ return Promise.resolve(object);
599
+ })
600
+ );
392
601
  }
393
602
 
394
603
  // Decrypt shares (files, whiteboards, shared links)
@@ -402,49 +611,85 @@ class Transforms {
402
611
 
403
612
  // Decrypt the share's display name
404
613
  // Ignore display names for whiteboards which are unencrypted
405
- if (share.displayName && (!activity.whiteboards || !activity.whiteboards.includes(share))) {
406
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
407
- [activity.encryptionKeyUrl, share.displayName, {onBehalfOf: container.onBehalfOfUser}])
408
- .then((decryptedDisplayName) => {
409
- share.displayName = decryptedDisplayName;
410
- })
411
- .catch((reason) => {
412
- ctx.webex.logger.warn(`Decrypt DisplayName error for activity ${activity.activityId} in container ${activity.targetId} for share type: ${share.mimeType}, size: ${share.fileSize}, and url: ${share.url} due to error: ${reason}`);
413
- // add warning property to activity - this will present an indication that there was data loss on the downloader
414
- activity.warning = reason;
415
- }));
614
+ if (
615
+ share.displayName &&
616
+ (!activity.whiteboards || !activity.whiteboards.includes(share))
617
+ ) {
618
+ promises.push(
619
+ requestWithRetries(
620
+ ctx.webex.internal.encryption,
621
+ ctx.webex.internal.encryption.decryptText,
622
+ [
623
+ activity.encryptionKeyUrl,
624
+ share.displayName,
625
+ {onBehalfOf: container.onBehalfOfUser},
626
+ ]
627
+ )
628
+ .then((decryptedDisplayName) => {
629
+ share.displayName = decryptedDisplayName;
630
+ })
631
+ .catch((reason) => {
632
+ ctx.webex.logger.warn(
633
+ `Decrypt DisplayName error for activity ${activity.activityId} in container ${activity.targetId} for share type: ${share.mimeType}, size: ${share.fileSize}, and url: ${share.url} due to error: ${reason}`
634
+ );
635
+ // add warning property to activity - this will present an indication that there was data loss on the downloader
636
+ activity.warning = reason;
637
+ })
638
+ );
416
639
  }
417
640
 
418
641
  // Shared Links can have additional decryption fields
419
642
  if (share.microsoftSharedLinkInfo) {
420
643
  if (share.microsoftSharedLinkInfo.driveId) {
421
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
422
- [activity.encryptionKeyUrl, share.microsoftSharedLinkInfo.driveId, {onBehalfOf: container.onBehalfOfUser}])
423
- .then((decryptedDriveId) => {
424
- share.microsoftSharedLinkInfo.driveId = decryptedDriveId;
425
- })
426
- .catch((reason) => {
427
- ctx.webex.logger.error(`Decrypt share.microsoftSharedLinkInfo.driveId error for activity ${activity.activityId} in container ${activity.targetId} for share type: ${share.mimeType}, size: ${share.fileSize}, and url: ${share.url} due to error: ${reason}`);
428
- // add error property to activity - this error will be recorded in the downloader and the activity omitted from the report
429
- activity.error = reason;
430
-
431
- return Promise.resolve(object);
432
- }));
644
+ promises.push(
645
+ requestWithRetries(
646
+ ctx.webex.internal.encryption,
647
+ ctx.webex.internal.encryption.decryptText,
648
+ [
649
+ activity.encryptionKeyUrl,
650
+ share.microsoftSharedLinkInfo.driveId,
651
+ {onBehalfOf: container.onBehalfOfUser},
652
+ ]
653
+ )
654
+ .then((decryptedDriveId) => {
655
+ share.microsoftSharedLinkInfo.driveId = decryptedDriveId;
656
+ })
657
+ .catch((reason) => {
658
+ ctx.webex.logger.error(
659
+ `Decrypt share.microsoftSharedLinkInfo.driveId error for activity ${activity.activityId} in container ${activity.targetId} for share type: ${share.mimeType}, size: ${share.fileSize}, and url: ${share.url} due to error: ${reason}`
660
+ );
661
+ // add error property to activity - this error will be recorded in the downloader and the activity omitted from the report
662
+ activity.error = reason;
663
+
664
+ return Promise.resolve(object);
665
+ })
666
+ );
433
667
  }
434
668
 
435
669
  if (share.microsoftSharedLinkInfo.itemId) {
436
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
437
- [activity.encryptionKeyUrl, share.microsoftSharedLinkInfo.itemId, {onBehalfOf: container.onBehalfOfUser}])
438
- .then((decryptedItemId) => {
439
- share.microsoftSharedLinkInfo.itemId = decryptedItemId;
440
- })
441
- .catch((reason) => {
442
- ctx.webex.logger.error(`Decrypt share.microsoftSharedLinkInfo.itemId error for activity ${activity.activityId} in container ${activity.targetId} for share type: ${share.mimeType}, size: ${share.fileSize}, and url: ${share.url} due to error: ${reason}`);
443
- // add error property to activity - this error will be recorded in the downloader and the activity omitted from the report
444
- activity.error = reason;
445
-
446
- return Promise.resolve(object);
447
- }));
670
+ promises.push(
671
+ requestWithRetries(
672
+ ctx.webex.internal.encryption,
673
+ ctx.webex.internal.encryption.decryptText,
674
+ [
675
+ activity.encryptionKeyUrl,
676
+ share.microsoftSharedLinkInfo.itemId,
677
+ {onBehalfOf: container.onBehalfOfUser},
678
+ ]
679
+ )
680
+ .then((decryptedItemId) => {
681
+ share.microsoftSharedLinkInfo.itemId = decryptedItemId;
682
+ })
683
+ .catch((reason) => {
684
+ ctx.webex.logger.error(
685
+ `Decrypt share.microsoftSharedLinkInfo.itemId error for activity ${activity.activityId} in container ${activity.targetId} for share type: ${share.mimeType}, size: ${share.fileSize}, and url: ${share.url} due to error: ${reason}`
686
+ );
687
+ // add error property to activity - this error will be recorded in the downloader and the activity omitted from the report
688
+ activity.error = reason;
689
+
690
+ return Promise.resolve(object);
691
+ })
692
+ );
448
693
  }
449
694
  }
450
695
 
@@ -452,32 +697,44 @@ class Transforms {
452
697
  // Unlike a scr the sslr contains only a loc. But decryptScr(...) is flexible and
453
698
  // leaves the tag, auth, IV, etc fields on the SCR object as undefined.
454
699
  if (share.scr || share.sslr) {
455
- promises.push(requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptScr,
456
- // A share will have an encryptionKeyUrl when it's activity uses a different encryptionKeyUrl. This can happen when old activities are edited
457
- // and key rotation is turn on.
458
- [share.encryptionKeyUrl || activity.encryptionKeyUrl, share.scr || share.sslr, {onBehalfOf: container.onBehalfOfUser}])
459
- .then((decryptedSCR) => {
460
- if (share.scr) {
461
- share.scr = decryptedSCR;
462
- }
463
- else {
464
- share.sslr = decryptedSCR.loc;
465
- }
466
- })
467
- .catch((reason) => {
468
- ctx.webex.logger.error(`Decrypt file scr or sslr error for activity ${activity.activityId} in container ${activity.targetId} for share type: ${share.mimeType}, size: ${share.fileSize}, and url: ${share.url} due to error: ${reason}`);
469
- // add error property to activity - this error will be recorded in the downloader and the activity omitted from the report
470
- activity.error = reason;
700
+ promises.push(
701
+ requestWithRetries(
702
+ ctx.webex.internal.encryption,
703
+ ctx.webex.internal.encryption.decryptScr,
704
+ // A share will have an encryptionKeyUrl when it's activity uses a different encryptionKeyUrl. This can happen when old activities are edited
705
+ // and key rotation is turn on.
706
+ [
707
+ share.encryptionKeyUrl || activity.encryptionKeyUrl,
708
+ share.scr || share.sslr,
709
+ {onBehalfOf: container.onBehalfOfUser},
710
+ ]
711
+ )
712
+ .then((decryptedSCR) => {
713
+ if (share.scr) {
714
+ share.scr = decryptedSCR;
715
+ } else {
716
+ share.sslr = decryptedSCR.loc;
717
+ }
718
+ })
719
+ .catch((reason) => {
720
+ ctx.webex.logger.error(
721
+ `Decrypt file scr or sslr error for activity ${activity.activityId} in container ${activity.targetId} for share type: ${share.mimeType}, size: ${share.fileSize}, and url: ${share.url} due to error: ${reason}`
722
+ );
723
+ // add error property to activity - this error will be recorded in the downloader and the activity omitted from the report
724
+ activity.error = reason;
471
725
 
472
- return Promise.resolve(object);
473
- }));
726
+ return Promise.resolve(object);
727
+ })
728
+ );
474
729
  }
475
730
  }
476
731
 
477
732
  return Promise.all(promises);
478
733
  })
479
734
  .catch((reason) => {
480
- ctx.webex.logger.error(`Error retrieving content container for: ${activity.activityId} in container ${activity.targetId}: ${reason}`);
735
+ ctx.webex.logger.error(
736
+ `Error retrieving content container for: ${activity.activityId} in container ${activity.targetId}: ${reason}`
737
+ );
481
738
  // add error property to activity - this error will be recorded in the downloader and the activity omitted from the report
482
739
  activity.error = reason;
483
740
 
@@ -503,7 +760,9 @@ class Transforms {
503
760
 
504
761
  if (!container.encryptionKeyUrl) {
505
762
  // If the encryptionKeyUrl is empty we assume the container name is unencrypted
506
- ctx.webex.logger.info(`${container.containerType} container ${container.containerId} cannot be decrypted due to a missing encryption key url`);
763
+ ctx.webex.logger.info(
764
+ `${container.containerType} container ${container.containerId} cannot be decrypted due to a missing encryption key url`
765
+ );
507
766
 
508
767
  return Promise.resolve(object);
509
768
  }
@@ -519,26 +778,36 @@ class Transforms {
519
778
 
520
779
  // decrypt description if present with a descriptionEncryptionKeyUrl
521
780
  if (container.description && container.descriptionEncryptionKeyUrl) {
522
- requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
523
- [container.descriptionEncryptionKeyUrl, container.description, {onBehalfOf: container.onBehalfOfUser}])
781
+ requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText, [
782
+ container.descriptionEncryptionKeyUrl,
783
+ container.description,
784
+ {onBehalfOf: container.onBehalfOfUser},
785
+ ])
524
786
  .then((decryptedContainerDescription) => {
525
787
  container.description = decryptedContainerDescription;
526
788
  })
527
789
  .catch((reason) => {
528
- ctx.webex.logger.error(`Decrypt container description error for ${container.containerType} container ${container.containerId}: ${reason}`);
790
+ ctx.webex.logger.error(
791
+ `Decrypt container description error for ${container.containerType} container ${container.containerId}: ${reason}`
792
+ );
529
793
  // add warn property to container info - this warning will be recorded in the downloader
530
794
  container.warning = reason;
531
795
  // don't return, attempt to decrypt the name first
532
796
  });
533
797
  }
534
798
 
535
- return requestWithRetries(ctx.webex.internal.encryption, ctx.webex.internal.encryption.decryptText,
536
- [container.encryptionKeyUrl, container.containerName, {onBehalfOf: container.onBehalfOfUser}])
799
+ return requestWithRetries(
800
+ ctx.webex.internal.encryption,
801
+ ctx.webex.internal.encryption.decryptText,
802
+ [container.encryptionKeyUrl, container.containerName, {onBehalfOf: container.onBehalfOfUser}]
803
+ )
537
804
  .then((decryptedContainerName) => {
538
805
  container.containerName = decryptedContainerName;
539
806
  })
540
807
  .catch((reason) => {
541
- ctx.webex.logger.error(`Decrypt container name error for ${container.containerType} container ${container.containerId}: ${reason}`);
808
+ ctx.webex.logger.error(
809
+ `Decrypt container name error for ${container.containerType} container ${container.containerId}: ${reason}`
810
+ );
542
811
  // add warn property to container info - this warning will be recorded in the downloader
543
812
  container.warning = reason;
544
813