@c8y/client
Version:
Client application programming interface to access the Cumulocity IoT-Platform REST services.
599 lines • 21.2 kB
JavaScript
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