@webex/internal-plugin-team 2.59.3-next.1 → 2.59.4-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/team.js CHANGED
@@ -1,437 +1,437 @@
1
- /*!
2
- * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
- */
4
-
5
- import querystring from 'querystring';
6
-
7
- import uuid from 'uuid';
8
- import {find, pick, uniq} from 'lodash';
9
- import {WebexPlugin} from '@webex/webex-core';
10
-
11
- const Team = WebexPlugin.extend({
12
- namespace: 'Team',
13
-
14
- /**
15
- * Move an existing group conversation into a team.
16
- * @param {TeamObject} team
17
- * @param {ConversationObject} conversation
18
- * @param {Object} activity Reference to the activity that will eventually be
19
- * posted. Use this to (a) pass in e.g. clientTempId and (b) render a
20
- * provisional activity
21
- * @returns {Promise} Resolves with the add activity
22
- */
23
- addConversation(team, conversation, activity) {
24
- return this._ensureGeneralConversation(team)
25
- .then((generalConversation) =>
26
- this.webex.internal.conversation.prepare(activity, {
27
- verb: 'add',
28
- target: this.webex.internal.conversation.prepareConversation(generalConversation),
29
- object: {
30
- id: conversation.id,
31
- objectType: 'conversation',
32
- },
33
- kmsMessage: {
34
- method: 'create',
35
- uri: '/authorizations',
36
- resourceUri: conversation.kmsResourceObjectUrl,
37
- userIds: [generalConversation.kmsResourceObjectUrl],
38
- },
39
- })
40
- )
41
- .then((a) => this.webex.internal.conversation.submit(a));
42
- },
43
-
44
- /**
45
- * Add a member to a team
46
- * @param {TeamObject} team
47
- * @param {Object} participant
48
- * @param {Object} activity Reference to the activity that will eventually be
49
- * posted. Use this to (a) pass in e.g. clientTempId and (b) render a
50
- * provisional activity
51
- * @returns {Promise} Resolves with activity that was posted
52
- */
53
- addMember(team, participant, activity) {
54
- return this._ensureGeneralConversation(team).then((generalConversation) =>
55
- this.webex.internal.conversation.add(generalConversation, participant, activity)
56
- );
57
- },
58
-
59
- /**
60
- * Create a team
61
- * @param {NewTeamObject} params
62
- * @param {string} params.displayName
63
- * @param {string} params.summary
64
- * @param {Array} params.participants
65
- * @returns {Promise} Resolves with the created team
66
- */
67
- create(params) {
68
- if (!params.displayName) {
69
- return Promise.reject(new Error('`params.displayName` is required'));
70
- }
71
-
72
- if (!params.participants || params.participants.length === 0) {
73
- return Promise.reject(new Error('`params.participants` is required'));
74
- }
75
-
76
- return Promise.all(
77
- params.participants.map((participant) =>
78
- this.webex.internal.user.asUUID(participant, {create: true})
79
- )
80
- )
81
- .then((participants) => {
82
- participants.unshift(this.webex.internal.device.userId);
83
- params.participants = uniq(participants);
84
- })
85
- .then(() => this._prepareTeam(params))
86
- .then((payload) =>
87
- this.webex.request({
88
- method: 'POST',
89
- service: 'conversation',
90
- resource: 'teams',
91
- body: payload,
92
- })
93
- )
94
- .then((res) => res.body);
95
- },
96
-
97
- /**
98
- * Create a conversation within a team. Currently does not support
99
- * activities besides add (ie no post or share activities).
100
- * @param {TeamObject} team
101
- * @param {NewConversationObject} params
102
- * @param {string} params.displayName
103
- * @param {string} params.summary
104
- * @param {Array} params.participants
105
- * @param {Object} options
106
- * @param {boolean} options.includeAllTeamMembers
107
- * @returns {Promise} Resolves with the newly created conversation
108
- */
109
- createConversation(team, params, options = {}) {
110
- if (!team.url) {
111
- return Promise.reject(new Error('`team.url` is required'));
112
- }
113
-
114
- if (!params.displayName) {
115
- return Promise.reject(new Error('`params.displayName` is required'));
116
- }
117
-
118
- return this._ensureGeneralConversation(team)
119
- .then((generalConversation) =>
120
- Promise.all(
121
- params.participants.map((participant) =>
122
- this.webex.internal.user.asUUID(participant, {create: true})
123
- )
124
- )
125
- .then((participants) => {
126
- participants.unshift(this.webex.internal.device.userId);
127
- params.participants = uniq(participants);
128
- })
129
- .then(() => this._prepareTeamConversation(generalConversation, params))
130
- )
131
- .then((payload) =>
132
- this.webex.request({
133
- method: 'POST',
134
- uri: `${team.url}/conversations`,
135
- qs: pick(options, 'includeAllTeamMembers'),
136
- body: payload,
137
- })
138
- )
139
- .then((res) => res.body);
140
- },
141
-
142
- /**
143
- * Retrieve a single team
144
- * @param {Object|Team~TeamObject} team
145
- * @param {string} team.url
146
- * @param {Object} options
147
- * @param {boolean} options.includeTeamConversations
148
- * @param {boolean} options.includeTeamMembers
149
- * @returns {Promise} Resolves with the requested team
150
- */
151
- get({url}, options = {}) {
152
- if (!url) {
153
- return Promise.reject(new Error('`team.url` is required'));
154
- }
155
- const params = {
156
- includeTeamConversations: false,
157
- includeTeamMembers: false,
158
- ...options,
159
- };
160
-
161
- return this.webex
162
- .request({
163
- uri: url,
164
- qs: params,
165
- })
166
- .then((res) => this._recordUUIDs(res.body).then(() => res.body));
167
- },
168
-
169
- /**
170
- * Get the list of conversations for a particular team
171
- * @param {TeamObject} team
172
- * @param {String} team.url
173
- * @returns {Promise} Resolves with an array of conversations
174
- */
175
- listConversations({url}) {
176
- if (!url) {
177
- return Promise.reject(new Error('`team.url` is required'));
178
- }
179
-
180
- return this.webex
181
- .request({
182
- uri: `${url}/conversations`,
183
- })
184
- .then((res) => res.body.items);
185
- },
186
-
187
- /**
188
- * Join a team conversation
189
- * @param {TeamObject} team
190
- * @param {ConversationObject} conversation
191
- * @param {userId} userId
192
- * @returns {Promise} Resolves with the conversation
193
- */
194
- joinConversation(team, conversation, userId) {
195
- if (!userId) {
196
- return Promise.reject(new Error('`userId` is required'));
197
- }
198
-
199
- const body = {
200
- kmsMessage: {
201
- client: {
202
- clientId: this.webex.internal.device.url,
203
- credential: {
204
- bearer: this.webex.credentials.supertoken.access_token,
205
- userId,
206
- },
207
- },
208
- method: 'create',
209
- requestId: uuid.v4(),
210
- resourceUri: conversation.kmsResourceObjectUrl,
211
- uri: '/authorizations',
212
- userIds: [userId],
213
- },
214
- };
215
-
216
- return this.webex
217
- .request({
218
- method: 'POST',
219
- uri: `${team.url}/conversations/${conversation.id}/participants`,
220
- body,
221
- })
222
- .then((res) => res.body);
223
- },
224
-
225
- /**
226
- * Retrieve all teams
227
- * @param {Object} options
228
- * @param {boolean} options.includeTeamConversations
229
- * @param {boolean} options.includeTeamMembers
230
- * @returns {Promise} Resolves with the requested teams
231
- */
232
- async list(options = {}) {
233
- const params = {
234
- includeTeamConversations: false,
235
- includeTeamMembers: false,
236
- ...options,
237
- };
238
- const resource = 'teams';
239
-
240
- const res = await this.webex.request({
241
- api: 'conversation',
242
- resource,
243
- qs: params,
244
- });
245
-
246
- let list = res.body.items.slice(0);
247
-
248
- if (res.body.additionalUrls) {
249
- const results = await Promise.all(
250
- res.body.additionalUrls.map((host) => {
251
- const uri = `${host}/${resource}`;
252
-
253
- return this.webex.request({
254
- uri,
255
- qs: params,
256
- });
257
- })
258
- );
259
-
260
- for (const result of results) {
261
- if (result.body && result.body.items && result.body.items.length) {
262
- list = list.concat(result.body.items);
263
- }
264
- }
265
- }
266
-
267
- await Promise.all(res.body.items.map((team) => this._recordUUIDs(team)));
268
-
269
- return list;
270
- },
271
-
272
- /**
273
- * Remove a member from a team
274
- * @param {TeamObject} team
275
- * @param {Object} participant
276
- * @param {Object} activity Reference to the activity that will eventually be
277
- * posted. Use this to (a) pass in e.g. clientTempId and (b) render a
278
- * provisional activity
279
- * @returns {Promise} Resolves with activity that was posted
280
- */
281
- removeMember(team, participant, activity) {
282
- return this._ensureGeneralConversation(team).then((generalConversation) =>
283
- this.webex.internal.conversation.leave(generalConversation, participant, activity)
284
- );
285
- },
286
-
287
- /**
288
- * Remove a team conversation from a team.
289
- * @param {TeamObject} team
290
- * @param {ConversationObject} conversation to be removed
291
- * @param {Object} activity Reference to the activity that will eventually be
292
- * posted. Use this to (a) pass in e.g. clientTempId and (b) render a
293
- * provisional activity
294
- * @returns {Promise} Resolves with the leave activity
295
- */
296
- removeConversation(team, conversation, activity) {
297
- return this._ensureGeneralConversation(team)
298
- .then((generalConversation) => {
299
- const properties = {
300
- verb: 'remove',
301
- object: pick(conversation, 'id', 'url', 'objectType'),
302
- target: pick(generalConversation, 'id', 'url', 'objectType'),
303
- kmsMessage: {
304
- method: 'delete',
305
- uri: `<KRO>/authorizations?${querystring.stringify({authId: conversation.id})}`,
306
- },
307
- };
308
-
309
- return this.webex.internal.conversation.prepare(activity, properties);
310
- })
311
- .then((a) => this.webex.internal.conversation.submit(a));
312
- },
313
-
314
- /**
315
- * Update the displayName, summary, or teamColor field for a team.
316
- * @param {TeamObject} team to be updated
317
- * @param {Object} object with updated displayName, summary, and/or teamColor
318
- * @param {Object} activity Reference to the activity that will eventually be
319
- * posted. Use this to (a) pass in e.g. clientTempId and (b) render a
320
- * provisional activity
321
- * @returns {Promise} Resolves with posted activity
322
- */
323
- update(team, object, activity) {
324
- return this.webex.internal.conversation.update(team, object, activity);
325
- },
326
-
327
- /* eslint-disable require-jsdoc */
328
- _ensureGeneralConversation(team) {
329
- if (!team.generalConversationUuid) {
330
- return Promise.reject(new Error('`team.generalConversationUuid` must be present'));
331
- }
332
-
333
- if (team.conversations.items.length) {
334
- const generalConversation = find(team.conversations.items, {
335
- id: team.generalConversationUuid,
336
- });
337
-
338
- if (generalConversation) {
339
- return Promise.resolve(generalConversation);
340
- }
341
- }
342
-
343
- return this.webex.internal.conversation.get({id: team.generalConversationUuid});
344
- },
345
-
346
- _prepareTeam: function _prepareTeam(params) {
347
- const payload = this.webex.internal.conversation._prepareConversationForCreation(params);
348
-
349
- payload.objectType = 'team';
350
-
351
- if (params.summary) {
352
- payload.summary = params.summary;
353
- }
354
-
355
- return Promise.resolve(payload);
356
- },
357
-
358
- _prepareTeamConversation(teamConversation, params) {
359
- if (!teamConversation.kmsResourceObjectUrl) {
360
- return Promise.reject(new Error('Team general conversation must have a KRO'));
361
- }
362
-
363
- const payload = this.webex.internal.conversation._prepareConversationForCreation(params);
364
-
365
- // Push the general conversation KRO on so that team members can
366
- // decrypt the title of this open room without joining it.
367
- payload.kmsMessage.userIds.push(teamConversation.kmsResourceObjectUrl);
368
-
369
- return Promise.resolve(payload);
370
- },
371
-
372
- _recordUUIDs(team) {
373
- if (!team.teamMembers || !team.teamMembers.items) {
374
- return Promise.resolve(team);
375
- }
376
-
377
- return Promise.all(
378
- team.teamMembers.items.map((participant) => {
379
- // ROOMs or LYRA_SPACEs do not have email addresses, so there's no point attempting to
380
- // record their UUIDs.
381
- if (participant.type === 'ROOM' || participant.type === 'LYRA_SPACE') {
382
- return Promise.resolve();
383
- }
384
-
385
- return this.webex.internal.user
386
- .recordUUID(participant)
387
- .catch((err) => this.logger.warn('Could not record uuid', err));
388
- })
389
- );
390
- },
391
- /* eslint-enable require-jsdoc */
392
- });
393
-
394
- /**
395
- * Assign or unassign a team member to be a moderator of a team
396
- * @param {TeamObject} team
397
- * @param {Object} participant
398
- * @param {Object} activity
399
- * @returns {Promise} Resolves with activity that was posted
400
- */
401
- ['assignModerator', 'unassignModerator'].forEach((verb) => {
402
- Team.prototype[verb] = function submitModerationChangeActivity(team, member, activity) {
403
- return this._ensureGeneralConversation(team).then((teamConversation) =>
404
- this.webex.internal.conversation[verb](teamConversation, member, activity)
405
- );
406
- };
407
- });
408
-
409
- /**
410
- * Archive or unarchive a team or team conversation.
411
- * @param {TeamObject|ConversationObject} target team or team conversation that should be archived
412
- * @param {Object} activity Reference to the activity that will eventually be
413
- * posted. Use this to (a) pass in e.g. clientTempId and (b) render a
414
- * provisional activity
415
- * @returns {Promise} Resolves with the posted activity
416
- */
417
- ['archive', 'unarchive'].forEach((verb) => {
418
- Team.prototype[verb] = function submitArchiveStateChangeActivity(target, activity) {
419
- if (!target.objectType) {
420
- return Promise.reject(new Error('`target.objectType` is required'));
421
- }
422
-
423
- const properties = {
424
- verb,
425
- object: pick(target, 'id', 'url', 'objectType'),
426
- target: pick(target, 'id', 'url', 'objectType'),
427
- };
428
-
429
- const teamUrl = this.webex.internal.conversation.getConvoUrl(target);
430
-
431
- return this.webex.internal.conversation
432
- .prepare(activity, properties)
433
- .then((a) => this.webex.internal.conversation.submit(a, teamUrl));
434
- };
435
- });
436
-
437
- export default Team;
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ import querystring from 'querystring';
6
+
7
+ import uuid from 'uuid';
8
+ import {find, pick, uniq} from 'lodash';
9
+ import {WebexPlugin} from '@webex/webex-core';
10
+
11
+ const Team = WebexPlugin.extend({
12
+ namespace: 'Team',
13
+
14
+ /**
15
+ * Move an existing group conversation into a team.
16
+ * @param {TeamObject} team
17
+ * @param {ConversationObject} conversation
18
+ * @param {Object} activity Reference to the activity that will eventually be
19
+ * posted. Use this to (a) pass in e.g. clientTempId and (b) render a
20
+ * provisional activity
21
+ * @returns {Promise} Resolves with the add activity
22
+ */
23
+ addConversation(team, conversation, activity) {
24
+ return this._ensureGeneralConversation(team)
25
+ .then((generalConversation) =>
26
+ this.webex.internal.conversation.prepare(activity, {
27
+ verb: 'add',
28
+ target: this.webex.internal.conversation.prepareConversation(generalConversation),
29
+ object: {
30
+ id: conversation.id,
31
+ objectType: 'conversation',
32
+ },
33
+ kmsMessage: {
34
+ method: 'create',
35
+ uri: '/authorizations',
36
+ resourceUri: conversation.kmsResourceObjectUrl,
37
+ userIds: [generalConversation.kmsResourceObjectUrl],
38
+ },
39
+ })
40
+ )
41
+ .then((a) => this.webex.internal.conversation.submit(a));
42
+ },
43
+
44
+ /**
45
+ * Add a member to a team
46
+ * @param {TeamObject} team
47
+ * @param {Object} participant
48
+ * @param {Object} activity Reference to the activity that will eventually be
49
+ * posted. Use this to (a) pass in e.g. clientTempId and (b) render a
50
+ * provisional activity
51
+ * @returns {Promise} Resolves with activity that was posted
52
+ */
53
+ addMember(team, participant, activity) {
54
+ return this._ensureGeneralConversation(team).then((generalConversation) =>
55
+ this.webex.internal.conversation.add(generalConversation, participant, activity)
56
+ );
57
+ },
58
+
59
+ /**
60
+ * Create a team
61
+ * @param {NewTeamObject} params
62
+ * @param {string} params.displayName
63
+ * @param {string} params.summary
64
+ * @param {Array} params.participants
65
+ * @returns {Promise} Resolves with the created team
66
+ */
67
+ create(params) {
68
+ if (!params.displayName) {
69
+ return Promise.reject(new Error('`params.displayName` is required'));
70
+ }
71
+
72
+ if (!params.participants || params.participants.length === 0) {
73
+ return Promise.reject(new Error('`params.participants` is required'));
74
+ }
75
+
76
+ return Promise.all(
77
+ params.participants.map((participant) =>
78
+ this.webex.internal.user.asUUID(participant, {create: true})
79
+ )
80
+ )
81
+ .then((participants) => {
82
+ participants.unshift(this.webex.internal.device.userId);
83
+ params.participants = uniq(participants);
84
+ })
85
+ .then(() => this._prepareTeam(params))
86
+ .then((payload) =>
87
+ this.webex.request({
88
+ method: 'POST',
89
+ service: 'conversation',
90
+ resource: 'teams',
91
+ body: payload,
92
+ })
93
+ )
94
+ .then((res) => res.body);
95
+ },
96
+
97
+ /**
98
+ * Create a conversation within a team. Currently does not support
99
+ * activities besides add (ie no post or share activities).
100
+ * @param {TeamObject} team
101
+ * @param {NewConversationObject} params
102
+ * @param {string} params.displayName
103
+ * @param {string} params.summary
104
+ * @param {Array} params.participants
105
+ * @param {Object} options
106
+ * @param {boolean} options.includeAllTeamMembers
107
+ * @returns {Promise} Resolves with the newly created conversation
108
+ */
109
+ createConversation(team, params, options = {}) {
110
+ if (!team.url) {
111
+ return Promise.reject(new Error('`team.url` is required'));
112
+ }
113
+
114
+ if (!params.displayName) {
115
+ return Promise.reject(new Error('`params.displayName` is required'));
116
+ }
117
+
118
+ return this._ensureGeneralConversation(team)
119
+ .then((generalConversation) =>
120
+ Promise.all(
121
+ params.participants.map((participant) =>
122
+ this.webex.internal.user.asUUID(participant, {create: true})
123
+ )
124
+ )
125
+ .then((participants) => {
126
+ participants.unshift(this.webex.internal.device.userId);
127
+ params.participants = uniq(participants);
128
+ })
129
+ .then(() => this._prepareTeamConversation(generalConversation, params))
130
+ )
131
+ .then((payload) =>
132
+ this.webex.request({
133
+ method: 'POST',
134
+ uri: `${team.url}/conversations`,
135
+ qs: pick(options, 'includeAllTeamMembers'),
136
+ body: payload,
137
+ })
138
+ )
139
+ .then((res) => res.body);
140
+ },
141
+
142
+ /**
143
+ * Retrieve a single team
144
+ * @param {Object|Team~TeamObject} team
145
+ * @param {string} team.url
146
+ * @param {Object} options
147
+ * @param {boolean} options.includeTeamConversations
148
+ * @param {boolean} options.includeTeamMembers
149
+ * @returns {Promise} Resolves with the requested team
150
+ */
151
+ get({url}, options = {}) {
152
+ if (!url) {
153
+ return Promise.reject(new Error('`team.url` is required'));
154
+ }
155
+ const params = {
156
+ includeTeamConversations: false,
157
+ includeTeamMembers: false,
158
+ ...options,
159
+ };
160
+
161
+ return this.webex
162
+ .request({
163
+ uri: url,
164
+ qs: params,
165
+ })
166
+ .then((res) => this._recordUUIDs(res.body).then(() => res.body));
167
+ },
168
+
169
+ /**
170
+ * Get the list of conversations for a particular team
171
+ * @param {TeamObject} team
172
+ * @param {String} team.url
173
+ * @returns {Promise} Resolves with an array of conversations
174
+ */
175
+ listConversations({url}) {
176
+ if (!url) {
177
+ return Promise.reject(new Error('`team.url` is required'));
178
+ }
179
+
180
+ return this.webex
181
+ .request({
182
+ uri: `${url}/conversations`,
183
+ })
184
+ .then((res) => res.body.items);
185
+ },
186
+
187
+ /**
188
+ * Join a team conversation
189
+ * @param {TeamObject} team
190
+ * @param {ConversationObject} conversation
191
+ * @param {userId} userId
192
+ * @returns {Promise} Resolves with the conversation
193
+ */
194
+ joinConversation(team, conversation, userId) {
195
+ if (!userId) {
196
+ return Promise.reject(new Error('`userId` is required'));
197
+ }
198
+
199
+ const body = {
200
+ kmsMessage: {
201
+ client: {
202
+ clientId: this.webex.internal.device.url,
203
+ credential: {
204
+ bearer: this.webex.credentials.supertoken.access_token,
205
+ userId,
206
+ },
207
+ },
208
+ method: 'create',
209
+ requestId: uuid.v4(),
210
+ resourceUri: conversation.kmsResourceObjectUrl,
211
+ uri: '/authorizations',
212
+ userIds: [userId],
213
+ },
214
+ };
215
+
216
+ return this.webex
217
+ .request({
218
+ method: 'POST',
219
+ uri: `${team.url}/conversations/${conversation.id}/participants`,
220
+ body,
221
+ })
222
+ .then((res) => res.body);
223
+ },
224
+
225
+ /**
226
+ * Retrieve all teams
227
+ * @param {Object} options
228
+ * @param {boolean} options.includeTeamConversations
229
+ * @param {boolean} options.includeTeamMembers
230
+ * @returns {Promise} Resolves with the requested teams
231
+ */
232
+ async list(options = {}) {
233
+ const params = {
234
+ includeTeamConversations: false,
235
+ includeTeamMembers: false,
236
+ ...options,
237
+ };
238
+ const resource = 'teams';
239
+
240
+ const res = await this.webex.request({
241
+ api: 'conversation',
242
+ resource,
243
+ qs: params,
244
+ });
245
+
246
+ let list = res.body.items.slice(0);
247
+
248
+ if (res.body.additionalUrls) {
249
+ const results = await Promise.all(
250
+ res.body.additionalUrls.map((host) => {
251
+ const uri = `${host}/${resource}`;
252
+
253
+ return this.webex.request({
254
+ uri,
255
+ qs: params,
256
+ });
257
+ })
258
+ );
259
+
260
+ for (const result of results) {
261
+ if (result.body && result.body.items && result.body.items.length) {
262
+ list = list.concat(result.body.items);
263
+ }
264
+ }
265
+ }
266
+
267
+ await Promise.all(res.body.items.map((team) => this._recordUUIDs(team)));
268
+
269
+ return list;
270
+ },
271
+
272
+ /**
273
+ * Remove a member from a team
274
+ * @param {TeamObject} team
275
+ * @param {Object} participant
276
+ * @param {Object} activity Reference to the activity that will eventually be
277
+ * posted. Use this to (a) pass in e.g. clientTempId and (b) render a
278
+ * provisional activity
279
+ * @returns {Promise} Resolves with activity that was posted
280
+ */
281
+ removeMember(team, participant, activity) {
282
+ return this._ensureGeneralConversation(team).then((generalConversation) =>
283
+ this.webex.internal.conversation.leave(generalConversation, participant, activity)
284
+ );
285
+ },
286
+
287
+ /**
288
+ * Remove a team conversation from a team.
289
+ * @param {TeamObject} team
290
+ * @param {ConversationObject} conversation to be removed
291
+ * @param {Object} activity Reference to the activity that will eventually be
292
+ * posted. Use this to (a) pass in e.g. clientTempId and (b) render a
293
+ * provisional activity
294
+ * @returns {Promise} Resolves with the leave activity
295
+ */
296
+ removeConversation(team, conversation, activity) {
297
+ return this._ensureGeneralConversation(team)
298
+ .then((generalConversation) => {
299
+ const properties = {
300
+ verb: 'remove',
301
+ object: pick(conversation, 'id', 'url', 'objectType'),
302
+ target: pick(generalConversation, 'id', 'url', 'objectType'),
303
+ kmsMessage: {
304
+ method: 'delete',
305
+ uri: `<KRO>/authorizations?${querystring.stringify({authId: conversation.id})}`,
306
+ },
307
+ };
308
+
309
+ return this.webex.internal.conversation.prepare(activity, properties);
310
+ })
311
+ .then((a) => this.webex.internal.conversation.submit(a));
312
+ },
313
+
314
+ /**
315
+ * Update the displayName, summary, or teamColor field for a team.
316
+ * @param {TeamObject} team to be updated
317
+ * @param {Object} object with updated displayName, summary, and/or teamColor
318
+ * @param {Object} activity Reference to the activity that will eventually be
319
+ * posted. Use this to (a) pass in e.g. clientTempId and (b) render a
320
+ * provisional activity
321
+ * @returns {Promise} Resolves with posted activity
322
+ */
323
+ update(team, object, activity) {
324
+ return this.webex.internal.conversation.update(team, object, activity);
325
+ },
326
+
327
+ /* eslint-disable require-jsdoc */
328
+ _ensureGeneralConversation(team) {
329
+ if (!team.generalConversationUuid) {
330
+ return Promise.reject(new Error('`team.generalConversationUuid` must be present'));
331
+ }
332
+
333
+ if (team.conversations.items.length) {
334
+ const generalConversation = find(team.conversations.items, {
335
+ id: team.generalConversationUuid,
336
+ });
337
+
338
+ if (generalConversation) {
339
+ return Promise.resolve(generalConversation);
340
+ }
341
+ }
342
+
343
+ return this.webex.internal.conversation.get({id: team.generalConversationUuid});
344
+ },
345
+
346
+ _prepareTeam: function _prepareTeam(params) {
347
+ const payload = this.webex.internal.conversation._prepareConversationForCreation(params);
348
+
349
+ payload.objectType = 'team';
350
+
351
+ if (params.summary) {
352
+ payload.summary = params.summary;
353
+ }
354
+
355
+ return Promise.resolve(payload);
356
+ },
357
+
358
+ _prepareTeamConversation(teamConversation, params) {
359
+ if (!teamConversation.kmsResourceObjectUrl) {
360
+ return Promise.reject(new Error('Team general conversation must have a KRO'));
361
+ }
362
+
363
+ const payload = this.webex.internal.conversation._prepareConversationForCreation(params);
364
+
365
+ // Push the general conversation KRO on so that team members can
366
+ // decrypt the title of this open room without joining it.
367
+ payload.kmsMessage.userIds.push(teamConversation.kmsResourceObjectUrl);
368
+
369
+ return Promise.resolve(payload);
370
+ },
371
+
372
+ _recordUUIDs(team) {
373
+ if (!team.teamMembers || !team.teamMembers.items) {
374
+ return Promise.resolve(team);
375
+ }
376
+
377
+ return Promise.all(
378
+ team.teamMembers.items.map((participant) => {
379
+ // ROOMs or LYRA_SPACEs do not have email addresses, so there's no point attempting to
380
+ // record their UUIDs.
381
+ if (participant.type === 'ROOM' || participant.type === 'LYRA_SPACE') {
382
+ return Promise.resolve();
383
+ }
384
+
385
+ return this.webex.internal.user
386
+ .recordUUID(participant)
387
+ .catch((err) => this.logger.warn('Could not record uuid', err));
388
+ })
389
+ );
390
+ },
391
+ /* eslint-enable require-jsdoc */
392
+ });
393
+
394
+ /**
395
+ * Assign or unassign a team member to be a moderator of a team
396
+ * @param {TeamObject} team
397
+ * @param {Object} participant
398
+ * @param {Object} activity
399
+ * @returns {Promise} Resolves with activity that was posted
400
+ */
401
+ ['assignModerator', 'unassignModerator'].forEach((verb) => {
402
+ Team.prototype[verb] = function submitModerationChangeActivity(team, member, activity) {
403
+ return this._ensureGeneralConversation(team).then((teamConversation) =>
404
+ this.webex.internal.conversation[verb](teamConversation, member, activity)
405
+ );
406
+ };
407
+ });
408
+
409
+ /**
410
+ * Archive or unarchive a team or team conversation.
411
+ * @param {TeamObject|ConversationObject} target team or team conversation that should be archived
412
+ * @param {Object} activity Reference to the activity that will eventually be
413
+ * posted. Use this to (a) pass in e.g. clientTempId and (b) render a
414
+ * provisional activity
415
+ * @returns {Promise} Resolves with the posted activity
416
+ */
417
+ ['archive', 'unarchive'].forEach((verb) => {
418
+ Team.prototype[verb] = function submitArchiveStateChangeActivity(target, activity) {
419
+ if (!target.objectType) {
420
+ return Promise.reject(new Error('`target.objectType` is required'));
421
+ }
422
+
423
+ const properties = {
424
+ verb,
425
+ object: pick(target, 'id', 'url', 'objectType'),
426
+ target: pick(target, 'id', 'url', 'objectType'),
427
+ };
428
+
429
+ const teamUrl = this.webex.internal.conversation.getConvoUrl(target);
430
+
431
+ return this.webex.internal.conversation
432
+ .prepare(activity, properties)
433
+ .then((a) => this.webex.internal.conversation.submit(a, teamUrl));
434
+ };
435
+ });
436
+
437
+ export default Team;