couchbase
Version:
The official Couchbase Node.js Client Library.
643 lines (642 loc) • 21.9 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserManager = exports.Group = exports.UserAndMetadata = exports.User = exports.RoleAndOrigin = exports.RoleAndDescription = exports.Role = exports.Origin = void 0;
const errors_1 = require("./errors");
const httpexecutor_1 = require("./httpexecutor");
const utilities_1 = require("./utilities");
/**
* Contains information about an origin for a role.
*
* @category Management
*/
class Origin {
/**
* @internal
*/
constructor(data) {
this.type = data.type;
this.name = data.name;
}
/**
* @internal
*/
static _fromNsData(data) {
return new Origin({
type: data.type,
name: data.name,
});
}
}
exports.Origin = Origin;
/**
* Contains information about a role.
*
* @category Management
*/
class Role {
/**
* @internal
*/
constructor(data) {
this.name = data.name;
this.bucket = data.bucket;
this.scope = data.scope;
this.collection = data.collection;
}
/**
* @internal
*/
static _fromNsData(data) {
return new Role({
name: data.role,
bucket: data.bucket_name,
scope: data.scope_name,
collection: data.collection_name,
});
}
/**
* @internal
*/
static _toNsStr(role) {
if (typeof role === 'string') {
return role;
}
if (role.bucket && role.scope && role.collection) {
return `${role.name}[${role.bucket}:${role.scope}:${role.collection}]`;
}
else if (role.bucket && role.scope) {
return `${role.name}[${role.bucket}:${role.scope}]`;
}
else if (role.bucket) {
return `${role.name}[${role.bucket}]`;
}
else {
return role.name;
}
}
}
exports.Role = Role;
/**
* Contains information about a role along with its description.
*
* @category Management
*/
class RoleAndDescription extends Role {
/**
* @internal
*/
constructor(data) {
super(data);
this.displayName = data.displayName;
this.description = data.description;
}
/**
* @internal
*/
static _fromNsData(data) {
return new RoleAndDescription({
...Role._fromNsData(data),
displayName: data.name,
description: data.description,
});
}
}
exports.RoleAndDescription = RoleAndDescription;
/**
* Contains information about a role along with its origin.
*
* @category Management
*/
class RoleAndOrigin extends Role {
/**
* @internal
*/
constructor(data) {
super(data);
this.origins = data.origins;
}
/**
* @internal
*/
static _fromNsData(data) {
let origins;
if (data.origins) {
origins = data.origins.map((originData) => Origin._fromNsData(originData));
}
else {
origins = [];
}
return new RoleAndOrigin({
...Role._fromNsData(data),
origins,
});
}
}
exports.RoleAndOrigin = RoleAndOrigin;
/**
* Contains information about a user.
*
* @category Management
*/
class User {
/**
* @internal
*/
constructor(data) {
this.username = data.username;
this.displayName = data.displayName;
this.groups = data.groups;
this.roles = data.roles;
}
/**
* @internal
*/
static _fromNsData(data) {
let roles;
if (data.roles) {
roles = data.roles
.filter((roleData) => {
// Check whether or not this role has originated from the user directly
// or whether it was through a group.
if (!roleData.origins || roleData.origins.length === 0) {
return false;
}
return !!roleData.origins.find((originData) => originData.type === 'user');
})
.map((roleData) => Role._fromNsData(roleData));
}
else {
roles = [];
}
return new User({
username: data.id,
displayName: data.name,
groups: data.groups,
roles: roles,
password: undefined,
});
}
/**
* @internal
*/
static _toNsData(user) {
let groups = undefined;
if (user.groups && user.groups.length > 0) {
groups = user.groups;
}
let roles = undefined;
if (user.roles && user.roles.length > 0) {
roles = user.roles.map((role) => Role._toNsStr(role)).join(',');
}
return {
name: user.displayName,
groups: groups,
password: user.password,
roles: roles,
};
}
}
exports.User = User;
/**
* Contains information about a user along with some additional meta-data
* about that user.
*
* @category Management
*/
class UserAndMetadata extends User {
/**
* Same as {@link effectiveRoles}, which already contains the roles
* including their origins.
*
* @deprecated Use {@link effectiveRoles} instead.
*/
get effectiveRolesAndOrigins() {
return this.effectiveRoles;
}
/**
* @internal
*/
constructor(data) {
super(data);
this.domain = data.domain;
this.effectiveRoles = data.effectiveRoles;
this.passwordChanged = data.passwordChanged;
this.externalGroups = data.externalGroups;
}
/**
* @internal
*/
static _fromNsData(data) {
let effectiveRoles;
if (data.roles) {
effectiveRoles = data.roles.map((roleData) => RoleAndOrigin._fromNsData(roleData));
}
else {
effectiveRoles = [];
}
return new UserAndMetadata({
...User._fromNsData(data),
domain: data.domain,
effectiveRoles: effectiveRoles,
effectiveRolesAndOrigins: effectiveRoles,
passwordChanged: new Date(data.password_change_date),
externalGroups: data.external_groups,
});
}
}
exports.UserAndMetadata = UserAndMetadata;
/**
* Contains information about a group.
*
* @category Management
*/
class Group {
/**
* @internal
*/
constructor(data) {
this.name = data.name;
this.description = data.description;
this.roles = data.roles;
this.ldapGroupReference = data.ldapGroupReference;
}
/**
* @internal
*/
static _fromNsData(data) {
let roles;
if (data.roles) {
roles = data.roles.map((roleData) => Role._fromNsData(roleData));
}
else {
roles = [];
}
return new Group({
name: data.id,
description: data.description,
roles: roles,
ldapGroupReference: data.ldap_group_reference,
});
}
/**
* @internal
*/
static _toNsData(group) {
let roles = undefined;
if (group.roles && group.roles.length > 0) {
roles = group.roles.map((role) => Role._toNsStr(role)).join(',');
}
return {
description: group.description,
roles: roles,
ldap_group_reference: group.ldapGroupReference,
};
}
}
exports.Group = Group;
/**
* UserManager is an interface which enables the management of users,
* groups and roles for the cluster.
*
* @category Management
*/
class UserManager {
/**
* @internal
*/
constructor(cluster) {
this._cluster = cluster;
}
get _http() {
return new httpexecutor_1.HttpExecutor(this._cluster.conn);
}
/**
* Returns a specific user by their username.
*
* @param username The username of the user to fetch.
* @param options Optional parameters for this operation.
* @param callback A node-style callback to be invoked after execution.
*/
async getUser(username, options, callback) {
if (options instanceof Function) {
callback = arguments[1];
options = undefined;
}
if (!options) {
options = {};
}
const domainName = options.domainName || 'local';
const timeout = options.timeout || this._cluster.managementTimeout;
return utilities_1.PromiseHelper.wrapAsync(async () => {
const res = await this._http.request({
type: httpexecutor_1.HttpServiceType.Management,
method: httpexecutor_1.HttpMethod.Get,
path: `/settings/rbac/users/${domainName}/${username}`,
timeout: timeout,
});
if (res.statusCode !== 200) {
const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
if (res.statusCode === 404) {
throw new errors_1.UserNotFoundError(undefined, errCtx);
}
throw new errors_1.CouchbaseError('failed to get the user', undefined, errCtx);
}
const userData = JSON.parse(res.body.toString());
return UserAndMetadata._fromNsData(userData);
}, callback);
}
/**
* Returns a list of all existing users.
*
* @param options Optional parameters for this operation.
* @param callback A node-style callback to be invoked after execution.
*/
async getAllUsers(options, callback) {
if (options instanceof Function) {
callback = arguments[0];
options = undefined;
}
if (!options) {
options = {};
}
const domainName = options.domainName || 'local';
const timeout = options.timeout || this._cluster.managementTimeout;
return utilities_1.PromiseHelper.wrapAsync(async () => {
const res = await this._http.request({
type: httpexecutor_1.HttpServiceType.Management,
method: httpexecutor_1.HttpMethod.Get,
path: `/settings/rbac/users/${domainName}`,
timeout: timeout,
});
if (res.statusCode !== 200) {
const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
throw new errors_1.CouchbaseError('failed to get users', undefined, errCtx);
}
const usersData = JSON.parse(res.body.toString());
const users = usersData.map((userData) => UserAndMetadata._fromNsData(userData));
return users;
}, callback);
}
/**
* Creates or updates an existing user.
*
* @param user The user to update.
* @param options Optional parameters for this operation.
* @param callback A node-style callback to be invoked after execution.
*/
async upsertUser(user, options, callback) {
if (options instanceof Function) {
callback = arguments[1];
options = undefined;
}
if (!options) {
options = {};
}
const domainName = options.domainName || 'local';
const timeout = options.timeout || this._cluster.managementTimeout;
return utilities_1.PromiseHelper.wrapAsync(async () => {
const userData = User._toNsData(user);
const res = await this._http.request({
type: httpexecutor_1.HttpServiceType.Management,
method: httpexecutor_1.HttpMethod.Put,
path: `/settings/rbac/users/${domainName}/${user.username}`,
contentType: 'application/x-www-form-urlencoded',
body: (0, utilities_1.cbQsStringify)(userData),
timeout: timeout,
});
if (res.statusCode !== 200) {
const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
throw new errors_1.CouchbaseError('failed to upsert user', undefined, errCtx);
}
}, callback);
}
/**
* Change password for the currently authenticatd user.
*
* @param newPassword The new password to be applied.
* @param options Optional parameters for this operation.
* @param callback A node-style callback to be invoked after execution.
*/
async changePassword(newPassword, options, callback) {
if (options instanceof Function) {
callback = arguments[1];
options = undefined;
}
if (!options) {
options = {};
}
const timeout = options.timeout || this._cluster.managementTimeout;
return utilities_1.PromiseHelper.wrapAsync(async () => {
const passwordData = { password: newPassword };
const res = await this._http.request({
type: httpexecutor_1.HttpServiceType.Management,
method: httpexecutor_1.HttpMethod.Post,
path: `/controller/changePassword`,
contentType: 'application/x-www-form-urlencoded',
body: (0, utilities_1.cbQsStringify)(passwordData),
timeout: timeout,
});
if (res.statusCode !== 200) {
const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
if (res.statusCode === 404) {
throw new errors_1.UserNotFoundError(undefined, errCtx);
}
throw new errors_1.CouchbaseError('failed to change password for the current user', undefined, errCtx);
}
}, callback);
}
/**
* Drops an existing user.
*
* @param username The username of the user to drop.
* @param options Optional parameters for this operation.
* @param callback A node-style callback to be invoked after execution.
*/
async dropUser(username, options, callback) {
if (options instanceof Function) {
callback = arguments[1];
options = undefined;
}
if (!options) {
options = {};
}
const domainName = options.domainName || 'local';
const timeout = options.timeout || this._cluster.managementTimeout;
return utilities_1.PromiseHelper.wrapAsync(async () => {
const res = await this._http.request({
type: httpexecutor_1.HttpServiceType.Management,
method: httpexecutor_1.HttpMethod.Delete,
path: `/settings/rbac/users/${domainName}/${username}`,
timeout: timeout,
});
if (res.statusCode !== 200) {
const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
if (res.statusCode === 404) {
throw new errors_1.UserNotFoundError(undefined, errCtx);
}
throw new errors_1.CouchbaseError('failed to drop the user', undefined, errCtx);
}
}, callback);
}
/**
* Returns a list of roles available on the server.
*
* @param options Optional parameters for this operation.
* @param callback A node-style callback to be invoked after execution.
*/
async getRoles(options, callback) {
if (options instanceof Function) {
callback = arguments[0];
options = undefined;
}
if (!options) {
options = {};
}
const timeout = options.timeout || this._cluster.managementTimeout;
return utilities_1.PromiseHelper.wrapAsync(async () => {
const res = await this._http.request({
type: httpexecutor_1.HttpServiceType.Management,
method: httpexecutor_1.HttpMethod.Get,
path: `/settings/rbac/roles`,
timeout: timeout,
});
if (res.statusCode !== 200) {
const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
throw new errors_1.CouchbaseError('failed to get roles', undefined, errCtx);
}
const rolesData = JSON.parse(res.body.toString());
const roles = rolesData.map((roleData) => RoleAndDescription._fromNsData(roleData));
return roles;
}, callback);
}
/**
* Returns a group by it's name.
*
* @param groupName The name of the group to retrieve.
* @param options Optional parameters for this operation.
* @param callback A node-style callback to be invoked after execution.
*/
async getGroup(groupName, options, callback) {
if (options instanceof Function) {
callback = arguments[1];
options = undefined;
}
if (!options) {
options = {};
}
const timeout = options.timeout || this._cluster.managementTimeout;
return utilities_1.PromiseHelper.wrapAsync(async () => {
const res = await this._http.request({
type: httpexecutor_1.HttpServiceType.Management,
method: httpexecutor_1.HttpMethod.Get,
path: `/settings/rbac/groups/${groupName}`,
timeout: timeout,
});
if (res.statusCode !== 200) {
const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
if (res.statusCode === 404) {
throw new errors_1.GroupNotFoundError(undefined, errCtx);
}
throw new errors_1.CouchbaseError('failed to get the group', undefined, errCtx);
}
const groupData = JSON.parse(res.body.toString());
return Group._fromNsData(groupData);
}, callback);
}
/**
* Returns a list of all existing groups.
*
* @param options Optional parameters for this operation.
* @param callback A node-style callback to be invoked after execution.
*/
async getAllGroups(options, callback) {
if (options instanceof Function) {
callback = arguments[0];
options = undefined;
}
if (!options) {
options = {};
}
const timeout = options.timeout || this._cluster.managementTimeout;
return utilities_1.PromiseHelper.wrapAsync(async () => {
const res = await this._http.request({
type: httpexecutor_1.HttpServiceType.Management,
method: httpexecutor_1.HttpMethod.Get,
path: `/settings/rbac/groups`,
timeout: timeout,
});
if (res.statusCode !== 200) {
const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
throw new errors_1.CouchbaseError('failed to get groups', undefined, errCtx);
}
const groupsData = JSON.parse(res.body.toString());
const groups = groupsData.map((groupData) => Group._fromNsData(groupData));
return groups;
}, callback);
}
/**
* Creates or updates an existing group.
*
* @param group The group to update.
* @param options Optional parameters for this operation.
* @param callback A node-style callback to be invoked after execution.
*/
async upsertGroup(group, options, callback) {
if (options instanceof Function) {
callback = arguments[1];
options = undefined;
}
if (!options) {
options = {};
}
const timeout = options.timeout || this._cluster.managementTimeout;
return utilities_1.PromiseHelper.wrapAsync(async () => {
const groupData = Group._toNsData(group);
const res = await this._http.request({
type: httpexecutor_1.HttpServiceType.Management,
method: httpexecutor_1.HttpMethod.Put,
path: `/settings/rbac/groups/${group.name}`,
contentType: 'application/x-www-form-urlencoded',
body: (0, utilities_1.cbQsStringify)(groupData),
timeout: timeout,
});
if (res.statusCode !== 200) {
const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
throw new errors_1.CouchbaseError('failed to upsert group', undefined, errCtx);
}
}, callback);
}
/**
* Drops an existing group.
*
* @param groupName The name of the group to drop.
* @param options Optional parameters for this operation.
* @param callback A node-style callback to be invoked after execution.
*/
async dropGroup(groupName, options, callback) {
if (options instanceof Function) {
callback = arguments[1];
options = undefined;
}
if (!options) {
options = {};
}
const timeout = options.timeout || this._cluster.managementTimeout;
return utilities_1.PromiseHelper.wrapAsync(async () => {
const res = await this._http.request({
type: httpexecutor_1.HttpServiceType.Management,
method: httpexecutor_1.HttpMethod.Delete,
path: `/settings/rbac/groups/${groupName}`,
timeout: timeout,
});
if (res.statusCode !== 200) {
const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
if (res.statusCode === 404) {
throw new errors_1.GroupNotFoundError(undefined, errCtx);
}
throw new errors_1.CouchbaseError('failed to drop the group', undefined, errCtx);
}
}, callback);
}
}
exports.UserManager = UserManager;
;