@webex/internal-plugin-board 3.0.0-beta.13 → 3.0.0-beta.131
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/board.js +44 -110
- package/dist/board.js.map +1 -1
- package/dist/config.js +0 -8
- package/dist/config.js.map +1 -1
- package/dist/index.js +7 -28
- package/dist/index.js.map +1 -1
- package/dist/realtime-channel-collection.js +2 -8
- package/dist/realtime-channel-collection.js.map +1 -1
- package/dist/realtime-channel.js +1 -5
- package/dist/realtime-channel.js.map +1 -1
- package/dist/realtime.js +38 -82
- package/dist/realtime.js.map +1 -1
- package/package.json +14 -14
- package/src/board.js +273 -207
- package/src/config.js +2 -2
- package/src/index.js +19 -21
- package/src/realtime-channel-collection.js +2 -2
- package/src/realtime-channel.js +8 -9
- package/src/realtime.js +109 -93
- package/test/integration/spec/board.js +347 -221
- package/test/integration/spec/realtime.js +84 -57
- package/test/integration/spec/sharing-mercury.js +154 -73
- package/test/unit/spec/board.js +327 -216
- package/test/unit/spec/encryption.js +152 -120
- package/test/unit/spec/realtime.js +131 -89
package/src/board.js
CHANGED
|
@@ -14,7 +14,7 @@ const Board = WebexPlugin.extend({
|
|
|
14
14
|
namespace: 'Board',
|
|
15
15
|
|
|
16
16
|
children: {
|
|
17
|
-
realtime: Realtime
|
|
17
|
+
realtime: Realtime,
|
|
18
18
|
},
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -48,17 +48,20 @@ const Board = WebexPlugin.extend({
|
|
|
48
48
|
* @returns {Promise<Board~Content>}
|
|
49
49
|
*/
|
|
50
50
|
addImage(channel, image, metadata) {
|
|
51
|
-
return this.webex.internal.board._uploadImage(channel, image)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
51
|
+
return this.webex.internal.board._uploadImage(channel, image).then((scr) =>
|
|
52
|
+
this.webex.internal.board.addContent(channel, [
|
|
53
|
+
{
|
|
54
|
+
type: 'FILE',
|
|
55
|
+
metadata,
|
|
56
|
+
file: {
|
|
57
|
+
mimeType: image.type,
|
|
58
|
+
scr,
|
|
59
|
+
size: image.size,
|
|
60
|
+
url: scr.loc,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
])
|
|
64
|
+
);
|
|
62
65
|
},
|
|
63
66
|
|
|
64
67
|
/**
|
|
@@ -71,7 +74,8 @@ const Board = WebexPlugin.extend({
|
|
|
71
74
|
setSnapshotImage(channel, image) {
|
|
72
75
|
let imageScr;
|
|
73
76
|
|
|
74
|
-
return this.webex.internal.board
|
|
77
|
+
return this.webex.internal.board
|
|
78
|
+
._uploadImage(channel, image, {hiddenSpace: true})
|
|
75
79
|
.then((scr) => {
|
|
76
80
|
imageScr = scr;
|
|
77
81
|
|
|
@@ -91,14 +95,14 @@ const Board = WebexPlugin.extend({
|
|
|
91
95
|
mimeType: image.type || 'image/png',
|
|
92
96
|
scr: imageScr.encryptedScr,
|
|
93
97
|
encryptionKeyUrl: channel.defaultEncryptionKeyUrl,
|
|
94
|
-
fileSize: image.size
|
|
95
|
-
}
|
|
98
|
+
fileSize: image.size,
|
|
99
|
+
},
|
|
96
100
|
};
|
|
97
101
|
|
|
98
102
|
return this.webex.request({
|
|
99
103
|
method: 'PATCH',
|
|
100
104
|
uri: channel.channelUrl,
|
|
101
|
-
body: imageBody
|
|
105
|
+
body: imageBody,
|
|
102
106
|
});
|
|
103
107
|
})
|
|
104
108
|
.then((res) => res.body);
|
|
@@ -112,25 +116,41 @@ const Board = WebexPlugin.extend({
|
|
|
112
116
|
* @returns {Promise<Board~Channel>}
|
|
113
117
|
*/
|
|
114
118
|
createChannel(conversation, channel) {
|
|
115
|
-
return this.webex
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
return this.webex
|
|
120
|
+
.request({
|
|
121
|
+
method: 'POST',
|
|
122
|
+
api: 'board',
|
|
123
|
+
resource: '/channels',
|
|
124
|
+
body: this._prepareChannel(conversation, channel),
|
|
125
|
+
})
|
|
121
126
|
.then((res) => res.body);
|
|
122
127
|
},
|
|
123
128
|
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
/**
|
|
130
|
+
* Prepare a create request body to the board services based on the provided
|
|
131
|
+
* conversation and channel.
|
|
132
|
+
*
|
|
133
|
+
* @param {Conversation} conversation - Conversation object.
|
|
134
|
+
* @param {Channel} channel - Channel Object
|
|
135
|
+
* @returns {Object} - Create channel request body.
|
|
136
|
+
*/
|
|
137
|
+
_prepareChannel(conversation = {}, channel = {}) {
|
|
138
|
+
const results = {
|
|
126
139
|
aclUrlLink: conversation.aclUrl,
|
|
127
140
|
kmsMessage: {
|
|
128
141
|
method: 'create',
|
|
129
142
|
uri: '/resources',
|
|
130
|
-
userIds: [
|
|
131
|
-
keyUris: []
|
|
132
|
-
}
|
|
133
|
-
|
|
143
|
+
userIds: [],
|
|
144
|
+
keyUris: [],
|
|
145
|
+
},
|
|
146
|
+
...channel,
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
if (conversation.kmsResourceObjectUrl) {
|
|
150
|
+
results.kmsMessage.userIds.push(conversation.kmsResourceObjectUrl);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return results;
|
|
134
154
|
},
|
|
135
155
|
|
|
136
156
|
/**
|
|
@@ -150,9 +170,11 @@ const Board = WebexPlugin.extend({
|
|
|
150
170
|
linkedAcl: conversation.aclUrl,
|
|
151
171
|
kmsMessage: {
|
|
152
172
|
method: 'delete',
|
|
153
|
-
uri: `${channel.kmsResourceUrl}/authorizations?${querystring.stringify({
|
|
173
|
+
uri: `${channel.kmsResourceUrl}/authorizations?${querystring.stringify({
|
|
174
|
+
authId: conversation.kmsResourceObjectUrl,
|
|
175
|
+
})}`,
|
|
154
176
|
},
|
|
155
|
-
aclLinkOperation: 'DELETE'
|
|
177
|
+
aclLinkOperation: 'DELETE',
|
|
156
178
|
};
|
|
157
179
|
|
|
158
180
|
let promise = Promise.resolve();
|
|
@@ -162,11 +184,13 @@ const Board = WebexPlugin.extend({
|
|
|
162
184
|
}
|
|
163
185
|
|
|
164
186
|
return promise
|
|
165
|
-
.then(() =>
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
187
|
+
.then(() =>
|
|
188
|
+
this.webex.request({
|
|
189
|
+
method: 'PUT',
|
|
190
|
+
uri: `${channel.aclUrl}/links`,
|
|
191
|
+
body,
|
|
192
|
+
})
|
|
193
|
+
)
|
|
170
194
|
.then((res) => res.body);
|
|
171
195
|
},
|
|
172
196
|
|
|
@@ -178,13 +202,14 @@ const Board = WebexPlugin.extend({
|
|
|
178
202
|
* @returns {Promise}
|
|
179
203
|
*/
|
|
180
204
|
lockChannelForDeletion(channel) {
|
|
181
|
-
return this.webex
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
205
|
+
return this.webex
|
|
206
|
+
.request({
|
|
207
|
+
method: 'POST',
|
|
208
|
+
uri: `${channel.channelUrl}/lock`,
|
|
209
|
+
qs: {
|
|
210
|
+
intent: 'delete',
|
|
211
|
+
},
|
|
212
|
+
})
|
|
188
213
|
.then((res) => res.body);
|
|
189
214
|
},
|
|
190
215
|
|
|
@@ -196,7 +221,7 @@ const Board = WebexPlugin.extend({
|
|
|
196
221
|
keepActive(channel) {
|
|
197
222
|
return this.webex.request({
|
|
198
223
|
method: 'POST',
|
|
199
|
-
uri: `${channel.channelUrl}/keepAlive
|
|
224
|
+
uri: `${channel.channelUrl}/keepAlive`,
|
|
200
225
|
});
|
|
201
226
|
},
|
|
202
227
|
|
|
@@ -208,24 +233,24 @@ const Board = WebexPlugin.extend({
|
|
|
208
233
|
* @returns {Promise<Array>} Resolves with an array of {@link Board~Content} objects.
|
|
209
234
|
*/
|
|
210
235
|
decryptContents(contents) {
|
|
211
|
-
return Promise.all(
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
.then((res) => {
|
|
236
|
+
return Promise.all(
|
|
237
|
+
contents.items.map((content) => {
|
|
238
|
+
let decryptPromise;
|
|
239
|
+
|
|
240
|
+
if (content.type === 'FILE') {
|
|
241
|
+
decryptPromise = this.decryptSingleFileContent(content.encryptionKeyUrl, content);
|
|
242
|
+
} else {
|
|
243
|
+
decryptPromise = this.decryptSingleContent(content.encryptionKeyUrl, content.payload);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return decryptPromise.then((res) => {
|
|
223
247
|
Reflect.deleteProperty(content, 'payload');
|
|
224
248
|
Reflect.deleteProperty(content, 'encryptionKeyUrl');
|
|
225
249
|
|
|
226
250
|
return defaults(res, content);
|
|
227
251
|
});
|
|
228
|
-
|
|
252
|
+
})
|
|
253
|
+
);
|
|
229
254
|
},
|
|
230
255
|
|
|
231
256
|
/**
|
|
@@ -236,7 +261,8 @@ const Board = WebexPlugin.extend({
|
|
|
236
261
|
* @returns {Promise<Board~Content>}
|
|
237
262
|
*/
|
|
238
263
|
decryptSingleContent(encryptionKeyUrl, encryptedData) {
|
|
239
|
-
return this.webex.internal.encryption
|
|
264
|
+
return this.webex.internal.encryption
|
|
265
|
+
.decryptText(encryptionKeyUrl, encryptedData)
|
|
240
266
|
.then((res) => JSON.parse(res));
|
|
241
267
|
},
|
|
242
268
|
|
|
@@ -254,7 +280,8 @@ const Board = WebexPlugin.extend({
|
|
|
254
280
|
metadata = encryptedContent.payload;
|
|
255
281
|
}
|
|
256
282
|
|
|
257
|
-
return this.webex.internal.encryption
|
|
283
|
+
return this.webex.internal.encryption
|
|
284
|
+
.decryptScr(encryptionKeyUrl, encryptedContent.file.scr)
|
|
258
285
|
.then((scr) => {
|
|
259
286
|
encryptedContent.file.scr = scr;
|
|
260
287
|
if (metadata) {
|
|
@@ -269,8 +296,7 @@ const Board = WebexPlugin.extend({
|
|
|
269
296
|
if (encryptedContent.metadata.displayName) {
|
|
270
297
|
encryptedContent.displayName = encryptedContent.metadata.displayName;
|
|
271
298
|
}
|
|
272
|
-
}
|
|
273
|
-
catch (error) {
|
|
299
|
+
} catch (error) {
|
|
274
300
|
encryptedContent.metadata = {};
|
|
275
301
|
}
|
|
276
302
|
|
|
@@ -285,15 +311,18 @@ const Board = WebexPlugin.extend({
|
|
|
285
311
|
* @returns {Promise} Resolves with an content response
|
|
286
312
|
*/
|
|
287
313
|
deleteAllContent(channel) {
|
|
288
|
-
return this.webex
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
314
|
+
return this.webex
|
|
315
|
+
.request({
|
|
316
|
+
method: 'DELETE',
|
|
317
|
+
uri: `${channel.channelUrl}/contents`,
|
|
318
|
+
})
|
|
292
319
|
.then((res) => res.body);
|
|
293
320
|
},
|
|
294
321
|
|
|
295
322
|
/**
|
|
296
323
|
* Deletes Contents from a Channel except the ones listed in contentsToKeep
|
|
324
|
+
*
|
|
325
|
+
* THIS API HAS CHANGED!!! SEE SPARK-412694. NEEDS UPDATING.
|
|
297
326
|
* @memberof Board.BoardService
|
|
298
327
|
* @param {Board~Channel} channel
|
|
299
328
|
* @param {Array<Board~Content>} contentsToKeep Array of board objects (curves, text, and images) with valid contentId (received from server)
|
|
@@ -302,14 +331,15 @@ const Board = WebexPlugin.extend({
|
|
|
302
331
|
deletePartialContent(channel, contentsToKeep) {
|
|
303
332
|
const body = contentsToKeep.map((content) => pick(content, 'contentId'));
|
|
304
333
|
|
|
305
|
-
return this.webex
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
334
|
+
return this.webex
|
|
335
|
+
.request({
|
|
336
|
+
method: 'POST',
|
|
337
|
+
uri: `${channel.channelUrl}/contents`,
|
|
338
|
+
body,
|
|
339
|
+
qs: {
|
|
340
|
+
clearBoard: true,
|
|
341
|
+
},
|
|
342
|
+
})
|
|
313
343
|
.then((res) => res.body);
|
|
314
344
|
},
|
|
315
345
|
|
|
@@ -321,27 +351,31 @@ const Board = WebexPlugin.extend({
|
|
|
321
351
|
* @returns {Promise<Array>} Resolves with an array of encrypted {@link Board~Content} objects.
|
|
322
352
|
*/
|
|
323
353
|
encryptContents(encryptionKeyUrl, contents) {
|
|
324
|
-
return Promise.all(
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
354
|
+
return Promise.all(
|
|
355
|
+
contents.map((content) => {
|
|
356
|
+
let encryptionPromise;
|
|
357
|
+
let contentType = 'STRING';
|
|
358
|
+
|
|
359
|
+
// the existence of an scr will determine if the content is a FILE.
|
|
360
|
+
if (content.file) {
|
|
361
|
+
contentType = 'FILE';
|
|
362
|
+
encryptionPromise = this.encryptSingleFileContent(encryptionKeyUrl, content);
|
|
363
|
+
} else {
|
|
364
|
+
encryptionPromise = this.encryptSingleContent(encryptionKeyUrl, content);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return encryptionPromise.then((res) =>
|
|
368
|
+
assign(
|
|
369
|
+
{
|
|
370
|
+
device: this.webex.internal.device.deviceType,
|
|
371
|
+
type: contentType,
|
|
372
|
+
encryptionKeyUrl,
|
|
373
|
+
},
|
|
374
|
+
pick(res, 'file', 'payload')
|
|
375
|
+
)
|
|
376
|
+
);
|
|
377
|
+
})
|
|
378
|
+
);
|
|
345
379
|
},
|
|
346
380
|
|
|
347
381
|
/**
|
|
@@ -352,10 +386,11 @@ const Board = WebexPlugin.extend({
|
|
|
352
386
|
* @returns {Promise<Board~Content>}
|
|
353
387
|
*/
|
|
354
388
|
encryptSingleContent(encryptionKeyUrl, content) {
|
|
355
|
-
return this.webex.internal.encryption
|
|
389
|
+
return this.webex.internal.encryption
|
|
390
|
+
.encryptText(encryptionKeyUrl, JSON.stringify(content))
|
|
356
391
|
.then((res) => ({
|
|
357
392
|
payload: res,
|
|
358
|
-
encryptionKeyUrl
|
|
393
|
+
encryptionKeyUrl,
|
|
359
394
|
}));
|
|
360
395
|
},
|
|
361
396
|
|
|
@@ -367,14 +402,16 @@ const Board = WebexPlugin.extend({
|
|
|
367
402
|
* @returns {Promise<Board~Content>}
|
|
368
403
|
*/
|
|
369
404
|
encryptSingleFileContent(encryptionKeyUrl, content) {
|
|
370
|
-
return this.webex.internal.encryption
|
|
405
|
+
return this.webex.internal.encryption
|
|
406
|
+
.encryptScr(encryptionKeyUrl, content.file.scr)
|
|
371
407
|
.then((encryptedScr) => {
|
|
372
408
|
content.file.scr = encryptedScr;
|
|
373
409
|
if (content.displayName) {
|
|
374
410
|
content.metadata = assign(content.metadata, {displayName: content.displayName});
|
|
375
411
|
}
|
|
376
412
|
if (content.metadata) {
|
|
377
|
-
return this.webex.internal.encryption
|
|
413
|
+
return this.webex.internal.encryption
|
|
414
|
+
.encryptText(encryptionKeyUrl, JSON.stringify(content.metadata))
|
|
378
415
|
.then((encryptedMetadata) => {
|
|
379
416
|
content.metadata = encryptedMetadata;
|
|
380
417
|
});
|
|
@@ -385,7 +422,7 @@ const Board = WebexPlugin.extend({
|
|
|
385
422
|
.then(() => ({
|
|
386
423
|
file: content.file,
|
|
387
424
|
payload: content.metadata,
|
|
388
|
-
encryptionKeyUrl
|
|
425
|
+
encryptionKeyUrl,
|
|
389
426
|
}));
|
|
390
427
|
},
|
|
391
428
|
|
|
@@ -403,14 +440,13 @@ const Board = WebexPlugin.extend({
|
|
|
403
440
|
const params = {
|
|
404
441
|
uri: `${channel.channelUrl}/contents`,
|
|
405
442
|
qs: {
|
|
406
|
-
contentsLimit: this.config.numberContentsPerPageForGet
|
|
407
|
-
}
|
|
443
|
+
contentsLimit: this.config.numberContentsPerPageForGet,
|
|
444
|
+
},
|
|
408
445
|
};
|
|
409
446
|
|
|
410
447
|
assign(params.qs, pick(options, 'contentsLimit'));
|
|
411
448
|
|
|
412
|
-
return this.request(params)
|
|
413
|
-
.then((res) => new Page(res, this.webex));
|
|
449
|
+
return this.request(params).then((res) => new Page(res, this.webex));
|
|
414
450
|
},
|
|
415
451
|
|
|
416
452
|
/**
|
|
@@ -420,10 +456,11 @@ const Board = WebexPlugin.extend({
|
|
|
420
456
|
* @returns {Promise<Board~Channel>}
|
|
421
457
|
*/
|
|
422
458
|
getChannel(channel) {
|
|
423
|
-
return this.webex
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
459
|
+
return this.webex
|
|
460
|
+
.request({
|
|
461
|
+
method: 'GET',
|
|
462
|
+
uri: channel.channelUrl,
|
|
463
|
+
})
|
|
427
464
|
.then((res) => res.body);
|
|
428
465
|
},
|
|
429
466
|
|
|
@@ -447,14 +484,13 @@ const Board = WebexPlugin.extend({
|
|
|
447
484
|
api: 'board',
|
|
448
485
|
resource: '/channels',
|
|
449
486
|
qs: {
|
|
450
|
-
aclUrlLink: conversation.aclUrl
|
|
451
|
-
}
|
|
487
|
+
aclUrlLink: conversation.aclUrl,
|
|
488
|
+
},
|
|
452
489
|
};
|
|
453
490
|
|
|
454
491
|
assign(params.qs, pick(options, 'channelsLimit', 'type'));
|
|
455
492
|
|
|
456
|
-
return this.request(params)
|
|
457
|
-
.then((res) => new Page(res, this.webex));
|
|
493
|
+
return this.request(params).then((res) => new Page(res, this.webex));
|
|
458
494
|
},
|
|
459
495
|
|
|
460
496
|
/**
|
|
@@ -463,11 +499,12 @@ const Board = WebexPlugin.extend({
|
|
|
463
499
|
* @returns {Promise<Object>} ping response body
|
|
464
500
|
*/
|
|
465
501
|
ping() {
|
|
466
|
-
return this.webex
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
502
|
+
return this.webex
|
|
503
|
+
.request({
|
|
504
|
+
method: 'GET',
|
|
505
|
+
api: 'board',
|
|
506
|
+
resource: '/ping',
|
|
507
|
+
})
|
|
471
508
|
.then((res) => res.body);
|
|
472
509
|
},
|
|
473
510
|
|
|
@@ -475,19 +512,23 @@ const Board = WebexPlugin.extend({
|
|
|
475
512
|
let decryptionPromise;
|
|
476
513
|
|
|
477
514
|
if (message.contentType === 'FILE') {
|
|
478
|
-
decryptionPromise = this.decryptSingleFileContent(
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
515
|
+
decryptionPromise = this.decryptSingleFileContent(
|
|
516
|
+
message.envelope.encryptionKeyUrl,
|
|
517
|
+
message.payload
|
|
518
|
+
);
|
|
519
|
+
} else {
|
|
520
|
+
decryptionPromise = this.decryptSingleContent(
|
|
521
|
+
message.envelope.encryptionKeyUrl,
|
|
522
|
+
message.payload
|
|
523
|
+
);
|
|
482
524
|
}
|
|
483
525
|
|
|
484
|
-
return decryptionPromise
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
message.payload = decryptedData;
|
|
526
|
+
return decryptionPromise.then((decryptedData) => {
|
|
527
|
+
// call the event handlers
|
|
528
|
+
message.payload = decryptedData;
|
|
488
529
|
|
|
489
|
-
|
|
490
|
-
|
|
530
|
+
return message;
|
|
531
|
+
});
|
|
491
532
|
},
|
|
492
533
|
|
|
493
534
|
/**
|
|
@@ -497,12 +538,13 @@ const Board = WebexPlugin.extend({
|
|
|
497
538
|
* @returns {Promise<Board~Registration>}
|
|
498
539
|
*/
|
|
499
540
|
register(data) {
|
|
500
|
-
return this.webex
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
541
|
+
return this.webex
|
|
542
|
+
.request({
|
|
543
|
+
method: 'POST',
|
|
544
|
+
api: 'board',
|
|
545
|
+
resource: '/registrations',
|
|
546
|
+
body: data,
|
|
547
|
+
})
|
|
506
548
|
.then((res) => res.body);
|
|
507
549
|
},
|
|
508
550
|
|
|
@@ -513,28 +555,32 @@ const Board = WebexPlugin.extend({
|
|
|
513
555
|
* @returns {Promise<Board~Registration>}
|
|
514
556
|
*/
|
|
515
557
|
registerToShareMercury(channel) {
|
|
516
|
-
return this.webex.internal.feature
|
|
558
|
+
return this.webex.internal.feature
|
|
559
|
+
.getFeature('developer', 'web-shared-mercury')
|
|
517
560
|
.then((isSharingMercuryFeatureEnabled) => {
|
|
518
561
|
if (!this.webex.internal.mercury.localClusterServiceUrls) {
|
|
519
|
-
return Promise.reject(
|
|
562
|
+
return Promise.reject(
|
|
563
|
+
new Error('`localClusterServiceUrls` is not defined, make sure mercury is connected')
|
|
564
|
+
);
|
|
520
565
|
}
|
|
521
566
|
if (!isSharingMercuryFeatureEnabled) {
|
|
522
567
|
return Promise.reject(new Error('`web-shared-mercury` is not enabled'));
|
|
523
568
|
}
|
|
524
569
|
|
|
525
570
|
const {webSocketUrl} = this.webex.internal.device;
|
|
526
|
-
const {mercuryConnectionServiceClusterUrl} =
|
|
571
|
+
const {mercuryConnectionServiceClusterUrl} =
|
|
572
|
+
this.webex.internal.mercury.localClusterServiceUrls;
|
|
527
573
|
|
|
528
574
|
const data = {
|
|
529
575
|
mercuryConnectionServiceClusterUrl,
|
|
530
576
|
webSocketUrl,
|
|
531
|
-
action: 'ADD'
|
|
577
|
+
action: 'ADD',
|
|
532
578
|
};
|
|
533
579
|
|
|
534
580
|
return this.webex.request({
|
|
535
581
|
method: 'POST',
|
|
536
582
|
uri: `${channel.channelUrl}/register`,
|
|
537
|
-
body: data
|
|
583
|
+
body: data,
|
|
538
584
|
});
|
|
539
585
|
})
|
|
540
586
|
.then((res) => res.body);
|
|
@@ -552,24 +598,28 @@ const Board = WebexPlugin.extend({
|
|
|
552
598
|
const data = {
|
|
553
599
|
binding,
|
|
554
600
|
webSocketUrl,
|
|
555
|
-
action: 'REMOVE'
|
|
601
|
+
action: 'REMOVE',
|
|
556
602
|
};
|
|
557
603
|
|
|
558
|
-
return this.webex
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
604
|
+
return this.webex
|
|
605
|
+
.request({
|
|
606
|
+
method: 'POST',
|
|
607
|
+
uri: `${channel.channelUrl}/register`,
|
|
608
|
+
body: data,
|
|
609
|
+
})
|
|
563
610
|
.then((res) => res.body);
|
|
564
611
|
},
|
|
565
612
|
|
|
566
613
|
_addContentChunk(channel, contentChunk) {
|
|
567
|
-
return this.webex.internal.board
|
|
568
|
-
.
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
614
|
+
return this.webex.internal.board
|
|
615
|
+
.encryptContents(channel.defaultEncryptionKeyUrl, contentChunk)
|
|
616
|
+
.then((res) =>
|
|
617
|
+
this.webex.request({
|
|
618
|
+
method: 'POST',
|
|
619
|
+
uri: `${channel.channelUrl}/contents`,
|
|
620
|
+
body: res,
|
|
621
|
+
})
|
|
622
|
+
)
|
|
573
623
|
.then((res) => res.body);
|
|
574
624
|
},
|
|
575
625
|
|
|
@@ -586,8 +636,11 @@ const Board = WebexPlugin.extend({
|
|
|
586
636
|
_uploadImage(channel, file, options) {
|
|
587
637
|
options = options || {};
|
|
588
638
|
|
|
589
|
-
return this.webex.internal.encryption
|
|
590
|
-
.
|
|
639
|
+
return this.webex.internal.encryption
|
|
640
|
+
.encryptBinary(file)
|
|
641
|
+
.then(({scr, cdata}) =>
|
|
642
|
+
Promise.all([scr, this._uploadImageToWebexFiles(channel, cdata, options.hiddenSpace)])
|
|
643
|
+
)
|
|
591
644
|
.then(([scr, res]) => assign(scr, {loc: res.downloadUrl}));
|
|
592
645
|
},
|
|
593
646
|
|
|
@@ -598,38 +651,40 @@ const Board = WebexPlugin.extend({
|
|
|
598
651
|
requestUri = `${channel.channelUrl}/spaces/hidden`;
|
|
599
652
|
}
|
|
600
653
|
|
|
601
|
-
return this.webex
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
654
|
+
return this.webex
|
|
655
|
+
.request({
|
|
656
|
+
method: 'PUT',
|
|
657
|
+
uri: requestUri,
|
|
658
|
+
})
|
|
605
659
|
.then((res) => res.body.spaceUrl);
|
|
606
660
|
},
|
|
607
661
|
|
|
608
662
|
_uploadImageToWebexFiles(channel, file, hiddenSpace) {
|
|
609
663
|
const fileSize = file.length || file.size || file.byteLength;
|
|
610
664
|
|
|
611
|
-
return this._getSpaceUrl(channel, hiddenSpace)
|
|
612
|
-
|
|
665
|
+
return this._getSpaceUrl(channel, hiddenSpace).then((spaceUrl) =>
|
|
666
|
+
this.webex.upload({
|
|
613
667
|
uri: `${spaceUrl}/upload_sessions`,
|
|
614
668
|
file,
|
|
615
669
|
qs: {
|
|
616
|
-
transcode: true
|
|
670
|
+
transcode: true,
|
|
617
671
|
},
|
|
618
672
|
phases: {
|
|
619
673
|
initialize: {fileSize},
|
|
620
674
|
upload: {
|
|
621
675
|
$url(session) {
|
|
622
676
|
return session.uploadUrl;
|
|
623
|
-
}
|
|
677
|
+
},
|
|
624
678
|
},
|
|
625
679
|
finalize: {
|
|
626
680
|
$uri(session) {
|
|
627
681
|
return session.finishUploadUrl;
|
|
628
682
|
},
|
|
629
|
-
body: {fileSize}
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
})
|
|
683
|
+
body: {fileSize},
|
|
684
|
+
},
|
|
685
|
+
},
|
|
686
|
+
})
|
|
687
|
+
);
|
|
633
688
|
},
|
|
634
689
|
|
|
635
690
|
/** Authorize transcoder (for sharing whiteboard to mobile)
|
|
@@ -640,22 +695,26 @@ const Board = WebexPlugin.extend({
|
|
|
640
695
|
*/
|
|
641
696
|
authorizeMediaInjector(board) {
|
|
642
697
|
if (!board) {
|
|
643
|
-
Promise.reject(
|
|
698
|
+
Promise.reject(
|
|
699
|
+
new Error('#authorizeMediaInjector --> cannot authorize transcoder without board')
|
|
700
|
+
);
|
|
644
701
|
}
|
|
645
702
|
|
|
646
|
-
return this.webex.internal.encryption.kms
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
703
|
+
return this.webex.internal.encryption.kms
|
|
704
|
+
.prepareRequest({
|
|
705
|
+
method: 'create',
|
|
706
|
+
uri: '/authorizations',
|
|
707
|
+
resourceUri: board.kmsResourceUrl,
|
|
708
|
+
anonymous: 1,
|
|
709
|
+
})
|
|
710
|
+
.then((request) =>
|
|
711
|
+
this.webex.request({
|
|
712
|
+
uri: `${board.channelUrl}/sharePolicies/transcoder`,
|
|
713
|
+
method: 'PUT',
|
|
714
|
+
body: {kmsMessage: request.wrapped},
|
|
715
|
+
})
|
|
716
|
+
)
|
|
717
|
+
.then((res) => this.webex.internal.encryption.kms.decryptKmsMessage(res.body.kmsResponse))
|
|
659
718
|
.then((decryptedKmsMessage) => {
|
|
660
719
|
if (decryptedKmsMessage?.authorizations.length > 0) {
|
|
661
720
|
return decryptedKmsMessage.authorizations[0].bearer;
|
|
@@ -664,10 +723,11 @@ const Board = WebexPlugin.extend({
|
|
|
664
723
|
return undefined;
|
|
665
724
|
})
|
|
666
725
|
.catch((err) =>
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
Promise.resolve(err)
|
|
726
|
+
/* We want to resolve any errors so that whiteboard share will still work
|
|
727
|
+
* except mobile being able to receive the share
|
|
728
|
+
*/
|
|
729
|
+
Promise.resolve(err)
|
|
730
|
+
);
|
|
671
731
|
},
|
|
672
732
|
|
|
673
733
|
/** Unauthorize transcoder (for stopping whiteboard share to mobile)
|
|
@@ -678,37 +738,43 @@ const Board = WebexPlugin.extend({
|
|
|
678
738
|
*/
|
|
679
739
|
unauthorizeMediaInjector(board) {
|
|
680
740
|
if (!board) {
|
|
681
|
-
Promise.reject(
|
|
741
|
+
Promise.reject(
|
|
742
|
+
new Error('#unauthorizeMediaInjector --> cannot unauthorize transcoder without board')
|
|
743
|
+
);
|
|
682
744
|
}
|
|
683
745
|
|
|
684
|
-
return this.webex.internal.encryption.kms
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
746
|
+
return this.webex.internal.encryption.kms
|
|
747
|
+
.listAuthorizations({
|
|
748
|
+
kroUri: board.kmsResourceUrl,
|
|
749
|
+
})
|
|
750
|
+
.then((authorizations) => {
|
|
751
|
+
/* Attempt to remove the authorization made from starting whiteboard share
|
|
752
|
+
* Also removing any previous authorizations that were not cleared
|
|
753
|
+
*/
|
|
754
|
+
const promises = authorizations.map((auth) => {
|
|
755
|
+
const {authId} = auth;
|
|
756
|
+
|
|
757
|
+
return this.webex.internal.encryption.kms
|
|
758
|
+
.removeAuthorization({
|
|
759
|
+
authId,
|
|
760
|
+
kroUri: board.kmsResourceUrl,
|
|
761
|
+
})
|
|
762
|
+
.then(() => Promise.resolve(authId))
|
|
763
|
+
.catch((err) =>
|
|
764
|
+
/* We don't want this to error out, otherwise the
|
|
765
|
+
* Promise.all will not process the rest of the request
|
|
766
|
+
*/
|
|
767
|
+
Promise.resolve(err)
|
|
768
|
+
);
|
|
769
|
+
});
|
|
704
770
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
771
|
+
if (promises.length > 0) {
|
|
772
|
+
return Promise.all(promises).then((responses) => responses);
|
|
773
|
+
}
|
|
708
774
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
}
|
|
775
|
+
return Promise.resolve([]);
|
|
776
|
+
});
|
|
777
|
+
},
|
|
712
778
|
});
|
|
713
779
|
|
|
714
780
|
export default Board;
|