UNPKG

@c8y/client

Version:

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

544 lines • 18.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UserService = void 0; const core_1 = require("../core"); const UserInventoryRoleService_1 = require("./UserInventoryRoleService"); /** * @description * This service allows for managing users. */ class UserService extends core_1.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. */ async detail(entityOrId, params = {}) { return super.detail(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); * })(); * ``` */ async create(entity) { return super.create(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'. */ async update(entity) { return super.update(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); * })(); * ``` */ async list(filter = {}) { return super.list(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); * })(); * ``` */ async delete(entityOrId) { return super.delete(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_1.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(); * })(); * ``` */ async current() { const headers = { 'content-type': 'application/json', Accept: 'application/vnd.com.nsn.cumulocity.user+json;' }; const res = await this.fetch(this.currentUserUrl, { headers }); const data = await 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(); * })(); * ``` */ async currentWithEffectiveRoles() { const headers = { 'content-type': 'application/json', Accept: 'application/vnd.com.nsn.cumulocity.currentUser+json;' }; const res = await this.fetch(this.currentUserUrl, { headers }); const data = await 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 */ async updateCurrent(user) { 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 = await this.fetch(this.currentUserUrl, { headers, body, method: 'PUT' }); const data = await 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); * })(); * ``` */ async sendPasswordResetMail(email, tenantId) { 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 = await 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); * })(); * ``` */ async resetPassword(newPassword, tenantId) { 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 = await 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'); * })(); * ``` */ async verifyTFACode(pin) { const method = 'POST'; const body = JSON.stringify({ pin }); const headers = { 'content-type': 'application/json', accept: 'application/json' }; const res = await 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'); * })(); * ``` */ async verifyTotpCode(code) { const method = 'POST'; const headers = { 'content-type': 'application/json' }; const body = JSON.stringify({ code }); const res = await 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(); * })(); * ``` */ async activateTotp() { const method = 'POST'; const headers = { 'content-type': 'application/json' }; const body = JSON.stringify({ isActive: true }); const res = await 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); * })(); * ``` */ async getActivityTotp() { const method = 'GET'; const headers = { 'content-type': 'application/json' }; const res = await this.fetch(this.activateTOTPCodeUrl, { headers, method }); const data = await 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); * })(); * ``` */ async generateTotpSecret() { const method = 'POST'; const headers = { 'content-type': 'application/json', accept: 'application/json' }; const res = await this.fetch(this.totpCurrentUserURL, { headers, method }); const data = await res.json(); return { res, data }; } /** * Revokes a specific user's TOTP secret. * * @param {IUser} user User whose TOTP secret to revoke. * * @returns Status object */ async totpRevokeSecret(user) { const url = `${this.getDetailUrl(user)}/${this.revokeTOTPSecretUrl}`; const method = 'DELETE'; const headers = { accept: 'application/json' }; const res = await 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. */ async savePhoneNumber(phoneNumber) { const url = this.currentUserPhoneUrl; const options = { method: 'PUT', headers: { 'content-type': 'application/json', accept: 'application/json' }, body: JSON.stringify({ phone: phoneNumber }) }; const res = await this.fetch(url, options); const data = await 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. */ async getNewsletterEmails() { const url = this.newsletterEmailsUrl; const options = { method: 'GET', headers: { accept: 'text/plain' } }; const res = await this.fetch(url, options); const data = await 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. */ async changeUserPassword(entityOrId, newPassword, currentUserPassword) { const method = 'PUT'; const headers = { 'content-type': 'application/json' }; const body = JSON.stringify({ newPassword, currentUserPassword }); const res = await 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. */ async changeCurrentUserPassword(newPassword, currentUserPassword) { const method = 'PUT'; const headers = { 'content-type': 'application/json' }; const body = JSON.stringify({ newPassword, currentUserPassword }); const res = await 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. */ async revokeTokens() { const method = 'POST'; const headers = { 'content-type': 'application/json' }; const res = await 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) { const groupReferencesIds = (user?.groups?.references || []).map(gR => gR?.group?.id); return groupReferencesIds.some(id => id === globalRoleId); } } exports.UserService = UserService; //# sourceMappingURL=UserService.js.map