@webex/internal-plugin-user 3.12.0-mobius-socket.1 → 3.12.0-next.10
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/dist/user-uuid-batcher.js +1 -1
- package/dist/user.js +99 -3
- package/dist/user.js.map +1 -1
- package/package.json +11 -11
- package/src/user.js +96 -0
- package/test/unit/spec/user.js +193 -0
|
@@ -125,7 +125,7 @@ var UserUUIDBatcher = _webexCore.WebexPlugin.extend({
|
|
|
125
125
|
request: function request(payload) {
|
|
126
126
|
return payload.create ? this.creator.request(payload.email) : this.faker.request(payload.email);
|
|
127
127
|
},
|
|
128
|
-
version: "3.12.0-
|
|
128
|
+
version: "3.12.0-next.10"
|
|
129
129
|
});
|
|
130
130
|
var _default = exports.default = UserUUIDBatcher;
|
|
131
131
|
//# sourceMappingURL=user-uuid-batcher.js.map
|
package/dist/user.js
CHANGED
|
@@ -10,12 +10,17 @@ var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequ
|
|
|
10
10
|
_Object$defineProperty(exports, "__esModule", {
|
|
11
11
|
value: true
|
|
12
12
|
});
|
|
13
|
+
exports.SCIM_SCHEMAS = void 0;
|
|
14
|
+
exports.buildMeetingSiteList = buildMeetingSiteList;
|
|
15
|
+
exports.buildPreferredSiteBody = buildPreferredSiteBody;
|
|
13
16
|
exports.default = void 0;
|
|
17
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
|
|
18
|
+
var _applyDecoratedDescriptor2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/applyDecoratedDescriptor"));
|
|
19
|
+
var _set = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/set"));
|
|
14
20
|
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
|
|
15
21
|
var _apply = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/reflect/apply"));
|
|
16
22
|
var _getOwnPropertyDescriptor = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor"));
|
|
17
|
-
var
|
|
18
|
-
var _applyDecoratedDescriptor2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/applyDecoratedDescriptor"));
|
|
23
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/toConsumableArray"));
|
|
19
24
|
var _lodash = require("lodash");
|
|
20
25
|
var _common = require("@webex/common");
|
|
21
26
|
var _webexCore = require("@webex/webex-core");
|
|
@@ -27,6 +32,50 @@ var _dec, _dec2, _dec3, _dec4, _obj;
|
|
|
27
32
|
*/
|
|
28
33
|
function ownKeys(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return _Object$getOwnPropertyDescriptor2(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
29
34
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor2(t, r)); }); } return e; }
|
|
35
|
+
var SCIM_SCHEMAS = exports.SCIM_SCHEMAS = ['urn:scim:schemas:core:1.0', 'urn:scim:schemas:extension:cisco:commonidentity:1.0'];
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Builds a SCIM PATCH body for updating the user's preferred Webex site.
|
|
39
|
+
* Matches the native client's SCIM format: delete old + add new in a single PATCH.
|
|
40
|
+
* @param {string} newSiteUrl - The new preferred site
|
|
41
|
+
* @param {string} [oldSiteUrl] - The previous preferred site to remove
|
|
42
|
+
* @returns {Object} SCIM-formatted request body
|
|
43
|
+
*/
|
|
44
|
+
function buildPreferredSiteBody(newSiteUrl, oldSiteUrl) {
|
|
45
|
+
var userPreferences = [];
|
|
46
|
+
if (oldSiteUrl) {
|
|
47
|
+
userPreferences.push({
|
|
48
|
+
operation: 'delete',
|
|
49
|
+
value: "\"preferredWebExSite\":\"".concat(oldSiteUrl, "\"")
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
userPreferences.push({
|
|
53
|
+
value: "\"preferredWebExSite\":\"".concat(newSiteUrl, "\"")
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
schemas: SCIM_SCHEMAS,
|
|
57
|
+
userPreferences: userPreferences
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Builds a deduplicated, sorted list of meeting sites from a user profile.
|
|
63
|
+
* Merges linkedTrainSiteNames and trainSiteNames, filters out attendee-only
|
|
64
|
+
* sites (those containing '#'), and sorts alphabetically.
|
|
65
|
+
* Matches the native client's site list filtering logic.
|
|
66
|
+
* @param {Object} user - User profile object
|
|
67
|
+
* @param {string[]} [user.linkedTrainSiteNames] - Linked training site names
|
|
68
|
+
* @param {string[]} [user.trainSiteNames] - Training site names
|
|
69
|
+
* @returns {string[]} Sorted array of site URLs
|
|
70
|
+
*/
|
|
71
|
+
function buildMeetingSiteList(user) {
|
|
72
|
+
var linked = user && user.linkedTrainSiteNames || [];
|
|
73
|
+
var train = user && user.trainSiteNames || [];
|
|
74
|
+
return (0, _toConsumableArray2.default)(new _set.default(linked.concat(train))).filter(function (site) {
|
|
75
|
+
return site.indexOf('#') === -1;
|
|
76
|
+
}).sort();
|
|
77
|
+
}
|
|
78
|
+
|
|
30
79
|
/**
|
|
31
80
|
* @class
|
|
32
81
|
*/
|
|
@@ -312,6 +361,53 @@ var User = _webexCore.WebexPlugin.extend((_dec = (0, _webexCore.waitForValue)('@
|
|
|
312
361
|
return res.body;
|
|
313
362
|
});
|
|
314
363
|
},
|
|
364
|
+
/**
|
|
365
|
+
* Updates the user's preferred Webex meeting site via org-scoped SCIM PATCH.
|
|
366
|
+
* @instance
|
|
367
|
+
* @memberof User
|
|
368
|
+
* @param {Object} options
|
|
369
|
+
* @param {string} options.newSiteUrl - The new preferred site (e.g., 'example.webex.com')
|
|
370
|
+
* @param {string} [options.oldSiteUrl] - The previous preferred site to remove
|
|
371
|
+
* @param {string} [options.orgId] - Organization ID. If not provided, extracted from credentials.
|
|
372
|
+
* @returns {Promise<Object>} Resolves with the SCIM response body
|
|
373
|
+
*/
|
|
374
|
+
updatePreferredWebexSite: function updatePreferredWebexSite() {
|
|
375
|
+
var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
|
|
376
|
+
newSiteUrl = _ref2.newSiteUrl,
|
|
377
|
+
oldSiteUrl = _ref2.oldSiteUrl,
|
|
378
|
+
orgId = _ref2.orgId;
|
|
379
|
+
if (!newSiteUrl) {
|
|
380
|
+
return _promise.default.reject(new Error('`options.newSiteUrl` is required'));
|
|
381
|
+
}
|
|
382
|
+
try {
|
|
383
|
+
var resolvedOrgId = orgId || this.webex.credentials.getOrgId();
|
|
384
|
+
var userId = this.webex.internal.device.userId;
|
|
385
|
+
if (!userId) {
|
|
386
|
+
return _promise.default.reject(new Error('device.userId is not available — ensure device.register() has completed'));
|
|
387
|
+
}
|
|
388
|
+
var identityUrl = this.webex.config.credentials.identity.url;
|
|
389
|
+
return this.request({
|
|
390
|
+
uri: "".concat(identityUrl, "/identity/scim/").concat(resolvedOrgId, "/v1/Users/").concat(userId),
|
|
391
|
+
method: 'PATCH',
|
|
392
|
+
body: buildPreferredSiteBody(newSiteUrl, oldSiteUrl)
|
|
393
|
+
}).then(function (res) {
|
|
394
|
+
return res.body;
|
|
395
|
+
});
|
|
396
|
+
} catch (error) {
|
|
397
|
+
return _promise.default.reject(error);
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
/**
|
|
401
|
+
* Returns a sorted, filtered list of meeting sites from a user profile.
|
|
402
|
+
* Delegates to the pure buildMeetingSiteList function.
|
|
403
|
+
* @instance
|
|
404
|
+
* @memberof User
|
|
405
|
+
* @param {Object} user - User profile object from webex.internal.user.get()
|
|
406
|
+
* @returns {string[]} Sorted array of site URLs
|
|
407
|
+
*/
|
|
408
|
+
getMeetingSiteList: function getMeetingSiteList(user) {
|
|
409
|
+
return buildMeetingSiteList(user);
|
|
410
|
+
},
|
|
315
411
|
/**
|
|
316
412
|
* Updates the current user's display name
|
|
317
413
|
* @param {Object} options
|
|
@@ -451,7 +547,7 @@ var User = _webexCore.WebexPlugin.extend((_dec = (0, _webexCore.waitForValue)('@
|
|
|
451
547
|
_extractEmailAddress: function _extractEmailAddress(user) {
|
|
452
548
|
return user.email || user.emailAddress || user.entryEmail || user;
|
|
453
549
|
},
|
|
454
|
-
version: "3.12.0-
|
|
550
|
+
version: "3.12.0-next.10"
|
|
455
551
|
}, (0, _applyDecoratedDescriptor2.default)(_obj, "activate", [_dec], (0, _getOwnPropertyDescriptor.default)(_obj, "activate"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "getUUID", [_dec2], (0, _getOwnPropertyDescriptor.default)(_obj, "getUUID"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "initialize", [_dec3], (0, _getOwnPropertyDescriptor.default)(_obj, "initialize"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "register", [_dec4], (0, _getOwnPropertyDescriptor.default)(_obj, "register"), _obj), _obj));
|
|
456
552
|
var _default2 = exports.default = User;
|
|
457
553
|
//# sourceMappingURL=user.js.map
|
package/dist/user.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_lodash","require","_common","_webexCore","_userUuidBatcher","_interopRequireDefault","_userUuidStore","_dec","_dec2","_dec3","_dec4","_obj","ownKeys","e","r","t","_Object$keys","_Object$getOwnPropertySymbols","o","filter","_Object$getOwnPropertyDescriptor2","enumerable","push","apply","_objectSpread","arguments","length","Object","forEach","_defineProperty2","default","_Object$getOwnPropertyDescriptors","_Object$defineProperties","_Object$defineProperty","User","WebexPlugin","extend","waitForValue","oneFlight","keyFactory","email","options","String","create","persist","deprecated","namespace","children","batcher","UserUUIDBatcher","props","hasPassword","type","session","store","UserUUIDStore","activate","_this","undefined","verificationToken","confirmationCode","id","_promise","reject","Error","scope","webex","config","credentials","activateOptions","request","uri","activationUrl","method","body","auth","user","client_id","pass","client_secret","sendImmediately","then","res","set","supertoken","tokenData","asUUID","_this2","isArray","all","map","u","_extractUUID","force","patterns","uuid","test","resolve","_extractEmailAddress","getUUID","fetchUUID","_this3","recordUUID","emailAddress","generateOTP","generateOtpUrl","get","_this4","service","resource","tap","_this5","getByEmail","userExists","catch","initialize","_len","args","Array","_key","_apply","prototype","add","register","verify","_setUser","_this6","getUserToken","token","concat","setPasswordUrl","internal","device","userId","headers","authorization","toString","setPassword","_this7","password","schemas","updateName","_ref","givenName","familyName","displayName","name","update","validateOTP","_this8","oneTimePassword","validateOtpUrl","_this9","verifyDefaults","_options","services","collectPreauthCatalog","getClientToken","preloginId","shouldRefreshAccessToken","sso","getUserCI","lookupCI","verifyOptions","suppressEmail","userEntities","idBrokerUrl","idbroker","url","identityUrl","identity","entryUUID","entryEmail","version","_applyDecoratedDescriptor2","_getOwnPropertyDescriptor","_default2","exports"],"sources":["user.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {isArray} from 'lodash';\nimport {deprecated, oneFlight, patterns, tap} from '@webex/common';\nimport {persist, WebexPlugin, waitForValue} from '@webex/webex-core';\n\nimport UserUUIDBatcher from './user-uuid-batcher';\nimport UserUUIDStore from './user-uuid-store';\n\n/**\n * @class\n */\nconst User = WebexPlugin.extend({\n namespace: 'User',\n\n children: {\n batcher: UserUUIDBatcher,\n },\n\n props: {\n /**\n * Indicates if the current user is known to have a password.\n * @instance\n * @memberof User\n * @type {boolean}\n */\n hasPassword: {\n default: false,\n type: 'boolean',\n },\n },\n\n session: {\n store: {\n default() {\n return new UserUUIDStore();\n },\n type: 'any',\n },\n },\n\n @waitForValue('@')\n /**\n * Activates a Webex user account and exchanges for user token.\n * @instance\n * @memberof User\n * @param {Object} options\n * @param {Object} options.confirmationCode (required -- optional if verification token is provided)\n * @param {Object} options.id (required -- optional if verification token is provided)\n * @param {Object} options.verificationToken (required -- optional if uuid and verification token provided)\n * @param {Object} options.email (required with verificationToken for Federation/global user)\n * @returns {Promise} Resolves with a userSession\n */\n activate(options = {}) {\n if (!(options.verificationToken || (options.confirmationCode && options.id))) {\n return Promise.reject(\n new Error(\n 'either options.verificationToken is required or both options.confirmationCode and options.id are required'\n )\n );\n }\n\n options.scope = this.webex.config.credentials.scope;\n\n // if we have options.email and options.verificationToken\n // and Federation flag is enabled, flag that we need to\n // lookup user's CI.\n const activateOptions = {...options};\n\n delete activateOptions.email;\n\n return this.request({\n uri: this.webex.config.credentials.activationUrl,\n method: 'POST',\n body: activateOptions,\n auth: {\n user: this.webex.config.credentials.client_id,\n pass: this.webex.config.credentials.client_secret,\n sendImmediately: true,\n },\n }).then((res) => {\n this.webex.credentials.set({supertoken: res.body.tokenData});\n\n return res.body;\n });\n },\n\n /**\n * Converts a user-identifying object to a uuid, perhaps by doing a network\n * lookup\n * @param {string|Object} user\n * @param {Object} options\n * @param {boolean} options.create if true, ensures the return UUID refers to\n * an existing user (rather than creating one deterministically based on email\n * address), even if that user must be created\n * @returns {Promise<string>}\n */\n asUUID(user, options) {\n if (!user) {\n return Promise.reject(new Error('`user` is required'));\n }\n\n if (isArray(user)) {\n return Promise.all(user.map((u) => this.asUUID(u, options)));\n }\n\n const id = this._extractUUID(user);\n\n if (!(options && options.force) && patterns.uuid.test(id)) {\n return Promise.resolve(id);\n }\n\n const email = this._extractEmailAddress(user);\n\n if (!patterns.email.test(email)) {\n return Promise.reject(new Error('Provided user object does not appear to identify a user'));\n }\n\n return this.getUUID(email, options);\n },\n\n /**\n * Requests a uuid from the api\n * @param {string} email\n * @param {Object} options\n * @param {boolean} options.create\n * @returns {Promise<string>}\n */\n fetchUUID(email, options) {\n return this.batcher\n .request({\n email,\n create: options && options.create,\n })\n .then((user) => this.recordUUID({emailAddress: email, ...user}).then(() => user.id));\n },\n /**\n * Generates One Time Password.\n * @instance\n * @param {Object} options\n * @param {string} options.email\n * @param {string} options.id\n * @returns {Promise}\n */\n generateOTP(options = {}) {\n if (!(options.email || options.id)) {\n return Promise.reject(new Error('One of `options.email` or `options.id` is required'));\n }\n\n return this.request({\n uri: this.webex.config.credentials.generateOtpUrl,\n method: 'POST',\n body: options,\n auth: {\n user: this.webex.config.credentials.client_id,\n pass: this.webex.config.credentials.client_secret,\n },\n }).then((res) => res.body);\n },\n\n /**\n * Fetches details about the current user\n * @returns {Promise<Object>}\n */\n get() {\n return this.request({\n service: 'conversation',\n resource: 'users',\n })\n .then((res) => res.body)\n .then(\n tap((user) =>\n this.recordUUID({\n id: user.id,\n // CI endpoints don't use the same user format as actors, so, email may\n // be in one of a few fields\n emailAddress: user.email || user.emailAddress,\n })\n )\n );\n },\n\n /**\n * Converts an email address to a uuid, perhaps by doing a network lookup\n * @param {string} email\n * @param {Object} options\n * @param {boolean} options.create\n * @returns {Promise<string>}\n */\n @oneFlight({keyFactory: (email, options) => email + String(options && options.create)})\n getUUID(email, options) {\n return this.store\n .getByEmail(email)\n .then((user) => {\n if (options && options.create && !user.userExists) {\n return Promise.reject(new Error('User for specified email cannot be confirmed to exist'));\n }\n\n if (!user.id) {\n return Promise.reject(new Error('No id recorded for specified user'));\n }\n\n return user.id;\n })\n .catch(() => this.fetchUUID(email, options));\n },\n\n @persist('@')\n initialize(...args) {\n return Reflect.apply(WebexPlugin.prototype.initialize, this, args);\n },\n\n /**\n * Caches the uuid for the specified email address\n * @param {Object} user\n * @param {string} user.id\n * @param {string} user.emailAddress\n * @returns {Promise}\n */\n recordUUID(user) {\n if (!user) {\n return Promise.reject(new Error('`user` is required'));\n }\n\n if (!user.id) {\n return Promise.reject(new Error('`user.id` is required'));\n }\n\n if (!patterns.uuid.test(user.id)) {\n return Promise.reject(new Error('`user.id` must be a uuid'));\n }\n\n if (!user.emailAddress) {\n return Promise.reject(new Error('`user.emailAddress` is required'));\n }\n\n if (!patterns.email.test(user.emailAddress)) {\n return Promise.reject(new Error('`user.emailAddress` must be an email address'));\n }\n\n return this.store.add(user);\n },\n\n @deprecated('Use User#verify()')\n register(...args) {\n return this.verify(...args);\n },\n\n /**\n * Updates a user with webex.\n * @param {Object} body\n * @private\n * @returns {Promise} Resolves with a response from PATCH request\n */\n _setUser(body) {\n return this.webex.credentials.getUserToken().then((token) =>\n this.request({\n uri: `${this.webex.config.credentials.setPasswordUrl}/${this.webex.internal.device.userId}`,\n method: 'PATCH',\n headers: {\n authorization: token.toString(),\n },\n body,\n })\n );\n },\n\n /**\n * Updates a user's password with webex.\n * @instance\n * @memberof User\n * @param {Object} options\n * @param {string} options.password (required)\n * @param {string} options.email (required when federation enabled)\n * @returns {Promise} Resolves with complete user object containing new password\n */\n setPassword(options) {\n options = options || {};\n if (!options.password) {\n return Promise.reject(new Error('`options.password` is required'));\n }\n\n return this._setUser({\n schemas: ['urn:scim:schemas:core:1.0', 'urn:scim:schemas:extension:cisco:commonidentity:1.0'],\n password: options.password,\n }).then((res) => {\n this.hasPassword = true;\n\n return res.body;\n });\n },\n\n /**\n * Updates a user's name with webex.\n * @instance\n * @memberof User\n * @param {string} givenName\n * @param {string} familyName\n * @param {string} displayName\n * @returns {Promise<Object>}\n */\n updateName({givenName, familyName, displayName} = {}) {\n if (!(givenName || familyName || displayName)) {\n return Promise.reject(\n new Error('One of `givenName` and `familyName` or `displayName` is required')\n );\n }\n\n return this._setUser({\n schemas: ['urn:scim:schemas:core:1.0', 'urn:scim:schemas:extension:cisco:commonidentity:1.0'],\n name: {givenName, familyName},\n displayName,\n }).then((res) => res.body);\n },\n\n /**\n * Updates the current user's display name\n * @param {Object} options\n * @param {string} options.displayName\n * @returns {Promise<Object>}\n */\n update(options) {\n options = options || {};\n if (!options.displayName) {\n return Promise.reject(new Error('`options.displayName` is required'));\n }\n\n return this.request({\n method: 'PATCH',\n service: 'conversation',\n resource: 'users/user',\n body: options,\n }).then((res) => res.body);\n },\n\n /**\n * Validated One Time Password.\n * @instance\n * @param {Object} options\n * @param {string} options.email\n * @param {string} options.id\n * @param {string} options.oneTimePassword\n * @returns {Promise}\n */\n validateOTP(options = {}) {\n if (!(options.email || options.id) || !options.oneTimePassword) {\n return Promise.reject(\n new Error(\n 'One of `options.email` or `options.id` and `options.oneTimePassword` are required'\n )\n );\n }\n\n options.scope = this.webex.config.credentials.scope;\n\n return this.request({\n uri: this.webex.config.credentials.validateOtpUrl,\n method: 'POST',\n body: options,\n auth: {\n user: this.webex.config.credentials.client_id,\n pass: this.webex.config.credentials.client_secret,\n },\n }).then((res) => {\n this.webex.credentials.set({supertoken: res.body.tokenData});\n\n return res.body;\n });\n },\n\n /**\n * Determines if the specified user needs to signup or can signin.\n * Triggers activation email if client credentials are used\n * @param {Object} options\n * @param {string} options.email (required)\n * @param {string} options.reqId required if need to check email status\n * @param {string} options.preloginId\n * @returns {Promise<Object>}\n */\n verify(options) {\n options = {...this.config.verifyDefaults, ...options};\n const {email} = options;\n\n if (!email) {\n return Promise.reject(new Error('`options.email` is required'));\n }\n\n return this.webex.internal.services\n .collectPreauthCatalog({email})\n .then(() => this.webex.credentials.getUserToken())\n .catch(() => this.webex.credentials.getClientToken())\n .then((token) =>\n this.request({\n service: 'atlas',\n resource: 'users/activations',\n method: 'POST',\n headers: {\n authorization: token.toString(),\n 'x-prelogin-userid': options.preloginId,\n },\n body: options,\n shouldRefreshAccessToken: false,\n })\n )\n .then((res) => {\n if (res.body.hasPassword || res.body.sso) {\n this.hasPassword = true;\n }\n\n return res.body;\n });\n },\n\n /**\n * If the passed-in lookupCI is true, retrieve the user's\n * CI from Atlas and return the URL's via a Promise.\n * Otherwise, return current CI in config via a Promise.\n * Useful in a Promise chain to retrieve the CI based on\n * conditions like Federation enabled, and suppresses sending\n * an additional email to the user, since this is just a\n * look-up.\n * @param {string} email (required)\n * @param {boolean} lookupCI (required)\n * @returns {Promise<Object>}\n */\n getUserCI(email, lookupCI) {\n if (lookupCI) {\n // call verify first to get the user's CI, but suppress sending another email\n const verifyOptions = {\n email,\n suppressEmail: true,\n };\n\n return this.verify(verifyOptions).then((res) => Promise.resolve(res.userEntities));\n }\n\n return Promise.resolve({\n idBrokerUrl: this.webex.config.credentials.idbroker.url,\n identityUrl: this.webex.config.credentials.identity.url,\n });\n },\n\n /**\n * Extracts the uuid from a user identifying object\n * @param {string|Object} user\n * @private\n * @returns {string}\n */\n _extractUUID(user) {\n return user.entryUUID || user.id || user;\n },\n\n /**\n * Extracts the email address from a user identifying object\n * @param {string|Object} user\n * @private\n * @returns {string}\n */\n _extractEmailAddress(user) {\n return user.email || user.emailAddress || user.entryEmail || user;\n },\n});\n\nexport default User;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_lodash","require","_common","_webexCore","_userUuidBatcher","_interopRequireDefault","_userUuidStore","_dec","_dec2","_dec3","_dec4","_obj","ownKeys","e","r","t","_Object$keys","_Object$getOwnPropertySymbols","o","filter","_Object$getOwnPropertyDescriptor2","enumerable","push","apply","_objectSpread","arguments","length","Object","forEach","_defineProperty2","default","_Object$getOwnPropertyDescriptors","_Object$defineProperties","_Object$defineProperty","SCIM_SCHEMAS","exports","buildPreferredSiteBody","newSiteUrl","oldSiteUrl","userPreferences","operation","value","concat","schemas","buildMeetingSiteList","user","linked","linkedTrainSiteNames","train","trainSiteNames","_toConsumableArray2","_set","site","indexOf","sort","User","WebexPlugin","extend","waitForValue","oneFlight","keyFactory","email","options","String","create","persist","deprecated","namespace","children","batcher","UserUUIDBatcher","props","hasPassword","type","session","store","UserUUIDStore","activate","_this","undefined","verificationToken","confirmationCode","id","_promise","reject","Error","scope","webex","config","credentials","activateOptions","request","uri","activationUrl","method","body","auth","client_id","pass","client_secret","sendImmediately","then","res","set","supertoken","tokenData","asUUID","_this2","isArray","all","map","u","_extractUUID","force","patterns","uuid","test","resolve","_extractEmailAddress","getUUID","fetchUUID","_this3","recordUUID","emailAddress","generateOTP","generateOtpUrl","get","_this4","service","resource","tap","_this5","getByEmail","userExists","catch","initialize","_len","args","Array","_key","_apply","prototype","add","register","verify","_setUser","_this6","getUserToken","token","setPasswordUrl","internal","device","userId","headers","authorization","toString","setPassword","_this7","password","updateName","_ref","givenName","familyName","displayName","name","updatePreferredWebexSite","_ref2","orgId","resolvedOrgId","getOrgId","identityUrl","identity","url","error","getMeetingSiteList","update","validateOTP","_this8","oneTimePassword","validateOtpUrl","_this9","verifyDefaults","_options","services","collectPreauthCatalog","getClientToken","preloginId","shouldRefreshAccessToken","sso","getUserCI","lookupCI","verifyOptions","suppressEmail","userEntities","idBrokerUrl","idbroker","entryUUID","entryEmail","version","_applyDecoratedDescriptor2","_getOwnPropertyDescriptor","_default2"],"sources":["user.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {isArray} from 'lodash';\nimport {deprecated, oneFlight, patterns, tap} from '@webex/common';\nimport {persist, WebexPlugin, waitForValue} from '@webex/webex-core';\n\nimport UserUUIDBatcher from './user-uuid-batcher';\nimport UserUUIDStore from './user-uuid-store';\n\nconst SCIM_SCHEMAS = [\n 'urn:scim:schemas:core:1.0',\n 'urn:scim:schemas:extension:cisco:commonidentity:1.0',\n];\n\n/**\n * Builds a SCIM PATCH body for updating the user's preferred Webex site.\n * Matches the native client's SCIM format: delete old + add new in a single PATCH.\n * @param {string} newSiteUrl - The new preferred site\n * @param {string} [oldSiteUrl] - The previous preferred site to remove\n * @returns {Object} SCIM-formatted request body\n */\nfunction buildPreferredSiteBody(newSiteUrl, oldSiteUrl) {\n const userPreferences = [];\n\n if (oldSiteUrl) {\n userPreferences.push({\n operation: 'delete',\n value: `\"preferredWebExSite\":\"${oldSiteUrl}\"`,\n });\n }\n\n userPreferences.push({\n value: `\"preferredWebExSite\":\"${newSiteUrl}\"`,\n });\n\n return {schemas: SCIM_SCHEMAS, userPreferences};\n}\n\n/**\n * Builds a deduplicated, sorted list of meeting sites from a user profile.\n * Merges linkedTrainSiteNames and trainSiteNames, filters out attendee-only\n * sites (those containing '#'), and sorts alphabetically.\n * Matches the native client's site list filtering logic.\n * @param {Object} user - User profile object\n * @param {string[]} [user.linkedTrainSiteNames] - Linked training site names\n * @param {string[]} [user.trainSiteNames] - Training site names\n * @returns {string[]} Sorted array of site URLs\n */\nfunction buildMeetingSiteList(user) {\n const linked = (user && user.linkedTrainSiteNames) || [];\n const train = (user && user.trainSiteNames) || [];\n\n return [...new Set(linked.concat(train))].filter((site) => site.indexOf('#') === -1).sort();\n}\n\n/**\n * @class\n */\nconst User = WebexPlugin.extend({\n namespace: 'User',\n\n children: {\n batcher: UserUUIDBatcher,\n },\n\n props: {\n /**\n * Indicates if the current user is known to have a password.\n * @instance\n * @memberof User\n * @type {boolean}\n */\n hasPassword: {\n default: false,\n type: 'boolean',\n },\n },\n\n session: {\n store: {\n default() {\n return new UserUUIDStore();\n },\n type: 'any',\n },\n },\n\n @waitForValue('@')\n /**\n * Activates a Webex user account and exchanges for user token.\n * @instance\n * @memberof User\n * @param {Object} options\n * @param {Object} options.confirmationCode (required -- optional if verification token is provided)\n * @param {Object} options.id (required -- optional if verification token is provided)\n * @param {Object} options.verificationToken (required -- optional if uuid and verification token provided)\n * @param {Object} options.email (required with verificationToken for Federation/global user)\n * @returns {Promise} Resolves with a userSession\n */\n activate(options = {}) {\n if (!(options.verificationToken || (options.confirmationCode && options.id))) {\n return Promise.reject(\n new Error(\n 'either options.verificationToken is required or both options.confirmationCode and options.id are required'\n )\n );\n }\n\n options.scope = this.webex.config.credentials.scope;\n\n // if we have options.email and options.verificationToken\n // and Federation flag is enabled, flag that we need to\n // lookup user's CI.\n const activateOptions = {...options};\n\n delete activateOptions.email;\n\n return this.request({\n uri: this.webex.config.credentials.activationUrl,\n method: 'POST',\n body: activateOptions,\n auth: {\n user: this.webex.config.credentials.client_id,\n pass: this.webex.config.credentials.client_secret,\n sendImmediately: true,\n },\n }).then((res) => {\n this.webex.credentials.set({supertoken: res.body.tokenData});\n\n return res.body;\n });\n },\n\n /**\n * Converts a user-identifying object to a uuid, perhaps by doing a network\n * lookup\n * @param {string|Object} user\n * @param {Object} options\n * @param {boolean} options.create if true, ensures the return UUID refers to\n * an existing user (rather than creating one deterministically based on email\n * address), even if that user must be created\n * @returns {Promise<string>}\n */\n asUUID(user, options) {\n if (!user) {\n return Promise.reject(new Error('`user` is required'));\n }\n\n if (isArray(user)) {\n return Promise.all(user.map((u) => this.asUUID(u, options)));\n }\n\n const id = this._extractUUID(user);\n\n if (!(options && options.force) && patterns.uuid.test(id)) {\n return Promise.resolve(id);\n }\n\n const email = this._extractEmailAddress(user);\n\n if (!patterns.email.test(email)) {\n return Promise.reject(new Error('Provided user object does not appear to identify a user'));\n }\n\n return this.getUUID(email, options);\n },\n\n /**\n * Requests a uuid from the api\n * @param {string} email\n * @param {Object} options\n * @param {boolean} options.create\n * @returns {Promise<string>}\n */\n fetchUUID(email, options) {\n return this.batcher\n .request({\n email,\n create: options && options.create,\n })\n .then((user) => this.recordUUID({emailAddress: email, ...user}).then(() => user.id));\n },\n /**\n * Generates One Time Password.\n * @instance\n * @param {Object} options\n * @param {string} options.email\n * @param {string} options.id\n * @returns {Promise}\n */\n generateOTP(options = {}) {\n if (!(options.email || options.id)) {\n return Promise.reject(new Error('One of `options.email` or `options.id` is required'));\n }\n\n return this.request({\n uri: this.webex.config.credentials.generateOtpUrl,\n method: 'POST',\n body: options,\n auth: {\n user: this.webex.config.credentials.client_id,\n pass: this.webex.config.credentials.client_secret,\n },\n }).then((res) => res.body);\n },\n\n /**\n * Fetches details about the current user\n * @returns {Promise<Object>}\n */\n get() {\n return this.request({\n service: 'conversation',\n resource: 'users',\n })\n .then((res) => res.body)\n .then(\n tap((user) =>\n this.recordUUID({\n id: user.id,\n // CI endpoints don't use the same user format as actors, so, email may\n // be in one of a few fields\n emailAddress: user.email || user.emailAddress,\n })\n )\n );\n },\n\n /**\n * Converts an email address to a uuid, perhaps by doing a network lookup\n * @param {string} email\n * @param {Object} options\n * @param {boolean} options.create\n * @returns {Promise<string>}\n */\n @oneFlight({keyFactory: (email, options) => email + String(options && options.create)})\n getUUID(email, options) {\n return this.store\n .getByEmail(email)\n .then((user) => {\n if (options && options.create && !user.userExists) {\n return Promise.reject(new Error('User for specified email cannot be confirmed to exist'));\n }\n\n if (!user.id) {\n return Promise.reject(new Error('No id recorded for specified user'));\n }\n\n return user.id;\n })\n .catch(() => this.fetchUUID(email, options));\n },\n\n @persist('@')\n initialize(...args) {\n return Reflect.apply(WebexPlugin.prototype.initialize, this, args);\n },\n\n /**\n * Caches the uuid for the specified email address\n * @param {Object} user\n * @param {string} user.id\n * @param {string} user.emailAddress\n * @returns {Promise}\n */\n recordUUID(user) {\n if (!user) {\n return Promise.reject(new Error('`user` is required'));\n }\n\n if (!user.id) {\n return Promise.reject(new Error('`user.id` is required'));\n }\n\n if (!patterns.uuid.test(user.id)) {\n return Promise.reject(new Error('`user.id` must be a uuid'));\n }\n\n if (!user.emailAddress) {\n return Promise.reject(new Error('`user.emailAddress` is required'));\n }\n\n if (!patterns.email.test(user.emailAddress)) {\n return Promise.reject(new Error('`user.emailAddress` must be an email address'));\n }\n\n return this.store.add(user);\n },\n\n @deprecated('Use User#verify()')\n register(...args) {\n return this.verify(...args);\n },\n\n /**\n * Updates a user with webex.\n * @param {Object} body\n * @private\n * @returns {Promise} Resolves with a response from PATCH request\n */\n _setUser(body) {\n return this.webex.credentials.getUserToken().then((token) =>\n this.request({\n uri: `${this.webex.config.credentials.setPasswordUrl}/${this.webex.internal.device.userId}`,\n method: 'PATCH',\n headers: {\n authorization: token.toString(),\n },\n body,\n })\n );\n },\n\n /**\n * Updates a user's password with webex.\n * @instance\n * @memberof User\n * @param {Object} options\n * @param {string} options.password (required)\n * @param {string} options.email (required when federation enabled)\n * @returns {Promise} Resolves with complete user object containing new password\n */\n setPassword(options) {\n options = options || {};\n if (!options.password) {\n return Promise.reject(new Error('`options.password` is required'));\n }\n\n return this._setUser({\n schemas: ['urn:scim:schemas:core:1.0', 'urn:scim:schemas:extension:cisco:commonidentity:1.0'],\n password: options.password,\n }).then((res) => {\n this.hasPassword = true;\n\n return res.body;\n });\n },\n\n /**\n * Updates a user's name with webex.\n * @instance\n * @memberof User\n * @param {string} givenName\n * @param {string} familyName\n * @param {string} displayName\n * @returns {Promise<Object>}\n */\n updateName({givenName, familyName, displayName} = {}) {\n if (!(givenName || familyName || displayName)) {\n return Promise.reject(\n new Error('One of `givenName` and `familyName` or `displayName` is required')\n );\n }\n\n return this._setUser({\n schemas: ['urn:scim:schemas:core:1.0', 'urn:scim:schemas:extension:cisco:commonidentity:1.0'],\n name: {givenName, familyName},\n displayName,\n }).then((res) => res.body);\n },\n\n /**\n * Updates the user's preferred Webex meeting site via org-scoped SCIM PATCH.\n * @instance\n * @memberof User\n * @param {Object} options\n * @param {string} options.newSiteUrl - The new preferred site (e.g., 'example.webex.com')\n * @param {string} [options.oldSiteUrl] - The previous preferred site to remove\n * @param {string} [options.orgId] - Organization ID. If not provided, extracted from credentials.\n * @returns {Promise<Object>} Resolves with the SCIM response body\n */\n updatePreferredWebexSite({newSiteUrl, oldSiteUrl, orgId} = {}) {\n if (!newSiteUrl) {\n return Promise.reject(new Error('`options.newSiteUrl` is required'));\n }\n\n try {\n const resolvedOrgId = orgId || this.webex.credentials.getOrgId();\n const {userId} = this.webex.internal.device;\n\n if (!userId) {\n return Promise.reject(\n new Error('device.userId is not available — ensure device.register() has completed')\n );\n }\n\n const {url: identityUrl} = this.webex.config.credentials.identity;\n\n return this.request({\n uri: `${identityUrl}/identity/scim/${resolvedOrgId}/v1/Users/${userId}`,\n method: 'PATCH',\n body: buildPreferredSiteBody(newSiteUrl, oldSiteUrl),\n }).then((res) => res.body);\n } catch (error) {\n return Promise.reject(error);\n }\n },\n\n /**\n * Returns a sorted, filtered list of meeting sites from a user profile.\n * Delegates to the pure buildMeetingSiteList function.\n * @instance\n * @memberof User\n * @param {Object} user - User profile object from webex.internal.user.get()\n * @returns {string[]} Sorted array of site URLs\n */\n getMeetingSiteList(user) {\n return buildMeetingSiteList(user);\n },\n\n /**\n * Updates the current user's display name\n * @param {Object} options\n * @param {string} options.displayName\n * @returns {Promise<Object>}\n */\n update(options) {\n options = options || {};\n if (!options.displayName) {\n return Promise.reject(new Error('`options.displayName` is required'));\n }\n\n return this.request({\n method: 'PATCH',\n service: 'conversation',\n resource: 'users/user',\n body: options,\n }).then((res) => res.body);\n },\n\n /**\n * Validated One Time Password.\n * @instance\n * @param {Object} options\n * @param {string} options.email\n * @param {string} options.id\n * @param {string} options.oneTimePassword\n * @returns {Promise}\n */\n validateOTP(options = {}) {\n if (!(options.email || options.id) || !options.oneTimePassword) {\n return Promise.reject(\n new Error(\n 'One of `options.email` or `options.id` and `options.oneTimePassword` are required'\n )\n );\n }\n\n options.scope = this.webex.config.credentials.scope;\n\n return this.request({\n uri: this.webex.config.credentials.validateOtpUrl,\n method: 'POST',\n body: options,\n auth: {\n user: this.webex.config.credentials.client_id,\n pass: this.webex.config.credentials.client_secret,\n },\n }).then((res) => {\n this.webex.credentials.set({supertoken: res.body.tokenData});\n\n return res.body;\n });\n },\n\n /**\n * Determines if the specified user needs to signup or can signin.\n * Triggers activation email if client credentials are used\n * @param {Object} options\n * @param {string} options.email (required)\n * @param {string} options.reqId required if need to check email status\n * @param {string} options.preloginId\n * @returns {Promise<Object>}\n */\n verify(options) {\n options = {...this.config.verifyDefaults, ...options};\n const {email} = options;\n\n if (!email) {\n return Promise.reject(new Error('`options.email` is required'));\n }\n\n return this.webex.internal.services\n .collectPreauthCatalog({email})\n .then(() => this.webex.credentials.getUserToken())\n .catch(() => this.webex.credentials.getClientToken())\n .then((token) =>\n this.request({\n service: 'atlas',\n resource: 'users/activations',\n method: 'POST',\n headers: {\n authorization: token.toString(),\n 'x-prelogin-userid': options.preloginId,\n },\n body: options,\n shouldRefreshAccessToken: false,\n })\n )\n .then((res) => {\n if (res.body.hasPassword || res.body.sso) {\n this.hasPassword = true;\n }\n\n return res.body;\n });\n },\n\n /**\n * If the passed-in lookupCI is true, retrieve the user's\n * CI from Atlas and return the URL's via a Promise.\n * Otherwise, return current CI in config via a Promise.\n * Useful in a Promise chain to retrieve the CI based on\n * conditions like Federation enabled, and suppresses sending\n * an additional email to the user, since this is just a\n * look-up.\n * @param {string} email (required)\n * @param {boolean} lookupCI (required)\n * @returns {Promise<Object>}\n */\n getUserCI(email, lookupCI) {\n if (lookupCI) {\n // call verify first to get the user's CI, but suppress sending another email\n const verifyOptions = {\n email,\n suppressEmail: true,\n };\n\n return this.verify(verifyOptions).then((res) => Promise.resolve(res.userEntities));\n }\n\n return Promise.resolve({\n idBrokerUrl: this.webex.config.credentials.idbroker.url,\n identityUrl: this.webex.config.credentials.identity.url,\n });\n },\n\n /**\n * Extracts the uuid from a user identifying object\n * @param {string|Object} user\n * @private\n * @returns {string}\n */\n _extractUUID(user) {\n return user.entryUUID || user.id || user;\n },\n\n /**\n * Extracts the email address from a user identifying object\n * @param {string|Object} user\n * @private\n * @returns {string}\n */\n _extractEmailAddress(user) {\n return user.email || user.emailAddress || user.entryEmail || user;\n },\n});\n\nexport default User;\nexport {buildPreferredSiteBody, buildMeetingSiteList, SCIM_SCHEMAS};\n"],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -24,21 +24,21 @@
|
|
|
24
24
|
"@webex/eslint-config-legacy": "0.0.0",
|
|
25
25
|
"@webex/jest-config-legacy": "0.0.0",
|
|
26
26
|
"@webex/legacy-tools": "0.0.0",
|
|
27
|
-
"@webex/test-helper-chai": "3.
|
|
28
|
-
"@webex/test-helper-mocha": "3.
|
|
29
|
-
"@webex/test-helper-mock-webex": "3.
|
|
30
|
-
"@webex/test-helper-test-users": "3.
|
|
27
|
+
"@webex/test-helper-chai": "3.11.0-next.1",
|
|
28
|
+
"@webex/test-helper-mocha": "3.11.0-next.1",
|
|
29
|
+
"@webex/test-helper-mock-webex": "3.11.0-next.1",
|
|
30
|
+
"@webex/test-helper-test-users": "3.11.0-next.1",
|
|
31
31
|
"eslint": "^8.24.0",
|
|
32
32
|
"prettier": "^2.7.1",
|
|
33
33
|
"sinon": "^9.2.4"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@webex/common": "3.
|
|
37
|
-
"@webex/internal-plugin-device": "3.12.0-
|
|
38
|
-
"@webex/test-helper-chai": "3.
|
|
39
|
-
"@webex/test-helper-mock-webex": "3.
|
|
40
|
-
"@webex/test-helper-test-users": "3.
|
|
41
|
-
"@webex/webex-core": "3.12.0-
|
|
36
|
+
"@webex/common": "3.11.0-next.1",
|
|
37
|
+
"@webex/internal-plugin-device": "3.12.0-next.9",
|
|
38
|
+
"@webex/test-helper-chai": "3.11.0-next.1",
|
|
39
|
+
"@webex/test-helper-mock-webex": "3.11.0-next.1",
|
|
40
|
+
"@webex/test-helper-test-users": "3.11.0-next.1",
|
|
41
|
+
"@webex/webex-core": "3.12.0-next.9",
|
|
42
42
|
"lodash": "^4.17.21",
|
|
43
43
|
"uuid": "^3.3.2"
|
|
44
44
|
},
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"test:style": "eslint ./src/**/*.*",
|
|
52
52
|
"test:unit": "webex-legacy-tools test --unit --runner jest"
|
|
53
53
|
},
|
|
54
|
-
"version": "3.12.0-
|
|
54
|
+
"version": "3.12.0-next.10"
|
|
55
55
|
}
|
package/src/user.js
CHANGED
|
@@ -9,6 +9,52 @@ import {persist, WebexPlugin, waitForValue} from '@webex/webex-core';
|
|
|
9
9
|
import UserUUIDBatcher from './user-uuid-batcher';
|
|
10
10
|
import UserUUIDStore from './user-uuid-store';
|
|
11
11
|
|
|
12
|
+
const SCIM_SCHEMAS = [
|
|
13
|
+
'urn:scim:schemas:core:1.0',
|
|
14
|
+
'urn:scim:schemas:extension:cisco:commonidentity:1.0',
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Builds a SCIM PATCH body for updating the user's preferred Webex site.
|
|
19
|
+
* Matches the native client's SCIM format: delete old + add new in a single PATCH.
|
|
20
|
+
* @param {string} newSiteUrl - The new preferred site
|
|
21
|
+
* @param {string} [oldSiteUrl] - The previous preferred site to remove
|
|
22
|
+
* @returns {Object} SCIM-formatted request body
|
|
23
|
+
*/
|
|
24
|
+
function buildPreferredSiteBody(newSiteUrl, oldSiteUrl) {
|
|
25
|
+
const userPreferences = [];
|
|
26
|
+
|
|
27
|
+
if (oldSiteUrl) {
|
|
28
|
+
userPreferences.push({
|
|
29
|
+
operation: 'delete',
|
|
30
|
+
value: `"preferredWebExSite":"${oldSiteUrl}"`,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
userPreferences.push({
|
|
35
|
+
value: `"preferredWebExSite":"${newSiteUrl}"`,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return {schemas: SCIM_SCHEMAS, userPreferences};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Builds a deduplicated, sorted list of meeting sites from a user profile.
|
|
43
|
+
* Merges linkedTrainSiteNames and trainSiteNames, filters out attendee-only
|
|
44
|
+
* sites (those containing '#'), and sorts alphabetically.
|
|
45
|
+
* Matches the native client's site list filtering logic.
|
|
46
|
+
* @param {Object} user - User profile object
|
|
47
|
+
* @param {string[]} [user.linkedTrainSiteNames] - Linked training site names
|
|
48
|
+
* @param {string[]} [user.trainSiteNames] - Training site names
|
|
49
|
+
* @returns {string[]} Sorted array of site URLs
|
|
50
|
+
*/
|
|
51
|
+
function buildMeetingSiteList(user) {
|
|
52
|
+
const linked = (user && user.linkedTrainSiteNames) || [];
|
|
53
|
+
const train = (user && user.trainSiteNames) || [];
|
|
54
|
+
|
|
55
|
+
return [...new Set(linked.concat(train))].filter((site) => site.indexOf('#') === -1).sort();
|
|
56
|
+
}
|
|
57
|
+
|
|
12
58
|
/**
|
|
13
59
|
* @class
|
|
14
60
|
*/
|
|
@@ -315,6 +361,55 @@ const User = WebexPlugin.extend({
|
|
|
315
361
|
}).then((res) => res.body);
|
|
316
362
|
},
|
|
317
363
|
|
|
364
|
+
/**
|
|
365
|
+
* Updates the user's preferred Webex meeting site via org-scoped SCIM PATCH.
|
|
366
|
+
* @instance
|
|
367
|
+
* @memberof User
|
|
368
|
+
* @param {Object} options
|
|
369
|
+
* @param {string} options.newSiteUrl - The new preferred site (e.g., 'example.webex.com')
|
|
370
|
+
* @param {string} [options.oldSiteUrl] - The previous preferred site to remove
|
|
371
|
+
* @param {string} [options.orgId] - Organization ID. If not provided, extracted from credentials.
|
|
372
|
+
* @returns {Promise<Object>} Resolves with the SCIM response body
|
|
373
|
+
*/
|
|
374
|
+
updatePreferredWebexSite({newSiteUrl, oldSiteUrl, orgId} = {}) {
|
|
375
|
+
if (!newSiteUrl) {
|
|
376
|
+
return Promise.reject(new Error('`options.newSiteUrl` is required'));
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
try {
|
|
380
|
+
const resolvedOrgId = orgId || this.webex.credentials.getOrgId();
|
|
381
|
+
const {userId} = this.webex.internal.device;
|
|
382
|
+
|
|
383
|
+
if (!userId) {
|
|
384
|
+
return Promise.reject(
|
|
385
|
+
new Error('device.userId is not available — ensure device.register() has completed')
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const {url: identityUrl} = this.webex.config.credentials.identity;
|
|
390
|
+
|
|
391
|
+
return this.request({
|
|
392
|
+
uri: `${identityUrl}/identity/scim/${resolvedOrgId}/v1/Users/${userId}`,
|
|
393
|
+
method: 'PATCH',
|
|
394
|
+
body: buildPreferredSiteBody(newSiteUrl, oldSiteUrl),
|
|
395
|
+
}).then((res) => res.body);
|
|
396
|
+
} catch (error) {
|
|
397
|
+
return Promise.reject(error);
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Returns a sorted, filtered list of meeting sites from a user profile.
|
|
403
|
+
* Delegates to the pure buildMeetingSiteList function.
|
|
404
|
+
* @instance
|
|
405
|
+
* @memberof User
|
|
406
|
+
* @param {Object} user - User profile object from webex.internal.user.get()
|
|
407
|
+
* @returns {string[]} Sorted array of site URLs
|
|
408
|
+
*/
|
|
409
|
+
getMeetingSiteList(user) {
|
|
410
|
+
return buildMeetingSiteList(user);
|
|
411
|
+
},
|
|
412
|
+
|
|
318
413
|
/**
|
|
319
414
|
* Updates the current user's display name
|
|
320
415
|
* @param {Object} options
|
|
@@ -464,3 +559,4 @@ const User = WebexPlugin.extend({
|
|
|
464
559
|
});
|
|
465
560
|
|
|
466
561
|
export default User;
|
|
562
|
+
export {buildPreferredSiteBody, buildMeetingSiteList, SCIM_SCHEMAS};
|
package/test/unit/spec/user.js
CHANGED
|
@@ -3,12 +3,90 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import UserService from '@webex/internal-plugin-user';
|
|
6
|
+
import {buildPreferredSiteBody, buildMeetingSiteList, SCIM_SCHEMAS} from '@webex/internal-plugin-user/src/user';
|
|
6
7
|
import {assert} from '@webex/test-helper-chai';
|
|
7
8
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
8
9
|
import sinon from 'sinon';
|
|
9
10
|
import uuid from 'uuid';
|
|
10
11
|
|
|
11
12
|
describe('plugin-user', () => {
|
|
13
|
+
describe('buildPreferredSiteBody()', () => {
|
|
14
|
+
it('returns SCIM schemas in the body', () => {
|
|
15
|
+
const body = buildPreferredSiteBody('new.webex.com');
|
|
16
|
+
|
|
17
|
+
assert.deepEqual(body.schemas, SCIM_SCHEMAS);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('builds add-only body when no oldSiteUrl', () => {
|
|
21
|
+
const body = buildPreferredSiteBody('new.webex.com');
|
|
22
|
+
|
|
23
|
+
assert.deepEqual(body.userPreferences, [
|
|
24
|
+
{value: '"preferredWebExSite":"new.webex.com"'},
|
|
25
|
+
]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('builds delete+add body when oldSiteUrl provided', () => {
|
|
29
|
+
const body = buildPreferredSiteBody('new.webex.com', 'old.webex.com');
|
|
30
|
+
|
|
31
|
+
assert.deepEqual(body.userPreferences, [
|
|
32
|
+
{operation: 'delete', value: '"preferredWebExSite":"old.webex.com"'},
|
|
33
|
+
{value: '"preferredWebExSite":"new.webex.com"'},
|
|
34
|
+
]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('embeds site URLs in the SCIM string format', () => {
|
|
38
|
+
const body = buildPreferredSiteBody('my-site.webex.com');
|
|
39
|
+
|
|
40
|
+
assert.equal(body.userPreferences[0].value, '"preferredWebExSite":"my-site.webex.com"');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('buildMeetingSiteList()', () => {
|
|
45
|
+
it('returns empty array for null/undefined/empty user', () => {
|
|
46
|
+
assert.deepEqual(buildMeetingSiteList(null), []);
|
|
47
|
+
assert.deepEqual(buildMeetingSiteList(undefined), []);
|
|
48
|
+
assert.deepEqual(buildMeetingSiteList({}), []);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('merges linked + train sites and sorts alphabetically', () => {
|
|
52
|
+
const result = buildMeetingSiteList({
|
|
53
|
+
linkedTrainSiteNames: ['charlie.webex.com', 'alpha.webex.com'],
|
|
54
|
+
trainSiteNames: ['bravo.webex.com'],
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
assert.deepEqual(result, ['alpha.webex.com', 'bravo.webex.com', 'charlie.webex.com']);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('filters out attendee-only sites containing #', () => {
|
|
61
|
+
const result = buildMeetingSiteList({
|
|
62
|
+
trainSiteNames: ['good.webex.com', 'attendee#only.webex.com', 'also-good.webex.com'],
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
assert.deepEqual(result, ['also-good.webex.com', 'good.webex.com']);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('handles missing linkedTrainSiteNames gracefully', () => {
|
|
69
|
+
const result = buildMeetingSiteList({trainSiteNames: ['only.webex.com']});
|
|
70
|
+
|
|
71
|
+
assert.deepEqual(result, ['only.webex.com']);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('handles missing trainSiteNames gracefully', () => {
|
|
75
|
+
const result = buildMeetingSiteList({linkedTrainSiteNames: ['only.webex.com']});
|
|
76
|
+
|
|
77
|
+
assert.deepEqual(result, ['only.webex.com']);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('deduplicates sites appearing in both arrays', () => {
|
|
81
|
+
const result = buildMeetingSiteList({
|
|
82
|
+
linkedTrainSiteNames: ['shared.webex.com', 'alpha.webex.com'],
|
|
83
|
+
trainSiteNames: ['shared.webex.com', 'bravo.webex.com'],
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
assert.deepEqual(result, ['alpha.webex.com', 'bravo.webex.com', 'shared.webex.com']);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
12
90
|
describe('User', () => {
|
|
13
91
|
let webex, userService;
|
|
14
92
|
|
|
@@ -147,6 +225,121 @@ describe('plugin-user', () => {
|
|
|
147
225
|
));
|
|
148
226
|
});
|
|
149
227
|
|
|
228
|
+
describe('#updatePreferredWebexSite()', () => {
|
|
229
|
+
const testUserId = 'test-user-id-1234';
|
|
230
|
+
const testOrgId = 'test-org-id-5678';
|
|
231
|
+
|
|
232
|
+
beforeEach(() => {
|
|
233
|
+
webex.internal.device.userId = testUserId;
|
|
234
|
+
webex.credentials.getOrgId = sinon.stub().returns(testOrgId);
|
|
235
|
+
webex.config.credentials.identity = {url: 'https://identity.webex.com'};
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('rejects when `newSiteUrl` is not provided', () =>
|
|
239
|
+
assert.isRejected(
|
|
240
|
+
userService.updatePreferredWebexSite({}),
|
|
241
|
+
/`options.newSiteUrl` is required/
|
|
242
|
+
));
|
|
243
|
+
|
|
244
|
+
it('rejects when getOrgId throws and none provided', () => {
|
|
245
|
+
webex.credentials.getOrgId = sinon.stub().throws(new Error('no org'));
|
|
246
|
+
|
|
247
|
+
return assert.isRejected(
|
|
248
|
+
userService.updatePreferredWebexSite({newSiteUrl: 'new.webex.com'}),
|
|
249
|
+
/no org/
|
|
250
|
+
);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('rejects when device.userId is not available', () => {
|
|
254
|
+
webex.internal.device.userId = undefined;
|
|
255
|
+
|
|
256
|
+
return assert.isRejected(
|
|
257
|
+
userService.updatePreferredWebexSite({newSiteUrl: 'new.webex.com'}),
|
|
258
|
+
/device\.userId is not available/
|
|
259
|
+
);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('uses provided orgId instead of extracting from credentials', () =>
|
|
263
|
+
userService
|
|
264
|
+
.updatePreferredWebexSite({newSiteUrl: 'new.webex.com', orgId: 'custom-org-9999'})
|
|
265
|
+
.then(() => {
|
|
266
|
+
assert.notCalled(webex.credentials.getOrgId);
|
|
267
|
+
const {uri} = webex.request.getCall(0).args[0];
|
|
268
|
+
|
|
269
|
+
assert.include(uri, '/identity/scim/custom-org-9999/v1/Users/');
|
|
270
|
+
}));
|
|
271
|
+
|
|
272
|
+
it('constructs org-scoped PATCH request with correct URL', () =>
|
|
273
|
+
userService
|
|
274
|
+
.updatePreferredWebexSite({newSiteUrl: 'new.webex.com'})
|
|
275
|
+
.then(() => {
|
|
276
|
+
const requestArgs = webex.request.getCall(0).args[0];
|
|
277
|
+
|
|
278
|
+
assert.equal(
|
|
279
|
+
requestArgs.uri,
|
|
280
|
+
`https://identity.webex.com/identity/scim/${testOrgId}/v1/Users/${testUserId}`
|
|
281
|
+
);
|
|
282
|
+
assert.equal(requestArgs.method, 'PATCH');
|
|
283
|
+
}));
|
|
284
|
+
|
|
285
|
+
it('does not manually set the authorization header (relies on auth interceptor)', () =>
|
|
286
|
+
userService
|
|
287
|
+
.updatePreferredWebexSite({newSiteUrl: 'new.webex.com'})
|
|
288
|
+
.then(() => {
|
|
289
|
+
const requestArgs = webex.request.getCall(0).args[0];
|
|
290
|
+
|
|
291
|
+
assert.notProperty(requestArgs, 'headers');
|
|
292
|
+
}));
|
|
293
|
+
|
|
294
|
+
it('passes buildPreferredSiteBody output as request body', () =>
|
|
295
|
+
userService
|
|
296
|
+
.updatePreferredWebexSite({newSiteUrl: 'new.webex.com', oldSiteUrl: 'old.webex.com'})
|
|
297
|
+
.then(() => {
|
|
298
|
+
const {body} = webex.request.getCall(0).args[0];
|
|
299
|
+
|
|
300
|
+
assert.deepEqual(body.schemas, SCIM_SCHEMAS);
|
|
301
|
+
assert.lengthOf(body.userPreferences, 2);
|
|
302
|
+
}));
|
|
303
|
+
|
|
304
|
+
it('returns the response body', () => {
|
|
305
|
+
const responseBody = {id: testUserId, preferredWebExSite: 'new.webex.com'};
|
|
306
|
+
|
|
307
|
+
userService.request = sinon.stub().returns(Promise.resolve({body: responseBody}));
|
|
308
|
+
|
|
309
|
+
return userService
|
|
310
|
+
.updatePreferredWebexSite({newSiteUrl: 'new.webex.com'})
|
|
311
|
+
.then((result) => {
|
|
312
|
+
assert.deepEqual(result, responseBody);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('propagates request errors', () => {
|
|
317
|
+
const error = new Error('Forbidden');
|
|
318
|
+
|
|
319
|
+
error.statusCode = 403;
|
|
320
|
+
userService.request = sinon.stub().callsFake(() => Promise.reject(error));
|
|
321
|
+
|
|
322
|
+
return assert.isRejected(
|
|
323
|
+
userService.updatePreferredWebexSite({newSiteUrl: 'new.webex.com'}),
|
|
324
|
+
/Forbidden/
|
|
325
|
+
);
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
describe('#getMeetingSiteList()', () => {
|
|
330
|
+
it('delegates to buildMeetingSiteList', () => {
|
|
331
|
+
const user = {
|
|
332
|
+
linkedTrainSiteNames: ['charlie.webex.com'],
|
|
333
|
+
trainSiteNames: ['alpha.webex.com'],
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
assert.deepEqual(
|
|
337
|
+
userService.getMeetingSiteList(user),
|
|
338
|
+
['alpha.webex.com', 'charlie.webex.com']
|
|
339
|
+
);
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
|
|
150
343
|
describe('#verify()', () => {
|
|
151
344
|
it('requires an `email` param', () =>
|
|
152
345
|
assert.isRejected(userService.verify(), /`options.email` is required/));
|