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