@webex/internal-plugin-calendar 3.0.0-beta.3 → 3.0.0-beta.300
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/calendar.decrypt.helper.js +73 -0
- package/dist/calendar.decrypt.helper.js.map +1 -0
- package/dist/calendar.encrypt.helper.js +88 -0
- package/dist/calendar.encrypt.helper.js.map +1 -0
- package/dist/calendar.js +216 -116
- package/dist/calendar.js.map +1 -1
- package/dist/collection.js +0 -19
- package/dist/collection.js.map +1 -1
- package/dist/config.js +0 -3
- package/dist/config.js.map +1 -1
- package/dist/constants.js +0 -2
- package/dist/constants.js.map +1 -1
- package/dist/index.js +10 -24
- package/dist/index.js.map +1 -1
- package/dist/util.js +0 -13
- package/dist/util.js.map +1 -1
- package/package.json +9 -11
- package/src/calendar.decrypt.helper.js +121 -0
- package/src/calendar.encrypt.helper.js +98 -0
- package/src/calendar.js +242 -53
- package/src/collection.js +2 -4
- package/src/config.js +2 -2
- package/src/index.js +124 -43
- package/src/util.js +5 -3
- package/test/integration/spec/calendar.js +379 -271
- package/test/unit/spec/calendar.decrypt.helper.js +145 -0
- package/test/unit/spec/calendar.encrypt.helper.js +52 -0
- package/test/unit/spec/calendar.js +249 -94
- package/test/unit/spec/utils.js +4 -1
package/src/calendar.js
CHANGED
|
@@ -3,28 +3,28 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
* Calendar Item Create Event
|
|
7
|
+
* Emitted when a calendar item has been added
|
|
8
|
+
* @event calendar:meeting:create
|
|
9
|
+
* @instance
|
|
10
|
+
* @memberof Calendar
|
|
11
|
+
*/
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
* Calendar Item Update Event
|
|
15
|
+
* Emitted when a calendar item has been updated
|
|
16
|
+
* @event calendar:meeting:update
|
|
17
|
+
* @instance
|
|
18
|
+
* @memberof Calendar
|
|
19
|
+
*/
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
* Calendar Item Update Event
|
|
23
|
+
* Emitted when a calendar item has been deleted
|
|
24
|
+
* @event calendar:meeting:delete
|
|
25
|
+
* @instance
|
|
26
|
+
* @memberof Calendar
|
|
27
|
+
*/
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* Calendar Registered Event
|
|
@@ -41,12 +41,21 @@
|
|
|
41
41
|
* @instance
|
|
42
42
|
* @memberof Calendar
|
|
43
43
|
*/
|
|
44
|
-
|
|
45
|
-
import
|
|
44
|
+
import {isArray} from 'lodash';
|
|
45
|
+
import {base64} from '@webex/common';
|
|
46
46
|
import {WebexPlugin} from '@webex/webex-core';
|
|
47
47
|
|
|
48
48
|
import CalendarCollection from './collection';
|
|
49
|
-
import {
|
|
49
|
+
import {
|
|
50
|
+
CALENDAR_REGISTERED,
|
|
51
|
+
CALENDAR_UNREGISTERED,
|
|
52
|
+
CALENDAR_DELETE,
|
|
53
|
+
CALENDAR_CREATE,
|
|
54
|
+
CALENDAR_UPDATED,
|
|
55
|
+
} from './constants';
|
|
56
|
+
|
|
57
|
+
import EncryptHelper from './calendar.encrypt.helper';
|
|
58
|
+
import DecryptHelper from './calendar.decrypt.helper';
|
|
50
59
|
|
|
51
60
|
const Calendar = WebexPlugin.extend({
|
|
52
61
|
namespace: 'Calendar',
|
|
@@ -59,6 +68,43 @@ const Calendar = WebexPlugin.extend({
|
|
|
59
68
|
*/
|
|
60
69
|
registered: false,
|
|
61
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Cache all rpc event request locally
|
|
73
|
+
* */
|
|
74
|
+
rpcEventRequests: [],
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Cache KMS encryptionKeyUrl
|
|
78
|
+
* */
|
|
79
|
+
encryptionKeyUrl: null,
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* WebexPlugin initialize method. This triggers once Webex has completed its
|
|
83
|
+
* initialization workflow.
|
|
84
|
+
*
|
|
85
|
+
* If the plugin is meant to perform startup actions, place them in this
|
|
86
|
+
* `initialize()` method instead of the `constructor()` method.
|
|
87
|
+
* @returns {void}
|
|
88
|
+
*/
|
|
89
|
+
initialize() {
|
|
90
|
+
// Used to perform actions after webex is fully qualified and ready for
|
|
91
|
+
// operation.
|
|
92
|
+
this.listenToOnce(this.webex, 'ready', () => {
|
|
93
|
+
// Pre-fetch a KMS encryption key url to improve performance
|
|
94
|
+
this.webex.internal.encryption.kms.createUnboundKeys({count: 1}).then((keys) => {
|
|
95
|
+
const key = isArray(keys) ? keys[0] : keys;
|
|
96
|
+
this.encryptionKeyUrl = key ? key.uri : null;
|
|
97
|
+
this.logger.info('calendar->bind a KMS encryption key url');
|
|
98
|
+
this.webex.internal.encryption
|
|
99
|
+
.getKey(this.encryptionKeyUrl, {onBehalfOf: null})
|
|
100
|
+
.then((retrievedKey) => {
|
|
101
|
+
this.encryptionKeyUrl = retrievedKey ? retrievedKey.uri : null;
|
|
102
|
+
this.logger.info('calendar->retrieve the KMS encryption key url and cache it');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
},
|
|
107
|
+
|
|
62
108
|
/**
|
|
63
109
|
* Explicitly sets up the calendar plugin by registering
|
|
64
110
|
* the device, connecting to mercury, and listening for calendar events.
|
|
@@ -79,7 +125,8 @@ const Calendar = WebexPlugin.extend({
|
|
|
79
125
|
return Promise.resolve();
|
|
80
126
|
}
|
|
81
127
|
|
|
82
|
-
return this.webex.internal.device
|
|
128
|
+
return this.webex.internal.device
|
|
129
|
+
.register()
|
|
83
130
|
.then(() => this.webex.internal.mercury.connect())
|
|
84
131
|
.then(() => {
|
|
85
132
|
this.listenForEvents();
|
|
@@ -110,7 +157,8 @@ const Calendar = WebexPlugin.extend({
|
|
|
110
157
|
|
|
111
158
|
this.stopListeningForEvents();
|
|
112
159
|
|
|
113
|
-
return this.webex.internal.mercury
|
|
160
|
+
return this.webex.internal.mercury
|
|
161
|
+
.disconnect()
|
|
114
162
|
.then(() => this.webex.internal.device.unregister())
|
|
115
163
|
.then(() => {
|
|
116
164
|
this.trigger(CALENDAR_UNREGISTERED);
|
|
@@ -140,6 +188,9 @@ const Calendar = WebexPlugin.extend({
|
|
|
140
188
|
this.webex.internal.mercury.on('event:calendar.meeting.delete', (envelope) => {
|
|
141
189
|
this._handleDelete(envelope.data);
|
|
142
190
|
});
|
|
191
|
+
this.webex.internal.mercury.on('event:calendar.free_busy', (envelope) => {
|
|
192
|
+
this._handleFreeBusy(envelope.data);
|
|
193
|
+
});
|
|
143
194
|
},
|
|
144
195
|
|
|
145
196
|
/**
|
|
@@ -153,6 +204,7 @@ const Calendar = WebexPlugin.extend({
|
|
|
153
204
|
this.webex.internal.mercury.off('event:calendar.meeting.update');
|
|
154
205
|
this.webex.internal.mercury.off('event:calendar.meeting.update.minimal');
|
|
155
206
|
this.webex.internal.mercury.off('event:calendar.meeting.delete');
|
|
207
|
+
this.webex.internal.mercury.off('event:calendar.free_busy');
|
|
156
208
|
},
|
|
157
209
|
|
|
158
210
|
/**
|
|
@@ -191,6 +243,32 @@ const Calendar = WebexPlugin.extend({
|
|
|
191
243
|
this.trigger(CALENDAR_DELETE, item);
|
|
192
244
|
},
|
|
193
245
|
|
|
246
|
+
/**
|
|
247
|
+
* handles free_busy events
|
|
248
|
+
* @param {Object} data
|
|
249
|
+
* @returns {undefined}
|
|
250
|
+
* @private
|
|
251
|
+
*/
|
|
252
|
+
_handleFreeBusy(data) {
|
|
253
|
+
DecryptHelper.decryptFreeBusyResponse(this, data).then(() => {
|
|
254
|
+
let response = {};
|
|
255
|
+
if (data && data.calendarFreeBusyScheduleResponse) {
|
|
256
|
+
response = data.calendarFreeBusyScheduleResponse;
|
|
257
|
+
}
|
|
258
|
+
if (response && response.requestId && response.requestId in this.rpcEventRequests) {
|
|
259
|
+
this.logger.log(
|
|
260
|
+
`webex.internal.calendar - receive requests, requestId: ${response.requestId}`
|
|
261
|
+
);
|
|
262
|
+
delete response.encryptionKeyUrl;
|
|
263
|
+
const {resolve} = this.rpcEventRequests[response.requestId];
|
|
264
|
+
resolve(response);
|
|
265
|
+
delete this.rpcEventRequests[response.requestId];
|
|
266
|
+
} else {
|
|
267
|
+
this.logger.log('webex.internal.calendar - receive other requests.');
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
},
|
|
271
|
+
|
|
194
272
|
/**
|
|
195
273
|
* Retrieves a collection of calendars based on the request parameters
|
|
196
274
|
* Defaults to 1 day before and 7 days ahead
|
|
@@ -233,20 +311,30 @@ const Calendar = WebexPlugin.extend({
|
|
|
233
311
|
* @returns {Promise} Resolves with a decrypted calendar event
|
|
234
312
|
*/
|
|
235
313
|
processMeetingEvent(event) {
|
|
236
|
-
return this.webex.transform('inbound', event)
|
|
237
|
-
.then(() => event);
|
|
314
|
+
return this.webex.transform('inbound', event).then(() => event);
|
|
238
315
|
},
|
|
239
316
|
|
|
240
317
|
/**
|
|
241
|
-
* Retrieves an array of meeting participants for the meeting
|
|
242
|
-
* @param {String}
|
|
318
|
+
* Retrieves an array of meeting participants for the meeting participantsUrl
|
|
319
|
+
* @param {String} participantsUrl
|
|
243
320
|
* @returns {Promise} Resolves with an object of meeting participants
|
|
244
321
|
*/
|
|
245
|
-
getParticipants(
|
|
322
|
+
getParticipants(participantsUrl) {
|
|
246
323
|
return this.request({
|
|
247
324
|
method: 'GET',
|
|
248
|
-
|
|
249
|
-
|
|
325
|
+
uri: participantsUrl,
|
|
326
|
+
});
|
|
327
|
+
},
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* get meeting notes using notesUrl from meeting object.
|
|
331
|
+
* @param {String} notesUrl
|
|
332
|
+
* @returns {Promise} Resolves with an object of meeting notes
|
|
333
|
+
*/
|
|
334
|
+
getNotesByUrl(notesUrl) {
|
|
335
|
+
return this.request({
|
|
336
|
+
method: 'GET',
|
|
337
|
+
uri: notesUrl,
|
|
250
338
|
});
|
|
251
339
|
},
|
|
252
340
|
|
|
@@ -259,7 +347,7 @@ const Calendar = WebexPlugin.extend({
|
|
|
259
347
|
return this.request({
|
|
260
348
|
method: 'GET',
|
|
261
349
|
service: 'calendar',
|
|
262
|
-
resource: `calendarEvents/${
|
|
350
|
+
resource: `calendarEvents/${base64.encode(id)}/notes`,
|
|
263
351
|
});
|
|
264
352
|
},
|
|
265
353
|
|
|
@@ -273,40 +361,141 @@ const Calendar = WebexPlugin.extend({
|
|
|
273
361
|
list(options) {
|
|
274
362
|
options = options || {};
|
|
275
363
|
|
|
276
|
-
return this.webex
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
364
|
+
return this.webex
|
|
365
|
+
.request({
|
|
366
|
+
method: 'GET',
|
|
367
|
+
service: 'calendar',
|
|
368
|
+
resource: 'calendarEvents',
|
|
369
|
+
qs: options,
|
|
370
|
+
})
|
|
282
371
|
.then((res) => {
|
|
283
372
|
const meetingObjects = res.body.items;
|
|
284
373
|
const promises = [];
|
|
285
374
|
|
|
286
375
|
meetingObjects.forEach((meeting) => {
|
|
287
|
-
if (!meeting.encryptedNotes) {
|
|
288
|
-
promises.push(
|
|
289
|
-
this.getNotes(meeting.id)
|
|
290
|
-
.then((notesResponse) => {
|
|
291
|
-
meeting.encryptedNotes = notesResponse.body && notesResponse.body.encryptedNotes;
|
|
292
|
-
})
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
376
|
if (!meeting.encryptedParticipants) {
|
|
297
377
|
promises.push(
|
|
298
|
-
this.getParticipants(meeting.
|
|
299
|
-
.
|
|
300
|
-
|
|
301
|
-
})
|
|
378
|
+
this.getParticipants(meeting.participantsUrl).then((notesResponse) => {
|
|
379
|
+
meeting.encryptedParticipants = notesResponse.body.encryptedParticipants;
|
|
380
|
+
})
|
|
302
381
|
);
|
|
303
382
|
}
|
|
304
383
|
});
|
|
305
384
|
|
|
306
|
-
return Promise.all(promises)
|
|
307
|
-
|
|
385
|
+
return Promise.all(promises).then(() => meetingObjects);
|
|
386
|
+
});
|
|
387
|
+
},
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Create calendar event
|
|
391
|
+
* @param {object} [data] meeting payload data
|
|
392
|
+
* @param {object} [query] the query parameters for specific usage
|
|
393
|
+
* @returns {Promise} Resolves with creating calendar event response
|
|
394
|
+
* */
|
|
395
|
+
createCalendarEvent(data, query) {
|
|
396
|
+
return EncryptHelper.encryptCalendarEventRequest(this, data).then(() =>
|
|
397
|
+
this.request({
|
|
398
|
+
method: 'POST',
|
|
399
|
+
service: 'calendar',
|
|
400
|
+
body: data,
|
|
401
|
+
resource: 'calendarEvents/sync',
|
|
402
|
+
qs: query || {},
|
|
403
|
+
})
|
|
404
|
+
);
|
|
405
|
+
},
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Update calendar event
|
|
409
|
+
* @param {string} [id] calendar event id
|
|
410
|
+
* @param {object} [data] meeting payload data
|
|
411
|
+
* @param {object} [query] the query parameters for specific usage
|
|
412
|
+
* @returns {Promise} Resolves with updating calendar event response
|
|
413
|
+
* */
|
|
414
|
+
updateCalendarEvent(id, data, query) {
|
|
415
|
+
return EncryptHelper.encryptCalendarEventRequest(this, data).then(() =>
|
|
416
|
+
this.request({
|
|
417
|
+
method: 'PATCH',
|
|
418
|
+
service: 'calendar',
|
|
419
|
+
body: data,
|
|
420
|
+
resource: `calendarEvents/${base64.encode(id)}/sync`,
|
|
421
|
+
qs: query || {},
|
|
422
|
+
})
|
|
423
|
+
);
|
|
424
|
+
},
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Delete calendar event
|
|
428
|
+
* @param {string} [id] calendar event id
|
|
429
|
+
* @param {object} [query] the query parameters for specific usage
|
|
430
|
+
* @returns {Promise} Resolves with deleting calendar event response
|
|
431
|
+
* */
|
|
432
|
+
deleteCalendarEvent(id, query) {
|
|
433
|
+
return this.request({
|
|
434
|
+
method: 'DELETE',
|
|
435
|
+
service: 'calendar',
|
|
436
|
+
resource: `calendarEvents/${base64.encode(id)}/sync`,
|
|
437
|
+
qs: query || {},
|
|
438
|
+
});
|
|
439
|
+
},
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* @typedef QuerySchedulerDataOptions
|
|
443
|
+
* @param {string} [siteName] it is site full url, must have. Example: ccctest.dmz.webex.com
|
|
444
|
+
* @param {string} [id] it is seriesOrOccurrenceId. If present, the series/occurrence meeting ID to fetch data for.
|
|
445
|
+
* Example: 040000008200E00074C5B7101A82E008000000004A99F11A0841D9010000000000000000100000009EE499D4A71C1A46B51494C70EC7BFE5
|
|
446
|
+
* @param {string} [clientMeetingId] If present, the client meeting UUID to fetch data for.
|
|
447
|
+
* Example: 7f318aa9-887c-6e94-802a-8dc8e6eb1a0a
|
|
448
|
+
* @param {string} [scheduleTemplateId] it template id.
|
|
449
|
+
* @param {string} [sessionTypeId] it session type id.
|
|
450
|
+
* @param {string} [organizerCIUserId] required in schedule-on-behalf case. It is the organizer's CI UUID.
|
|
451
|
+
* @param {boolean} [usmPreference]
|
|
452
|
+
* @param {string} [webexMeetingId] webex side meeting UUID
|
|
453
|
+
* @param {string} [eventId] event ID.
|
|
454
|
+
* @param {string} [icalUid] icalendar UUID.
|
|
455
|
+
* @param {string} [thirdPartyType] third part type, such as: Microsoft
|
|
456
|
+
*/
|
|
457
|
+
/**
|
|
458
|
+
* Get scheduler data from calendar service
|
|
459
|
+
* @param {QuerySchedulerDataOptions} [query] the command parameters for fetching scheduler data.
|
|
460
|
+
* @returns {Promise} Resolves with a decrypted scheduler data
|
|
461
|
+
* */
|
|
462
|
+
getSchedulerData(query) {
|
|
463
|
+
return this.request({
|
|
464
|
+
method: 'GET',
|
|
465
|
+
service: 'calendar',
|
|
466
|
+
resource: 'schedulerData',
|
|
467
|
+
qs: query || {},
|
|
468
|
+
}).then((response) => {
|
|
469
|
+
return DecryptHelper.decryptSchedulerDataResponse(this, response.body).then(() => response);
|
|
470
|
+
});
|
|
471
|
+
},
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Get free busy status from calendar service
|
|
475
|
+
* @param {Object} [data] the command parameters for fetching free busy status.
|
|
476
|
+
* @param {object} [query] the query parameters for specific usage
|
|
477
|
+
* @returns {Promise} Resolves with a decrypted response
|
|
478
|
+
* */
|
|
479
|
+
getFreeBusy(data, query) {
|
|
480
|
+
return EncryptHelper.encryptFreeBusyRequest(this, data)
|
|
481
|
+
.then(() => {
|
|
482
|
+
return this.request({
|
|
483
|
+
method: 'POST',
|
|
484
|
+
service: 'calendar',
|
|
485
|
+
body: data,
|
|
486
|
+
resource: 'freebusy',
|
|
487
|
+
qs: query || {},
|
|
488
|
+
});
|
|
489
|
+
})
|
|
490
|
+
.then(() => {
|
|
491
|
+
return new Promise((resolve, reject) => {
|
|
492
|
+
this.rpcEventRequests[data.requestId] = {resolve, reject};
|
|
493
|
+
});
|
|
494
|
+
})
|
|
495
|
+
.catch((error) => {
|
|
496
|
+
throw error;
|
|
308
497
|
});
|
|
309
|
-
}
|
|
498
|
+
},
|
|
310
499
|
});
|
|
311
500
|
|
|
312
501
|
export default Calendar;
|
package/src/collection.js
CHANGED
|
@@ -27,7 +27,7 @@ const CalendarCollection = {
|
|
|
27
27
|
*/
|
|
28
28
|
getBy(key, value) {
|
|
29
29
|
if (key && value) {
|
|
30
|
-
return find(this.items, (item) =>
|
|
30
|
+
return find(this.items, (item) => item[key] === value);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
return null;
|
|
@@ -58,7 +58,6 @@ const CalendarCollection = {
|
|
|
58
58
|
this.items = {};
|
|
59
59
|
},
|
|
60
60
|
|
|
61
|
-
|
|
62
61
|
/**
|
|
63
62
|
* @param {Id} id is the id for the calendar item to be removed
|
|
64
63
|
* @returns {Any} calendar item which got removed
|
|
@@ -95,8 +94,7 @@ const CalendarCollection = {
|
|
|
95
94
|
*/
|
|
96
95
|
getAll() {
|
|
97
96
|
return Object.values(this.items);
|
|
98
|
-
}
|
|
99
|
-
|
|
97
|
+
},
|
|
100
98
|
};
|
|
101
99
|
|
|
102
100
|
export default CalendarCollection;
|
package/src/config.js
CHANGED
package/src/index.js
CHANGED
|
@@ -20,21 +20,37 @@ registerInternalPlugin('calendar', Calendar, {
|
|
|
20
20
|
name: 'transformMeetingNotes',
|
|
21
21
|
direction: 'inbound',
|
|
22
22
|
test(ctx, response) {
|
|
23
|
-
return Promise.resolve(
|
|
23
|
+
return Promise.resolve(
|
|
24
|
+
has(response, 'body.encryptedNotes') &&
|
|
25
|
+
!(
|
|
26
|
+
response.options &&
|
|
27
|
+
response.options.service === 'calendar' &&
|
|
28
|
+
response.options.method === 'GET' &&
|
|
29
|
+
response.options.resource === 'schedulerData'
|
|
30
|
+
)
|
|
31
|
+
);
|
|
24
32
|
},
|
|
25
33
|
extract(response) {
|
|
26
34
|
return Promise.resolve(response.body);
|
|
27
|
-
}
|
|
35
|
+
},
|
|
28
36
|
},
|
|
29
37
|
{
|
|
30
38
|
name: 'transformMeetingParticipants',
|
|
31
39
|
direction: 'inbound',
|
|
32
40
|
test(ctx, response) {
|
|
33
|
-
return Promise.resolve(
|
|
41
|
+
return Promise.resolve(
|
|
42
|
+
has(response, 'body.encryptedParticipants') &&
|
|
43
|
+
!(
|
|
44
|
+
response.options &&
|
|
45
|
+
response.options.service === 'calendar' &&
|
|
46
|
+
response.options.method === 'GET' &&
|
|
47
|
+
response.options.resource === 'schedulerData'
|
|
48
|
+
)
|
|
49
|
+
);
|
|
34
50
|
},
|
|
35
51
|
extract(response) {
|
|
36
52
|
return Promise.resolve(response.body);
|
|
37
|
-
}
|
|
53
|
+
},
|
|
38
54
|
},
|
|
39
55
|
{
|
|
40
56
|
name: 'transformMeetingArray',
|
|
@@ -44,17 +60,25 @@ registerInternalPlugin('calendar', Calendar, {
|
|
|
44
60
|
},
|
|
45
61
|
extract(response) {
|
|
46
62
|
return Promise.resolve(response.body.items);
|
|
47
|
-
}
|
|
63
|
+
},
|
|
48
64
|
},
|
|
49
65
|
{
|
|
50
66
|
name: 'transformMeeting',
|
|
51
67
|
direction: 'inbound',
|
|
52
68
|
test(ctx, response) {
|
|
53
|
-
return Promise.resolve(
|
|
69
|
+
return Promise.resolve(
|
|
70
|
+
has(response, 'body.seriesId') &&
|
|
71
|
+
!(
|
|
72
|
+
response.options &&
|
|
73
|
+
response.options.service === 'calendar' &&
|
|
74
|
+
response.options.method === 'GET' &&
|
|
75
|
+
response.options.resource === 'schedulerData'
|
|
76
|
+
)
|
|
77
|
+
);
|
|
54
78
|
},
|
|
55
79
|
extract(response) {
|
|
56
80
|
return Promise.resolve(response.body);
|
|
57
|
-
}
|
|
81
|
+
},
|
|
58
82
|
},
|
|
59
83
|
{
|
|
60
84
|
name: 'transformMeeting',
|
|
@@ -64,15 +88,15 @@ registerInternalPlugin('calendar', Calendar, {
|
|
|
64
88
|
},
|
|
65
89
|
extract(response) {
|
|
66
90
|
return Promise.resolve(response.calendarMeetingExternal);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
91
|
+
},
|
|
92
|
+
},
|
|
69
93
|
],
|
|
70
94
|
transforms: [
|
|
71
95
|
{
|
|
72
96
|
name: 'transformMeetingArray',
|
|
73
97
|
fn(ctx, array) {
|
|
74
98
|
return Promise.all(array.map((item) => ctx.transform('transformMeeting', item)));
|
|
75
|
-
}
|
|
99
|
+
},
|
|
76
100
|
},
|
|
77
101
|
{
|
|
78
102
|
name: 'transformMeeting',
|
|
@@ -87,33 +111,78 @@ registerInternalPlugin('calendar', Calendar, {
|
|
|
87
111
|
}
|
|
88
112
|
|
|
89
113
|
// Decrypt participant properties if meeting object contains participants
|
|
90
|
-
const decryptedParticipants = object.encryptedParticipants
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
114
|
+
const decryptedParticipants = object.encryptedParticipants
|
|
115
|
+
? object.encryptedParticipants.map((participant) =>
|
|
116
|
+
Promise.all([
|
|
117
|
+
ctx.transform(
|
|
118
|
+
'decryptTextProp',
|
|
119
|
+
'encryptedEmailAddress',
|
|
120
|
+
object.encryptionKeyUrl,
|
|
121
|
+
participant
|
|
122
|
+
),
|
|
123
|
+
ctx.transform(
|
|
124
|
+
'decryptTextProp',
|
|
125
|
+
'encryptedName',
|
|
126
|
+
object.encryptionKeyUrl,
|
|
127
|
+
participant
|
|
128
|
+
),
|
|
129
|
+
])
|
|
130
|
+
)
|
|
131
|
+
: [];
|
|
94
132
|
|
|
95
133
|
// Decrypt meetingJoinInfo properties if meeting object contains meetingJoinInfo
|
|
96
|
-
const decryptedMeetingJoinInfo = object.meetingJoinInfo
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
134
|
+
const decryptedMeetingJoinInfo = object.meetingJoinInfo
|
|
135
|
+
? Promise.all([
|
|
136
|
+
ctx.transform(
|
|
137
|
+
'decryptTextProp',
|
|
138
|
+
'meetingJoinURI',
|
|
139
|
+
object.encryptionKeyUrl,
|
|
140
|
+
object.meetingJoinInfo
|
|
141
|
+
),
|
|
142
|
+
ctx.transform(
|
|
143
|
+
'decryptTextProp',
|
|
144
|
+
'meetingJoinURL',
|
|
145
|
+
object.encryptionKeyUrl,
|
|
146
|
+
object.meetingJoinInfo
|
|
147
|
+
),
|
|
148
|
+
])
|
|
149
|
+
: [];
|
|
100
150
|
|
|
101
|
-
const decryptedOrganizer = object.encryptedOrganizer
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
151
|
+
const decryptedOrganizer = object.encryptedOrganizer
|
|
152
|
+
? Promise.all([
|
|
153
|
+
ctx.transform(
|
|
154
|
+
'decryptTextProp',
|
|
155
|
+
'encryptedEmailAddress',
|
|
156
|
+
object.encryptionKeyUrl,
|
|
157
|
+
object.encryptedOrganizer
|
|
158
|
+
),
|
|
159
|
+
ctx.transform(
|
|
160
|
+
'decryptTextProp',
|
|
161
|
+
'encryptedName',
|
|
162
|
+
object.encryptionKeyUrl,
|
|
163
|
+
object.encryptedOrganizer
|
|
164
|
+
),
|
|
165
|
+
])
|
|
166
|
+
: [];
|
|
105
167
|
|
|
106
|
-
return Promise.all(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
168
|
+
return Promise.all(
|
|
169
|
+
[
|
|
170
|
+
ctx.transform('decryptTextProp', 'encryptedSubject', object.encryptionKeyUrl, object),
|
|
171
|
+
ctx.transform(
|
|
172
|
+
'decryptTextProp',
|
|
173
|
+
'encryptedLocation',
|
|
174
|
+
object.encryptionKeyUrl,
|
|
175
|
+
object
|
|
176
|
+
),
|
|
177
|
+
ctx.transform('decryptTextProp', 'encryptedNotes', object.encryptionKeyUrl, object),
|
|
178
|
+
ctx.transform('decryptTextProp', 'webexURI', object.encryptionKeyUrl, object),
|
|
179
|
+
ctx.transform('decryptTextProp', 'webexURL', object.encryptionKeyUrl, object),
|
|
180
|
+
ctx.transform('decryptTextProp', 'spaceMeetURL', object.encryptionKeyUrl, object),
|
|
181
|
+
ctx.transform('decryptTextProp', 'spaceURI', object.encryptionKeyUrl, object),
|
|
182
|
+
ctx.transform('decryptTextProp', 'spaceURL', object.encryptionKeyUrl, object),
|
|
183
|
+
].concat(decryptedOrganizer, decryptedParticipants, decryptedMeetingJoinInfo)
|
|
184
|
+
);
|
|
185
|
+
},
|
|
117
186
|
},
|
|
118
187
|
{
|
|
119
188
|
name: 'transformMeetingNotes',
|
|
@@ -128,9 +197,9 @@ registerInternalPlugin('calendar', Calendar, {
|
|
|
128
197
|
}
|
|
129
198
|
|
|
130
199
|
return Promise.all([
|
|
131
|
-
ctx.transform('decryptTextProp', 'encryptedNotes', object.encryptionKeyUrl, object)
|
|
200
|
+
ctx.transform('decryptTextProp', 'encryptedNotes', object.encryptionKeyUrl, object),
|
|
132
201
|
]);
|
|
133
|
-
}
|
|
202
|
+
},
|
|
134
203
|
},
|
|
135
204
|
{
|
|
136
205
|
name: 'transformMeetingParticipants',
|
|
@@ -145,16 +214,28 @@ registerInternalPlugin('calendar', Calendar, {
|
|
|
145
214
|
}
|
|
146
215
|
|
|
147
216
|
// Decrypt participant properties
|
|
148
|
-
const decryptedParticipants = object.encryptedParticipants.map((participant) =>
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
217
|
+
const decryptedParticipants = object.encryptedParticipants.map((participant) =>
|
|
218
|
+
Promise.all([
|
|
219
|
+
ctx.transform(
|
|
220
|
+
'decryptTextProp',
|
|
221
|
+
'encryptedEmailAddress',
|
|
222
|
+
object.encryptionKeyUrl,
|
|
223
|
+
participant
|
|
224
|
+
),
|
|
225
|
+
ctx.transform(
|
|
226
|
+
'decryptTextProp',
|
|
227
|
+
'encryptedName',
|
|
228
|
+
object.encryptionKeyUrl,
|
|
229
|
+
participant
|
|
230
|
+
),
|
|
231
|
+
])
|
|
232
|
+
);
|
|
152
233
|
|
|
153
234
|
return Promise.all(decryptedParticipants);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
]
|
|
157
|
-
}
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
},
|
|
158
239
|
});
|
|
159
240
|
|
|
160
241
|
export {default} from './calendar';
|
package/src/util.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const CalendarUtil = {
|
|
2
|
-
|
|
3
2
|
// calculate the end time for the meeting based on the duration so it's stored on
|
|
4
3
|
// the scheduled meeting item, that way client can display start and end without
|
|
5
4
|
// calculation on their side
|
|
@@ -13,8 +12,11 @@ const CalendarUtil = {
|
|
|
13
12
|
* @memberof CalendarUtil
|
|
14
13
|
*/
|
|
15
14
|
calculateEndTime(item) {
|
|
16
|
-
return {
|
|
17
|
-
|
|
15
|
+
return {
|
|
16
|
+
...item,
|
|
17
|
+
endTime: new Date(new Date(item.start).getTime() + item.durationMinutes * 60000),
|
|
18
|
+
};
|
|
19
|
+
},
|
|
18
20
|
};
|
|
19
21
|
|
|
20
22
|
export default CalendarUtil;
|