UNPKG

@c8y/client

Version:

Client application programming interface to access the Cumulocity IoT-Platform REST services.

599 lines • 21.2 kB
import { __awaiter } from "tslib"; import { Service } from '../core'; import { UserInventoryRoleService } from './UserInventoryRoleService'; /** * @description * This service allows for managing users. */ export class UserService extends Service { constructor() { super(...arguments); this.baseUrl = 'user'; this.currentUserUrl = 'currentUser'; this.passwordResetUrl = 'passwordReset'; this.currentUserPhoneUrl = 'currentUserPhone'; this.verifyTFACodeUrl = 'pin'; this.totpCurrentUserURL = `${this.currentUserUrl}/totpSecret`; this.verifyTOTPCodeUrl = `${this.totpCurrentUserURL}/verify`; this.activateTOTPCodeUrl = `${this.totpCurrentUserURL}/activity`; this.revokeTOTPSecretUrl = 'totpSecret/revoke'; this.propertyName = 'users'; } get listUrl() { return `${this.client.tenant}/users`; } get newsletterEmailsUrl() { return `${this.client.tenant}/users/newsletterEmails`; } get currentUserPasswordUrl() { return `${this.currentUserUrl}/password`; } get revokeAllTokensUrl() { return `/logout/${this.client.tenant}/allUsers`; } /** * Gets the details of given user. * * @param {string | number | IUser} entityOrId User's id or user object. * @param {object} params Additional query params. * * @returns Returns promise object that is resolved with the IUser wrapped by IResult. * * **Example** * ```typescript * * const userId: number = 1; * const params = { withCertificates: true }; * * (async () => { * const { data, res } = await userService.detail(userId, params); * })(); * ``` * User password is never returned in GET response. Authentication mechanism is provided by another interface. */ detail(entityOrId_1) { const _super = Object.create(null, { detail: { get: () => super.detail } }); return __awaiter(this, arguments, void 0, function* (entityOrId, params = {}) { return _super.detail.call(this, entityOrId, params); }); } /** * Creates a new user. * * @param {IUser} entity User object. * * @returns {IResult<IUser>} Returns promise object that is resolved with the details of newly created user. * * **Example** * ```typescript * * const userObject: IUser = { * userName: "newUser", * password: "userPassword12!@" * }; * * (async () => { * const {data, res} = await userService.create(userObject); * })(); * ``` */ create(entity) { const _super = Object.create(null, { create: { get: () => super.create } }); return __awaiter(this, void 0, void 0, function* () { return _super.create.call(this, entity); }); } /** * Updates user data. * * @param {Partial<IUser>} entity User is partially updatable. * * @returns {IResult<IUserGroup>} Returns promise object that is resolved with the saved user object. * * **Example** * ```typescript * * const partialUpdateObject: Partial<IUser> = { * "id" : "myuser", * "userName" : "newUserName", * "email": "newUserEmail@example.com" * ... * } * * (async () => { * const {data, res} = await userService.update(partialUpdateObject); * })(); * ``` * When user is updated with changed permissions or groups, suitable audit record is created with type * 'User' and activity 'User updated'. */ update(entity) { const _super = Object.create(null, { update: { get: () => super.update } }); return __awaiter(this, void 0, void 0, function* () { return _super.update.call(this, entity); }); } /** * Gets the list of users filtered by parameters. * * @param {object} filter Object containing filters for querying users. * * @returns Returns promise object that is resolved with the IUser wrapped by IResultList. * * **Example** * ```typescript * * const filter: object = { * pageSize: 100, * withTotalPages: true * }; * * (async () => { * const {data, res, paging} = await userService.list(filter); * })(); * ``` */ list() { const _super = Object.create(null, { list: { get: () => super.list } }); return __awaiter(this, arguments, void 0, function* (filter = {}) { return _super.list.call(this, filter); }); } /** * Removes user. * * @param {number|IIdentified} entityOrId User's id or user object. * * @returns Returns promise object that is resolved with the IResult of null. * * **Example** * ```typescript * * const userId: string = "uniqueUserId"; * * (async () => { * const {data, res} = await userService.delete(userGroupId); * })(); * ``` */ delete(entityOrId) { const _super = Object.create(null, { delete: { get: () => super.delete } }); return __awaiter(this, void 0, void 0, function* () { return _super.delete.call(this, entityOrId); }); } /** * Create instance of User Inventory Role Service related with given User. * * @param {string|number|IUser} entityOrId User's id or user object. * * @returns Returns UserInventoryRoleService object that is related with given User. * * **Example** * ```typescript * * const userId: string = "uniqueUserId"; * * const userInventoryRoleService = userService.inventoryAssignment(userGroupId); * (async () => { * const {data, res} = await userInventoryRoleService.create(...); * })(); * ``` */ inventoryAssignment(entityOrId) { return new UserInventoryRoleService(this.getDetailUrl(entityOrId), this.client); } /** * Gets user that is currently logged in. * * @returns Returns promise object that is resolved with the IUser wrapped by IResult. * * **Example** * ```typescript * * (async () => { * const {data, res} = await userService.current(); * })(); * ``` */ current() { return __awaiter(this, void 0, void 0, function* () { const headers = { 'content-type': 'application/json', Accept: 'application/vnd.com.nsn.cumulocity.user+json;' }; const res = yield this.fetch(this.currentUserUrl, { headers }); const data = yield res.json(); return { res, data }; }); } /** * Gets user that is currently logged in with the list of all roles assigned. * * @returns Returns promise object that is resolved with the ICurrenUser wrapped by IResult. * * **Example** * ```typescript * * (async () => { * const {data, res} = await userService.currentWithEffectiveRoles(); * })(); * ``` */ currentWithEffectiveRoles() { return __awaiter(this, void 0, void 0, function* () { const headers = { 'content-type': 'application/json', Accept: 'application/vnd.com.nsn.cumulocity.currentUser+json;' }; const res = yield this.fetch(this.currentUserUrl, { headers }); const data = yield res.json(); return { res, data }; }); } /** * Updates the current user * * @param {IUser} user The user object with the properties to be updated * * @return Returns promise object resolved with the IUser wrapped by IResult */ updateCurrent(user) { return __awaiter(this, void 0, void 0, function* () { const mimeType = 'application/vnd.com.nsn.cumulocity.user+json'; const headers = { 'content-type': mimeType, Accept: mimeType }; const body = JSON.stringify(this.onBeforeUpdate(user)); const res = yield this.fetch(this.currentUserUrl, { headers, body, method: 'PUT' }); const data = yield res.json(); return { res, data }; }); } /** * Sends an email message with a link allowing user to reset their password. * * @param {string} email The email address to send the message to. * @param {string} tenantId The id of user's tenant (if cannot be inferred from URL). * * @returns Returns a request result object. * * **Example** * ```typescript * const email = 'user@example.com'; * const tenantId = 't123456'; * * (async () => { * const { res, data } = await userService.sendPasswordResetMail(email, tenantId); * })(); * ``` */ sendPasswordResetMail(email, tenantId) { return __awaiter(this, void 0, void 0, function* () { const headers = { 'content-type': 'application/json', accept: 'application/json' }; const method = 'POST'; const url = this.passwordResetUrl; const params = tenantId ? { tenantId } : {}; const body = JSON.stringify({ email }); const res = yield this.fetch(url, { headers, method, params, body }); return { res, data: null }; }); } /** * Resets user's password to a new one. * * @param {IResetPassword} newPassword Object with token, user's email, new password and its strength indicator. * @param {string} tenantId The id of user's tenant (if cannot be inferred from URL). * * @returns Returns a request result object. * * **Example** * ```typescript * const newPassword: IResetPassword = { * token: '123123ASDAWERER@#!WEDS$@#!WADA#A#EA#EA#EA', * email: 'user@example.com', * newPassword: 'myNewPassword', * passwordStrength: PasswordStrength.GREEN * }; * const tenantId = 't123456'; * * (async () => { * const { res, data } = await userService.resetPassword(newPassword, tenantId); * })(); * ``` */ resetPassword(newPassword, tenantId) { return __awaiter(this, void 0, void 0, function* () { const headers = { 'content-type': 'application/json', accept: 'application/json' }; const method = 'PUT'; const url = this.passwordResetUrl; const params = tenantId ? { tenantId } : {}; const body = JSON.stringify(newPassword); const res = yield this.fetch(url, { headers, method, params, body }); return { res, data: null }; }); } /** * Verifies TFA code which is sent via SMS. If invoked with string '0', new TFA code will be sent. * * @param {string} pin The code to verify. * * @returns Returns a status object. * * **Example** * ```typescript * * (async () => { * const {data, res} = await userService.verifyTFACode('123123'); * })(); * ``` */ verifyTFACode(pin) { return __awaiter(this, void 0, void 0, function* () { const method = 'POST'; const body = JSON.stringify({ pin }); const headers = { 'content-type': 'application/json', accept: 'application/json' }; const res = yield this.fetch(this.verifyTFACodeUrl, { headers, body, method }); return { res, data: null }; }); } /** * Verifies TFA code which is generated by a TOTP app. * * @param {string} code The code to verify. * * @returns Returns a status object. * * **Example** * ```typescript * * (async () => { * const {data, res} = await userService.verifyTotpCode('123123'); * })(); * ``` */ verifyTotpCode(code) { return __awaiter(this, void 0, void 0, function* () { const method = 'POST'; const headers = { 'content-type': 'application/json' }; const body = JSON.stringify({ code }); const res = yield this.fetch(this.verifyTOTPCodeUrl, { headers, body, method }); return { res, data: null }; }); } /** * Verifies TFA code which is generated by a TOTP app. * * @returns Returns a status object. * * **Example** * ```typescript * * (async () => { * const {data, res} = await userService.activateTotp(); * })(); * ``` */ activateTotp() { return __awaiter(this, void 0, void 0, function* () { const method = 'POST'; const headers = { 'content-type': 'application/json' }; const body = JSON.stringify({ isActive: true }); const res = yield this.fetch(this.activateTOTPCodeUrl, { headers, body, method }); return { res, data: null }; }); } /** * Checks if TOTP is activated and enforced. * * @returns Returns an object of ITotpStatus if it is active. * * **Example** * ```typescript * * (async () => { * const {data, res} = await userService.getActivityTotp(); * console.log(data.isActive); * })(); * ``` */ getActivityTotp() { return __awaiter(this, void 0, void 0, function* () { const method = 'GET'; const headers = { 'content-type': 'application/json' }; const res = yield this.fetch(this.activateTOTPCodeUrl, { headers, method }); const data = yield res.json(); return { res, data }; }); } /** * Generates a secret which can be used to setup two-factor authentication with TOTP. * * @returns Returns the secret and an URL to a QR Code. * * **Example** * ```typescript * * (async () => { * const {data, res} = await userService.generateTotpSecret(); * console.log(secret); * })(); * ``` */ generateTotpSecret() { return __awaiter(this, void 0, void 0, function* () { const method = 'POST'; const headers = { 'content-type': 'application/json', accept: 'application/json' }; const res = yield this.fetch(this.totpCurrentUserURL, { headers, method }); const data = yield res.json(); return { res, data }; }); } /** * Revokes a specific user's TOTP secret. * * @param {IUser} user User whose TOTP secret to revoke. * * @returns Status object */ totpRevokeSecret(user) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.getDetailUrl(user)}/${this.revokeTOTPSecretUrl}`; const method = 'DELETE'; const headers = { accept: 'application/json' }; const res = yield this.fetch(url, { headers, method }); return { res, data: null }; }); } /** * Saves phone number for the current user. * @param phoneNumber Phone number to save. * @returns Server response and data with updated current user object. */ savePhoneNumber(phoneNumber) { return __awaiter(this, void 0, void 0, function* () { const url = this.currentUserPhoneUrl; const options = { method: 'PUT', headers: { 'content-type': 'application/json', accept: 'application/json' }, body: JSON.stringify({ phone: phoneNumber }) }; const res = yield this.fetch(url, options); const data = yield res.json(); return { res, data }; }); } /** * Gets the list of emails of users subscribed for newsletter * on the current tenant and its subtenants. * @returns Server response and data with email addresses as plain text. */ getNewsletterEmails() { return __awaiter(this, void 0, void 0, function* () { const url = this.newsletterEmailsUrl; const options = { method: 'GET', headers: { accept: 'text/plain' } }; const res = yield this.fetch(url, options); const data = yield res.text(); return { res, data }; }); } /** * Changes password for user. * * @param {string | number | IUser} entityOrId User's id or user object. * @param {string} newPassword New user password. * @param {string} currentUserPassword The password of the currently logged user. * * @returns Returns a result object. */ changeUserPassword(entityOrId, newPassword, currentUserPassword) { return __awaiter(this, void 0, void 0, function* () { const method = 'PUT'; const headers = { 'content-type': 'application/json' }; const body = JSON.stringify({ newPassword, currentUserPassword }); const res = yield this.fetch(this.changeUserPasswordUrl(entityOrId), { headers, body, method }); return { res, data: null }; }); } /** * Changes password for current user. * * @param {string} newPassword New password for current user. * @param {string} currentUserPassword The password of the currently logged user. * * @returns Returns a result object. During this action if preferred login mode is OAI_SECURE new jwt cookie will be set. */ changeCurrentUserPassword(newPassword, currentUserPassword) { return __awaiter(this, void 0, void 0, function* () { const method = 'PUT'; const headers = { 'content-type': 'application/json' }; const body = JSON.stringify({ newPassword, currentUserPassword }); const res = yield this.fetch(this.currentUserPasswordUrl, { headers, body, method }); return { res, data: null }; }); } /** * Revoke tokens for all users. All users logged with "OAI-Secure" or "Single sign-on redirect" will be logged out. * * @returns Returns a result object. */ revokeTokens() { return __awaiter(this, void 0, void 0, function* () { const method = 'POST'; const headers = { 'content-type': 'application/json' }; const res = yield this.fetch(this.revokeAllTokensUrl, { headers, method }); return { res, data: null }; }); } hasRole(user, roleId) { return this.hasRoleInUser(user, roleId) || this.hasRoleInGroups(user, roleId); } hasAllRoles(user, roleIds) { return roleIds.every(roleId => this.hasRole(user, roleId)); } hasAnyRole(user, roleIds) { return roleIds.some(roleId => this.hasRole(user, roleId)); } hasAnyGlobalRole(user, globalRoleIds) { return globalRoleIds.some(globalRoleId => this.hasGlobalRoleInUser(user, globalRoleId)); } isDeviceUser(user) { return user.id.match(/^device_/); } onBeforeUpdate(user) { const obj = Object.assign({}, user); delete obj.id; delete obj.userName; return obj; } getDetailUrl(entityOrId) { return `${this.listUrl}/${encodeURIComponent(this.getId(entityOrId))}`; } getId(entityOrId) { let id; if (typeof entityOrId === 'object' && entityOrId.id) { id = entityOrId.id; } else if (typeof entityOrId === 'object' && entityOrId.userName) { id = entityOrId.userName; } else { id = entityOrId; } return String(id); } hasRoleInUser(user, roleId) { const effectiveRoles = user.effectiveRoles || []; return (this.hasRoleInReferences((user && user.roles && user.roles.references) || [], roleId) || effectiveRoles.some(({ id }) => roleId === id)); } hasRoleInGroups(user, roleId) { const groupReferences = (user && user.groups && user.groups.references) || []; return groupReferences.some(groupRef => this.hasRoleInReferences(groupRef.group.roles.references, roleId)); } hasRoleInReferences(references, roleId) { return references.some(ref => ref.role.id === roleId); } changeUserPasswordUrl(entityOrId) { return `${this.client.tenant}/users/${this.getId(entityOrId)}/password`; } hasGlobalRoleInUser(user, globalRoleId) { var _a; const groupReferencesIds = (((_a = user === null || user === void 0 ? void 0 : user.groups) === null || _a === void 0 ? void 0 : _a.references) || []).map(gR => { var _a; return (_a = gR === null || gR === void 0 ? void 0 : gR.group) === null || _a === void 0 ? void 0 : _a.id; }); return groupReferencesIds.some(id => id === globalRoleId); } } //# sourceMappingURL=UserService.js.map