@webex/internal-plugin-conversation 3.0.0-beta.4 → 3.0.0-beta.400
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/README.md +1 -3
- package/dist/activities.js +8 -69
- package/dist/activities.js.map +1 -1
- package/dist/activity-thread-ordering.js +19 -79
- package/dist/activity-thread-ordering.js.map +1 -1
- package/dist/config.js +1 -7
- package/dist/config.js.map +1 -1
- package/dist/constants.js +4 -5
- package/dist/constants.js.map +1 -1
- package/dist/conversation.js +791 -1202
- package/dist/conversation.js.map +1 -1
- package/dist/convo-error.js +0 -23
- package/dist/convo-error.js.map +1 -1
- package/dist/decryption-transforms.js +35 -98
- package/dist/decryption-transforms.js.map +1 -1
- package/dist/encryption-transforms.js +17 -49
- package/dist/encryption-transforms.js.map +1 -1
- package/dist/index.js +7 -50
- package/dist/index.js.map +1 -1
- package/dist/share-activity.js +40 -106
- package/dist/share-activity.js.map +1 -1
- package/dist/to-array.js +9 -11
- package/dist/to-array.js.map +1 -1
- package/package.json +15 -15
- package/src/activities.js +10 -7
- package/src/activity-thread-ordering.js +27 -30
- package/src/activity-threading.md +68 -49
- package/src/config.js +5 -5
- package/src/conversation.js +621 -591
- package/src/decryption-transforms.js +103 -62
- package/src/encryption-transforms.js +111 -83
- package/src/index.js +82 -66
- package/src/share-activity.js +64 -55
- package/src/to-array.js +2 -2
- package/test/integration/spec/create.js +186 -121
- package/test/integration/spec/encryption.js +249 -186
- package/test/integration/spec/get.js +764 -514
- package/test/integration/spec/mercury.js +37 -27
- package/test/integration/spec/share.js +292 -229
- package/test/integration/spec/verbs.js +628 -441
- package/test/unit/spec/conversation.js +265 -163
- package/test/unit/spec/decrypt-transforms.js +112 -131
- package/test/unit/spec/encryption-transforms.js +47 -18
- package/test/unit/spec/share-activity.js +37 -40
|
@@ -6,11 +6,12 @@ import {camelCase, capitalize, curry} from 'lodash';
|
|
|
6
6
|
|
|
7
7
|
import toArray from './to-array';
|
|
8
8
|
|
|
9
|
-
const decryptTextProp = curry((name, ctx, key, object) =>
|
|
9
|
+
const decryptTextProp = curry((name, ctx, key, object) =>
|
|
10
|
+
ctx.transform('decryptTextProp', name, key, object)
|
|
11
|
+
);
|
|
10
12
|
|
|
11
13
|
// eslint-disable-next-line import/prefer-default-export
|
|
12
14
|
export const transforms = toArray('inbound', {
|
|
13
|
-
|
|
14
15
|
/**
|
|
15
16
|
* This function is used recursively to decrypt various properties on conversations, activities, etc
|
|
16
17
|
* @param {Object} ctx An object containing a webex instance and a transform
|
|
@@ -61,12 +62,15 @@ export const transforms = toArray('inbound', {
|
|
|
61
62
|
}
|
|
62
63
|
const {decryptionFailureMessage} = ctx.webex.internal.conversation.config;
|
|
63
64
|
|
|
64
|
-
return ctx
|
|
65
|
+
return ctx
|
|
66
|
+
.transform('decryptPropCardItem', 0, key, [object.inputs])
|
|
65
67
|
.then((inputs) => {
|
|
66
68
|
object.inputs = JSON.parse(inputs[0]); // eslint-disable-line no-param-reassign
|
|
67
69
|
})
|
|
68
70
|
.catch((reason) => {
|
|
69
|
-
ctx.webex.logger.warn(
|
|
71
|
+
ctx.webex.logger.warn(
|
|
72
|
+
`plugin-conversation: failed to decrypt attachmentAction.inputs: ${reason}`
|
|
73
|
+
);
|
|
70
74
|
object.inputs = decryptionFailureMessage; // eslint-disable-line no-param-reassign
|
|
71
75
|
|
|
72
76
|
return Promise.resolve(decryptionFailureMessage);
|
|
@@ -87,7 +91,9 @@ export const transforms = toArray('inbound', {
|
|
|
87
91
|
return Promise.resolve();
|
|
88
92
|
}
|
|
89
93
|
|
|
90
|
-
return Promise.all(
|
|
94
|
+
return Promise.all(
|
|
95
|
+
object.reactions.map((reaction) => ctx.transform('decryptPropDisplayName', key, reaction))
|
|
96
|
+
);
|
|
91
97
|
},
|
|
92
98
|
|
|
93
99
|
/**
|
|
@@ -106,7 +112,9 @@ export const transforms = toArray('inbound', {
|
|
|
106
112
|
return Promise.resolve();
|
|
107
113
|
}
|
|
108
114
|
|
|
109
|
-
return Promise.all(
|
|
115
|
+
return Promise.all(
|
|
116
|
+
object.reactions.map((reaction) => ctx.transform('decryptPropDisplayName', key, reaction))
|
|
117
|
+
);
|
|
110
118
|
},
|
|
111
119
|
|
|
112
120
|
/**
|
|
@@ -123,28 +131,30 @@ export const transforms = toArray('inbound', {
|
|
|
123
131
|
},
|
|
124
132
|
|
|
125
133
|
/**
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
134
|
+
* Decrypt an individual threadObject
|
|
135
|
+
* @param {Object} ctx An object containing a webex instance and a transform
|
|
136
|
+
* @param {Object} threadObject An instance of a Webex threadObject (the objects returned by the /conversation/api/v1/threads api)
|
|
137
|
+
* @returns {Promise} Returns a ctx.transform promise
|
|
138
|
+
*/
|
|
131
139
|
decryptThread(ctx, threadObject) {
|
|
132
140
|
let promises = [];
|
|
133
141
|
|
|
134
142
|
if (threadObject.childActivities && Array.isArray(threadObject.childActivities)) {
|
|
135
|
-
promises = threadObject.childActivities.map((child) =>
|
|
143
|
+
promises = threadObject.childActivities.map((child) =>
|
|
144
|
+
ctx.transform('decryptObject', null, child)
|
|
145
|
+
);
|
|
136
146
|
}
|
|
137
147
|
|
|
138
148
|
return Promise.all(promises);
|
|
139
149
|
},
|
|
140
150
|
|
|
141
151
|
/**
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
152
|
+
* Decrypt an individual meeting container activity
|
|
153
|
+
* @param {Object} ctx An object containing a webex instance and a transform
|
|
154
|
+
* @param {object} key KMS encryption key url
|
|
155
|
+
* @param {Object} meetingContainerActivity An instance of a Webex meeting container activity
|
|
156
|
+
* @returns {Promise} Returns a ctx.transform promise
|
|
157
|
+
*/
|
|
148
158
|
decryptMeetingcontainer(ctx, key, meetingContainerActivity) {
|
|
149
159
|
const promises = [];
|
|
150
160
|
|
|
@@ -155,10 +165,14 @@ export const transforms = toArray('inbound', {
|
|
|
155
165
|
}
|
|
156
166
|
|
|
157
167
|
if (meetingContainerActivity.extensions) {
|
|
158
|
-
const itemsToDecrypt = meetingContainerActivity.extensions.items.filter(
|
|
168
|
+
const itemsToDecrypt = meetingContainerActivity.extensions.items.filter(
|
|
169
|
+
(item) => item.data.objectType === 'recording'
|
|
170
|
+
);
|
|
159
171
|
|
|
160
172
|
itemsToDecrypt.forEach((itemToDecrypt) => {
|
|
161
|
-
promises.push(
|
|
173
|
+
promises.push(
|
|
174
|
+
ctx.transform('decryptPropTopic', itemToDecrypt.encryptionKeyUrl, itemToDecrypt.data)
|
|
175
|
+
);
|
|
162
176
|
});
|
|
163
177
|
}
|
|
164
178
|
|
|
@@ -178,22 +192,33 @@ export const transforms = toArray('inbound', {
|
|
|
178
192
|
const promises = [];
|
|
179
193
|
|
|
180
194
|
if (conversation.activities.items) {
|
|
181
|
-
promises.push(
|
|
195
|
+
promises.push(
|
|
196
|
+
Promise.all(
|
|
197
|
+
conversation.activities.items.map((item) => ctx.transform('decryptObject', null, item))
|
|
198
|
+
)
|
|
199
|
+
);
|
|
182
200
|
}
|
|
183
201
|
|
|
184
202
|
const usableKey = conversation.encryptionKeyUrl || key;
|
|
185
203
|
const {decryptionFailureMessage} = ctx.webex.internal.conversation.config;
|
|
186
204
|
|
|
187
205
|
if (usableKey) {
|
|
188
|
-
promises.push(
|
|
189
|
-
.catch((error) => {
|
|
190
|
-
ctx.webex.logger.warn(
|
|
206
|
+
promises.push(
|
|
207
|
+
ctx.transform('decryptPropDisplayName', usableKey, conversation).catch((error) => {
|
|
208
|
+
ctx.webex.logger.warn(
|
|
209
|
+
'plugin-conversation: failed to decrypt display name of ',
|
|
210
|
+
conversation.url,
|
|
211
|
+
error
|
|
212
|
+
);
|
|
191
213
|
Promise.resolve(decryptionFailureMessage);
|
|
192
|
-
})
|
|
214
|
+
})
|
|
215
|
+
);
|
|
193
216
|
promises.push(ctx.transform('decryptPropContent', usableKey, conversation));
|
|
194
217
|
}
|
|
195
218
|
if (conversation.avatarEncryptionKeyUrl) {
|
|
196
|
-
promises.push(
|
|
219
|
+
promises.push(
|
|
220
|
+
ctx.transform('decryptObject', conversation.avatarEncryptionKeyUrl, conversation.avatar)
|
|
221
|
+
);
|
|
197
222
|
}
|
|
198
223
|
// TODO (holsted 04/06/19): This was deprecated in favor of .previousValue below. I wanted to remove this entirely
|
|
199
224
|
// but I wasn't sure if some open source use cases may be reading from cached conversations or not so leaving it for now.
|
|
@@ -226,7 +251,9 @@ export const transforms = toArray('inbound', {
|
|
|
226
251
|
// iterate and recursively decrypt over children objects
|
|
227
252
|
|
|
228
253
|
if (activity.children && Array.isArray(activity.children)) {
|
|
229
|
-
promises = activity.children.map((child) =>
|
|
254
|
+
promises = activity.children.map((child) =>
|
|
255
|
+
ctx.transform('decryptObject', keyUrl, child.activity)
|
|
256
|
+
);
|
|
230
257
|
}
|
|
231
258
|
|
|
232
259
|
promises.push(ctx.transform('decryptObject', keyUrl, activity.object));
|
|
@@ -247,20 +274,22 @@ export const transforms = toArray('inbound', {
|
|
|
247
274
|
},
|
|
248
275
|
|
|
249
276
|
/**
|
|
250
|
-
* Decrypts a comment...
|
|
251
|
-
* @param {Object} ctx An object containing a webex instance and transform prop
|
|
252
|
-
* @param {String} key KMS key
|
|
253
|
-
* @param {Object} comment A comment object with a displayName and content (encrypted)
|
|
254
|
-
* @returns {Promise} Returns the results of Promise.all on two transforms
|
|
255
|
-
*/
|
|
277
|
+
* Decrypts a comment...
|
|
278
|
+
* @param {Object} ctx An object containing a webex instance and transform prop
|
|
279
|
+
* @param {String} key KMS key
|
|
280
|
+
* @param {Object} comment A comment object with a displayName and content (encrypted)
|
|
281
|
+
* @returns {Promise} Returns the results of Promise.all on two transforms
|
|
282
|
+
*/
|
|
256
283
|
decryptComment(ctx, key, comment) {
|
|
257
284
|
const promises = [
|
|
258
285
|
ctx.transform('decryptPropDisplayName', key, comment),
|
|
259
|
-
ctx.transform('decryptPropContent', key, comment)
|
|
286
|
+
ctx.transform('decryptPropContent', key, comment),
|
|
260
287
|
];
|
|
261
288
|
|
|
262
289
|
if (comment.cards && Array.isArray(comment.cards)) {
|
|
263
|
-
comment.cards.map((item, index) =>
|
|
290
|
+
comment.cards.map((item, index) =>
|
|
291
|
+
promises.push(ctx.transform('decryptPropCardItem', index, key, comment.cards))
|
|
292
|
+
);
|
|
264
293
|
}
|
|
265
294
|
|
|
266
295
|
return Promise.all(promises);
|
|
@@ -300,7 +329,9 @@ export const transforms = toArray('inbound', {
|
|
|
300
329
|
promises.push(ctx.transform('decryptComment', key, content));
|
|
301
330
|
|
|
302
331
|
if (content.links && content.links.items && Array.isArray(content.links.items)) {
|
|
303
|
-
content.links.items.forEach((item) =>
|
|
332
|
+
content.links.items.forEach((item) =>
|
|
333
|
+
promises.push(ctx.transform('decryptObject', key, item))
|
|
334
|
+
);
|
|
304
335
|
}
|
|
305
336
|
|
|
306
337
|
return Promise.all(promises);
|
|
@@ -334,9 +365,7 @@ export const transforms = toArray('inbound', {
|
|
|
334
365
|
* @returns {Promise} Returns the result of Promise.all
|
|
335
366
|
*/
|
|
336
367
|
decryptEvent(ctx, key, event) {
|
|
337
|
-
const promises = [
|
|
338
|
-
ctx.transform('decryptPropDisplayName', key, event)
|
|
339
|
-
];
|
|
368
|
+
const promises = [ctx.transform('decryptPropDisplayName', key, event)];
|
|
340
369
|
|
|
341
370
|
if (event.location && event.location.split('.').length === 5) {
|
|
342
371
|
promises.push(ctx.transform('decryptPropLocation', key, event));
|
|
@@ -359,11 +388,14 @@ export const transforms = toArray('inbound', {
|
|
|
359
388
|
}
|
|
360
389
|
|
|
361
390
|
return Promise.all([
|
|
362
|
-
file.transcodedCollection &&
|
|
391
|
+
file.transcodedCollection &&
|
|
392
|
+
Promise.all(
|
|
393
|
+
file.transcodedCollection.items.map((item) => ctx.transform('decryptObject', key, item))
|
|
394
|
+
),
|
|
363
395
|
ctx.transform('decryptPropScr', key, file),
|
|
364
396
|
ctx.transform('decryptPropDisplayName', key, file),
|
|
365
397
|
ctx.transform('decryptPropContent', key, file),
|
|
366
|
-
file.image && ctx.transform('decryptPropScr', key, file.image)
|
|
398
|
+
file.image && ctx.transform('decryptPropScr', key, file.image),
|
|
367
399
|
]);
|
|
368
400
|
},
|
|
369
401
|
|
|
@@ -377,7 +409,7 @@ export const transforms = toArray('inbound', {
|
|
|
377
409
|
decryptLink(ctx, key, link) {
|
|
378
410
|
return Promise.all([
|
|
379
411
|
ctx.transform('decryptPropSslr', key, link),
|
|
380
|
-
ctx.transform('decryptPropDisplayName', key, link)
|
|
412
|
+
ctx.transform('decryptPropDisplayName', key, link),
|
|
381
413
|
]);
|
|
382
414
|
},
|
|
383
415
|
|
|
@@ -389,7 +421,9 @@ export const transforms = toArray('inbound', {
|
|
|
389
421
|
* @returns {Promise} Returns the result of Promise.all
|
|
390
422
|
*/
|
|
391
423
|
decryptTranscodedContent(ctx, key, transcodedContent) {
|
|
392
|
-
return Promise.all(
|
|
424
|
+
return Promise.all(
|
|
425
|
+
transcodedContent.files.items.map((item) => ctx.transform('decryptFile', key, item))
|
|
426
|
+
);
|
|
393
427
|
},
|
|
394
428
|
|
|
395
429
|
/**
|
|
@@ -417,7 +451,8 @@ export const transforms = toArray('inbound', {
|
|
|
417
451
|
}
|
|
418
452
|
const {decryptionFailureMessage} = ctx.webex.internal.conversation.config;
|
|
419
453
|
|
|
420
|
-
return ctx.webex.internal.encryption
|
|
454
|
+
return ctx.webex.internal.encryption
|
|
455
|
+
.decryptText(key, object[name])
|
|
421
456
|
.then((plaintext) => {
|
|
422
457
|
if (ctx.webex.config.conversation.keepEncryptedProperties) {
|
|
423
458
|
const encryptedPropName = camelCase(`encrypted_${name}`);
|
|
@@ -436,20 +471,28 @@ export const transforms = toArray('inbound', {
|
|
|
436
471
|
},
|
|
437
472
|
|
|
438
473
|
/**
|
|
439
|
-
* Decrypting an element in an Array.
|
|
440
|
-
* @param {Object} ctx An object containing a webex instance and transform prop
|
|
441
|
-
* @param {Integer} index Property of an object to be decrypted
|
|
442
|
-
* @param {String} key KMS key
|
|
443
|
-
* @param {Array} array An array of Strings to be decrypted
|
|
444
|
-
* @returns {Promise} Returns a lonely Promise
|
|
445
|
-
*/
|
|
474
|
+
* Decrypting an element in an Array.
|
|
475
|
+
* @param {Object} ctx An object containing a webex instance and transform prop
|
|
476
|
+
* @param {Integer} index Property of an object to be decrypted
|
|
477
|
+
* @param {String} key KMS key
|
|
478
|
+
* @param {Array} array An array of Strings to be decrypted
|
|
479
|
+
* @returns {Promise} Returns a lonely Promise
|
|
480
|
+
*/
|
|
446
481
|
decryptPropCardItem(ctx, index, key, array) {
|
|
447
|
-
if (
|
|
482
|
+
if (
|
|
483
|
+
!Number.isInteger(index) ||
|
|
484
|
+
!array ||
|
|
485
|
+
!Array.isArray(array) ||
|
|
486
|
+
index < 0 ||
|
|
487
|
+
index >= array.length ||
|
|
488
|
+
!(array[index] instanceof String || typeof array[index] === 'string')
|
|
489
|
+
) {
|
|
448
490
|
return Promise.resolve();
|
|
449
491
|
}
|
|
450
492
|
const {decryptionFailureMessage} = ctx.webex.internal.conversation.config;
|
|
451
493
|
|
|
452
|
-
return ctx.webex.internal.encryption
|
|
494
|
+
return ctx.webex.internal.encryption
|
|
495
|
+
.decryptText(key, array[index])
|
|
453
496
|
.then((plaintext) => {
|
|
454
497
|
array[index] = plaintext; // eslint-disable-line no-param-reassign
|
|
455
498
|
})
|
|
@@ -468,10 +511,9 @@ export const transforms = toArray('inbound', {
|
|
|
468
511
|
* @returns {Promise} Returns a promise
|
|
469
512
|
*/
|
|
470
513
|
decryptPropScr(ctx, key, object) {
|
|
471
|
-
return ctx.webex.internal.encryption.decryptScr(key, object.scr)
|
|
472
|
-
.
|
|
473
|
-
|
|
474
|
-
});
|
|
514
|
+
return ctx.webex.internal.encryption.decryptScr(key, object.scr).then((scr) => {
|
|
515
|
+
object.scr = scr; // eslint-disable-line no-param-reassign
|
|
516
|
+
});
|
|
475
517
|
},
|
|
476
518
|
|
|
477
519
|
/**
|
|
@@ -482,10 +524,9 @@ export const transforms = toArray('inbound', {
|
|
|
482
524
|
* @returns {Promise} Returns a promise
|
|
483
525
|
*/
|
|
484
526
|
decryptPropSslr(ctx, key, object) {
|
|
485
|
-
return ctx.webex.internal.encryption.decryptScr(key, object.sslr)
|
|
486
|
-
.
|
|
487
|
-
|
|
488
|
-
});
|
|
527
|
+
return ctx.webex.internal.encryption.decryptScr(key, object.sslr).then((sslr) => {
|
|
528
|
+
object.sslr = sslr; // eslint-disable-line no-param-reassign
|
|
529
|
+
});
|
|
489
530
|
},
|
|
490
531
|
|
|
491
532
|
decryptPropDisplayName: decryptTextProp('displayName'),
|
|
@@ -496,5 +537,5 @@ export const transforms = toArray('inbound', {
|
|
|
496
537
|
|
|
497
538
|
decryptPropLocation: decryptTextProp('location'),
|
|
498
539
|
|
|
499
|
-
decryptPropTopic: decryptTextProp('topic')
|
|
540
|
+
decryptPropTopic: decryptTextProp('topic'),
|
|
500
541
|
});
|
|
@@ -2,21 +2,19 @@
|
|
|
2
2
|
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
capitalize,
|
|
7
|
-
curry,
|
|
8
|
-
get,
|
|
9
|
-
has,
|
|
10
|
-
isArray
|
|
11
|
-
} from 'lodash';
|
|
5
|
+
import {capitalize, curry, get, has, isArray} from 'lodash';
|
|
12
6
|
|
|
13
7
|
import toArray from './to-array';
|
|
14
8
|
|
|
15
9
|
const KEY = Symbol('KEY');
|
|
16
10
|
|
|
17
|
-
const encryptTextProp = curry((name, ctx, key, object) =>
|
|
11
|
+
const encryptTextProp = curry((name, ctx, key, object) =>
|
|
12
|
+
ctx.transform('encryptTextProp', name, key, object)
|
|
13
|
+
);
|
|
18
14
|
|
|
19
|
-
const encryptJsonProp = curry((name, ctx, key, object) =>
|
|
15
|
+
const encryptJsonProp = curry((name, ctx, key, object) =>
|
|
16
|
+
ctx.transform('encryptJsonProp', name, key, object)
|
|
17
|
+
);
|
|
20
18
|
|
|
21
19
|
// eslint-disable-next-line import/prefer-default-export
|
|
22
20
|
export const transforms = toArray('outbound', {
|
|
@@ -50,50 +48,63 @@ export const transforms = toArray('outbound', {
|
|
|
50
48
|
return Promise.resolve();
|
|
51
49
|
}
|
|
52
50
|
|
|
53
|
-
return Promise.resolve(
|
|
54
|
-
.
|
|
55
|
-
|
|
51
|
+
return Promise.resolve(
|
|
52
|
+
key || ctx.webex.internal.encryption.kms.createUnboundKeys({count: 1})
|
|
53
|
+
).then((keys) => {
|
|
54
|
+
const k = isArray(keys) ? keys[0] : keys;
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
if (
|
|
57
|
+
has(conversation, 'kmsMessage.keyUris') &&
|
|
58
|
+
!conversation.kmsMessage.keyUris.includes(k.uri)
|
|
59
|
+
) {
|
|
60
|
+
conversation.kmsMessage.keyUris.push(k.uri);
|
|
61
|
+
}
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
return Promise.all([
|
|
64
|
+
// too many implicit returns on the same line is difficult to interpret
|
|
65
|
+
// eslint-disable-next-line arrow-body-style
|
|
66
|
+
has(conversation, 'activities.items') &&
|
|
67
|
+
conversation.activities.items.reduce((p, activity) => {
|
|
65
68
|
// eslint-disable-next-line max-nested-callbacks
|
|
66
69
|
return p.then(() => ctx.transform('encryptObject', k, activity));
|
|
67
70
|
}, Promise.resolve()),
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
});
|
|
71
|
+
ctx.transform('encryptPropDisplayName', k, conversation),
|
|
72
|
+
]).then(() => {
|
|
73
|
+
conversation.encryptionKeyUrl = k.uri || k;
|
|
74
|
+
// we only want to set the defaultActivityEncryptionKeyUrl if we've
|
|
75
|
+
// bound a new key
|
|
76
|
+
if (!key) {
|
|
77
|
+
conversation.defaultActivityEncryptionKeyUrl =
|
|
78
|
+
conversation.defaultActivityEncryptionKeyUrl || k.uri || k;
|
|
79
|
+
}
|
|
78
80
|
});
|
|
81
|
+
});
|
|
79
82
|
},
|
|
80
83
|
|
|
81
84
|
encryptActivity(ctx, key, activity) {
|
|
85
|
+
// Meeting Container policy update requests do not need to be encrypted.
|
|
86
|
+
if (
|
|
87
|
+
activity?.target?.objectType === 'meetingContainer' &&
|
|
88
|
+
activity?.object?.objectType === 'policies'
|
|
89
|
+
) {
|
|
90
|
+
return Promise.resolve();
|
|
91
|
+
}
|
|
92
|
+
|
|
82
93
|
// Activity is already encrypted
|
|
83
94
|
if (activity.encryptionKeyUrl || activity.object?.created === 'True') {
|
|
84
95
|
return Promise.resolve();
|
|
85
96
|
}
|
|
86
97
|
|
|
87
|
-
return ctx.transform(`encrypt${capitalize(activity.verb)}Activity`, key, activity)
|
|
88
|
-
|
|
89
|
-
key = key || activity[KEY];
|
|
98
|
+
return ctx.transform(`encrypt${capitalize(activity.verb)}Activity`, key, activity).then(() => {
|
|
99
|
+
key = key || activity[KEY];
|
|
90
100
|
|
|
91
|
-
|
|
92
|
-
|
|
101
|
+
return ctx.transform('prepareActivityKmsMessage', key, activity);
|
|
102
|
+
});
|
|
93
103
|
},
|
|
94
104
|
|
|
95
105
|
encryptVerbActivity(ctx, key, activity) {
|
|
96
|
-
return ctx
|
|
106
|
+
return ctx
|
|
107
|
+
.transform('maybeEncryptTarget', key, activity)
|
|
97
108
|
.then(() => {
|
|
98
109
|
key = key || activity[KEY];
|
|
99
110
|
})
|
|
@@ -107,7 +118,8 @@ export const transforms = toArray('outbound', {
|
|
|
107
118
|
return Promise.resolve();
|
|
108
119
|
}
|
|
109
120
|
|
|
110
|
-
if (
|
|
121
|
+
if (
|
|
122
|
+
has(activity, 'target.defaultActivityEncryptionKeyUrl') &&
|
|
111
123
|
activity.target.defaultActivityEncryptionKeyUrl &&
|
|
112
124
|
has(activity, 'target.kmsResourceObjectUrl')
|
|
113
125
|
) {
|
|
@@ -119,34 +131,42 @@ export const transforms = toArray('outbound', {
|
|
|
119
131
|
const conversationUrl = activity.target && activity.target.url;
|
|
120
132
|
|
|
121
133
|
if (!conversationUrl) {
|
|
122
|
-
return Promise.reject(
|
|
134
|
+
return Promise.reject(
|
|
135
|
+
new Error(
|
|
136
|
+
"Cannot determine encryption key for activity's conversation; no key url or conversation url provided"
|
|
137
|
+
)
|
|
138
|
+
);
|
|
123
139
|
}
|
|
124
140
|
|
|
125
|
-
return ctx.webex.internal.conversation.get({url: conversationUrl})
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
141
|
+
return ctx.webex.internal.conversation.get({url: conversationUrl}).then((conversation) => {
|
|
142
|
+
if (!conversation.defaultActivityEncryptionKeyUrl) {
|
|
143
|
+
return ctx.webex.internal.conversation.updateKey(conversation).then((updateKeyActivity) => {
|
|
144
|
+
if (updateKeyActivity.kmsMessage.resource) {
|
|
145
|
+
activity.target.kmsResourceObjectUrl = updateKeyActivity.kmsMessage.resource.uri;
|
|
146
|
+
}
|
|
147
|
+
activity[KEY] = activity.target.defaultActivityEncryptionKeyUrl =
|
|
148
|
+
updateKeyActivity.object.defaultActivityEncryptionKeyUrl;
|
|
149
|
+
});
|
|
150
|
+
}
|
|
136
151
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
152
|
+
if (!activity.target.defaultActivityEncryptionKeyUrl) {
|
|
153
|
+
ctx.webex.logger.warn(
|
|
154
|
+
'plugin-conversation: downloaded conversation to determine its defaultActivityEncryptionKeyUrl; make sure to pass all encryption related properties when calling Webex.conversation methods.'
|
|
155
|
+
);
|
|
156
|
+
}
|
|
140
157
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
158
|
+
if (!activity.target.kmsResourceObjectUrl) {
|
|
159
|
+
ctx.webex.logger.warn(
|
|
160
|
+
'plugin-conversation: downloaded conversation to determine its kmsResourceObjectUrl; make sure to pass all encryption related properties when calling Webex.conversation methods.'
|
|
161
|
+
);
|
|
162
|
+
}
|
|
144
163
|
|
|
145
|
-
|
|
146
|
-
|
|
164
|
+
activity[KEY] = activity.target.defaultActivityEncryptionKeyUrl =
|
|
165
|
+
conversation.defaultActivityEncryptionKeyUrl;
|
|
166
|
+
activity.target.kmsResourceObjectUrl = conversation.kmsResourceObjectUrl;
|
|
147
167
|
|
|
148
|
-
|
|
149
|
-
|
|
168
|
+
return Promise.resolve();
|
|
169
|
+
});
|
|
150
170
|
},
|
|
151
171
|
|
|
152
172
|
prepareActivityKmsMessage(ctx, key, activity) {
|
|
@@ -155,11 +175,19 @@ export const transforms = toArray('outbound', {
|
|
|
155
175
|
key = get(activity, 'target.defaultActivityEncryptionKeyUrl');
|
|
156
176
|
}
|
|
157
177
|
|
|
158
|
-
if (
|
|
178
|
+
if (
|
|
179
|
+
!key &&
|
|
180
|
+
activity.verb === 'updateKey' &&
|
|
181
|
+
has(activity, 'object.defaultActivityEncryptionKeyUrl')
|
|
182
|
+
) {
|
|
159
183
|
key = get(activity, 'object.defaultActivityEncryptionKeyUrl');
|
|
160
184
|
}
|
|
161
185
|
|
|
162
|
-
if (
|
|
186
|
+
if (
|
|
187
|
+
!key &&
|
|
188
|
+
activity.verb === 'leave' &&
|
|
189
|
+
has(activity, 'target.defaultActivityEncryptionKeyUrl')
|
|
190
|
+
) {
|
|
163
191
|
key = get(activity, 'target.defaultActivityEncryptionKeyUrl');
|
|
164
192
|
}
|
|
165
193
|
|
|
@@ -190,12 +218,11 @@ export const transforms = toArray('outbound', {
|
|
|
190
218
|
encryptVerbActivityWithKey: {
|
|
191
219
|
direction: 'outbound',
|
|
192
220
|
fn(ctx, key, activity) {
|
|
193
|
-
return ctx.transform('encryptVerbActivity', key, activity)
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
221
|
+
return ctx.transform('encryptVerbActivity', key, activity).then(() => {
|
|
222
|
+
key = key || activity[KEY];
|
|
223
|
+
activity.encryptionKeyUrl = key.uri || key;
|
|
224
|
+
});
|
|
225
|
+
},
|
|
199
226
|
},
|
|
200
227
|
|
|
201
228
|
encryptAddActivity: {
|
|
@@ -206,48 +233,48 @@ export const transforms = toArray('outbound', {
|
|
|
206
233
|
}
|
|
207
234
|
|
|
208
235
|
return ctx.transform('encryptVerbActivity', key, activity);
|
|
209
|
-
}
|
|
236
|
+
},
|
|
210
237
|
},
|
|
211
238
|
|
|
212
239
|
encryptAssignActivity: {
|
|
213
240
|
direction: 'outbound',
|
|
214
|
-
alias: 'encryptVerbActivityWithKey'
|
|
241
|
+
alias: 'encryptVerbActivityWithKey',
|
|
215
242
|
},
|
|
216
243
|
|
|
217
244
|
encryptCreateActivity: {
|
|
218
245
|
direction: 'outbound',
|
|
219
|
-
alias: 'encryptVerbActivity'
|
|
246
|
+
alias: 'encryptVerbActivity',
|
|
220
247
|
},
|
|
221
248
|
|
|
222
249
|
encryptPostActivity: {
|
|
223
250
|
direction: 'outbound',
|
|
224
|
-
alias: 'encryptVerbActivityWithKey'
|
|
251
|
+
alias: 'encryptVerbActivityWithKey',
|
|
225
252
|
},
|
|
226
253
|
|
|
227
254
|
encryptShareActivity: {
|
|
228
255
|
direction: 'outbound',
|
|
229
|
-
alias: 'encryptVerbActivityWithKey'
|
|
256
|
+
alias: 'encryptVerbActivityWithKey',
|
|
230
257
|
},
|
|
231
258
|
|
|
232
259
|
encryptCardactionActivity: {
|
|
233
260
|
direction: 'outbound',
|
|
234
|
-
alias: 'encryptVerbActivityWithKey'
|
|
261
|
+
alias: 'encryptVerbActivityWithKey',
|
|
235
262
|
},
|
|
236
263
|
|
|
237
264
|
encryptUpdateActivity: {
|
|
238
265
|
direction: 'outbound',
|
|
239
|
-
alias: 'encryptVerbActivityWithKey'
|
|
266
|
+
alias: 'encryptVerbActivityWithKey',
|
|
240
267
|
},
|
|
241
268
|
|
|
242
269
|
encryptUpdateKeyActivity: {
|
|
243
270
|
direction: 'outbound',
|
|
244
|
-
alias: 'encryptVerbActivity'
|
|
271
|
+
alias: 'encryptVerbActivity',
|
|
245
272
|
},
|
|
246
273
|
|
|
247
274
|
encryptComment(ctx, key, comment) {
|
|
248
275
|
return Promise.all([
|
|
249
276
|
ctx.transform('encryptPropDisplayName', key, comment),
|
|
250
|
-
ctx.transform('encryptPropContent', key, comment)
|
|
277
|
+
ctx.transform('encryptPropContent', key, comment),
|
|
251
278
|
]);
|
|
252
279
|
},
|
|
253
280
|
|
|
@@ -269,7 +296,7 @@ export const transforms = toArray('outbound', {
|
|
|
269
296
|
ctx.transform('encryptPropScr', key, file),
|
|
270
297
|
ctx.transform('encryptPropDisplayName', key, file),
|
|
271
298
|
ctx.transform('encryptPropContent', key, file),
|
|
272
|
-
file.image && ctx.transform('encryptPropScr', key, file.image)
|
|
299
|
+
file.image && ctx.transform('encryptPropScr', key, file.image),
|
|
273
300
|
]);
|
|
274
301
|
},
|
|
275
302
|
|
|
@@ -295,10 +322,9 @@ export const transforms = toArray('outbound', {
|
|
|
295
322
|
return Promise.resolve();
|
|
296
323
|
}
|
|
297
324
|
|
|
298
|
-
return ctx.webex.internal.encryption.encryptScr(key, object.scr)
|
|
299
|
-
.
|
|
300
|
-
|
|
301
|
-
});
|
|
325
|
+
return ctx.webex.internal.encryption.encryptScr(key, object.scr).then((scr) => {
|
|
326
|
+
object.scr = scr;
|
|
327
|
+
});
|
|
302
328
|
},
|
|
303
329
|
|
|
304
330
|
encryptJsonProp(ctx, name, key, object) {
|
|
@@ -306,7 +332,8 @@ export const transforms = toArray('outbound', {
|
|
|
306
332
|
return Promise.resolve();
|
|
307
333
|
}
|
|
308
334
|
|
|
309
|
-
return ctx.webex.internal.encryption
|
|
335
|
+
return ctx.webex.internal.encryption
|
|
336
|
+
.encryptText(key.uri || key, JSON.stringify(object[name]))
|
|
310
337
|
.then((ciphertext) => {
|
|
311
338
|
object[name] = ciphertext;
|
|
312
339
|
});
|
|
@@ -317,9 +344,10 @@ export const transforms = toArray('outbound', {
|
|
|
317
344
|
return Promise.resolve();
|
|
318
345
|
}
|
|
319
346
|
|
|
320
|
-
return ctx.webex.internal.encryption
|
|
347
|
+
return ctx.webex.internal.encryption
|
|
348
|
+
.encryptText(key.uri || key, object[name])
|
|
321
349
|
.then((ciphertext) => {
|
|
322
350
|
object[name] = ciphertext;
|
|
323
351
|
});
|
|
324
|
-
}
|
|
352
|
+
},
|
|
325
353
|
});
|