1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.UserManager = exports.Group = exports.UserAndMetadata = exports.User = exports.RoleAndOrigin = exports.RoleAndDescription = exports.Role = exports.Origin = void 0;
|
4 | const errors_1 = require("./errors");
|
5 | const httpexecutor_1 = require("./httpexecutor");
|
6 | const utilities_1 = require("./utilities");
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | class Origin {
|
13 | |
14 |
|
15 |
|
16 | constructor(data) {
|
17 | this.type = data.type;
|
18 | this.name = data.name;
|
19 | }
|
20 | |
21 |
|
22 |
|
23 | static _fromNsData(data) {
|
24 | return new Origin({
|
25 | type: data.type,
|
26 | name: data.name,
|
27 | });
|
28 | }
|
29 | }
|
30 | exports.Origin = Origin;
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 | class Role {
|
37 | |
38 |
|
39 |
|
40 | constructor(data) {
|
41 | this.name = data.name;
|
42 | this.bucket = data.bucket;
|
43 | this.scope = data.scope;
|
44 | this.collection = data.collection;
|
45 | }
|
46 | |
47 |
|
48 |
|
49 | static _fromNsData(data) {
|
50 | return new Role({
|
51 | name: data.role,
|
52 | bucket: data.bucket_name,
|
53 | scope: data.scope_name,
|
54 | collection: data.collection_name,
|
55 | });
|
56 | }
|
57 | |
58 |
|
59 |
|
60 | static _toNsStr(role) {
|
61 | if (typeof role === 'string') {
|
62 | return role;
|
63 | }
|
64 | if (role.bucket && role.scope && role.collection) {
|
65 | return `${role.name}[${role.bucket}:${role.scope}:${role.collection}]`;
|
66 | }
|
67 | else if (role.bucket && role.scope) {
|
68 | return `${role.name}[${role.bucket}:${role.scope}]`;
|
69 | }
|
70 | else if (role.bucket) {
|
71 | return `${role.name}[${role.bucket}]`;
|
72 | }
|
73 | else {
|
74 | return role.name;
|
75 | }
|
76 | }
|
77 | }
|
78 | exports.Role = Role;
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 | class RoleAndDescription extends Role {
|
85 | |
86 |
|
87 |
|
88 | constructor(data) {
|
89 | super(data);
|
90 | this.displayName = data.displayName;
|
91 | this.description = data.description;
|
92 | }
|
93 | |
94 |
|
95 |
|
96 | static _fromNsData(data) {
|
97 | return new RoleAndDescription({
|
98 | ...Role._fromNsData(data),
|
99 | displayName: data.name,
|
100 | description: data.description,
|
101 | });
|
102 | }
|
103 | }
|
104 | exports.RoleAndDescription = RoleAndDescription;
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 | class RoleAndOrigin extends Role {
|
111 | |
112 |
|
113 |
|
114 | constructor(data) {
|
115 | super(data);
|
116 | this.origins = data.origins;
|
117 | }
|
118 | |
119 |
|
120 |
|
121 | static _fromNsData(data) {
|
122 | let origins;
|
123 | if (data.origins) {
|
124 | origins = data.origins.map((originData) => Origin._fromNsData(originData));
|
125 | }
|
126 | else {
|
127 | origins = [];
|
128 | }
|
129 | return new RoleAndOrigin({
|
130 | ...Role._fromNsData(data),
|
131 | origins,
|
132 | });
|
133 | }
|
134 | }
|
135 | exports.RoleAndOrigin = RoleAndOrigin;
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 | class User {
|
142 | |
143 |
|
144 |
|
145 | constructor(data) {
|
146 | this.username = data.username;
|
147 | this.displayName = data.displayName;
|
148 | this.groups = data.groups;
|
149 | this.roles = data.roles;
|
150 | }
|
151 | |
152 |
|
153 |
|
154 | static _fromNsData(data) {
|
155 | let roles;
|
156 | if (data.roles) {
|
157 | roles = data.roles
|
158 | .filter((roleData) => {
|
159 |
|
160 |
|
161 | if (!roleData.origins || roleData.origins.length === 0) {
|
162 | return false;
|
163 | }
|
164 | return !!roleData.origins.find((originData) => originData.type === 'user');
|
165 | })
|
166 | .map((roleData) => Role._fromNsData(roleData));
|
167 | }
|
168 | else {
|
169 | roles = [];
|
170 | }
|
171 | return new User({
|
172 | username: data.id,
|
173 | displayName: data.name,
|
174 | groups: data.groups,
|
175 | roles: roles,
|
176 | password: undefined,
|
177 | });
|
178 | }
|
179 | |
180 |
|
181 |
|
182 | static _toNsData(user) {
|
183 | let groups = undefined;
|
184 | if (user.groups && user.groups.length > 0) {
|
185 | groups = user.groups;
|
186 | }
|
187 | let roles = undefined;
|
188 | if (user.roles && user.roles.length > 0) {
|
189 | roles = user.roles.map((role) => Role._toNsStr(role)).join(',');
|
190 | }
|
191 | return {
|
192 | name: user.displayName,
|
193 | groups: groups,
|
194 | password: user.password,
|
195 | roles: roles,
|
196 | };
|
197 | }
|
198 | }
|
199 | exports.User = User;
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 | class UserAndMetadata extends User {
|
207 | |
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 | get effectiveRolesAndOrigins() {
|
214 | return this.effectiveRoles;
|
215 | }
|
216 | |
217 |
|
218 |
|
219 | constructor(data) {
|
220 | super(data);
|
221 | this.domain = data.domain;
|
222 | this.effectiveRoles = data.effectiveRoles;
|
223 | this.passwordChanged = data.passwordChanged;
|
224 | this.externalGroups = data.externalGroups;
|
225 | }
|
226 | |
227 |
|
228 |
|
229 | static _fromNsData(data) {
|
230 | let effectiveRoles;
|
231 | if (data.roles) {
|
232 | effectiveRoles = data.roles.map((roleData) => RoleAndOrigin._fromNsData(roleData));
|
233 | }
|
234 | else {
|
235 | effectiveRoles = [];
|
236 | }
|
237 | return new UserAndMetadata({
|
238 | ...User._fromNsData(data),
|
239 | domain: data.domain,
|
240 | effectiveRoles: effectiveRoles,
|
241 | effectiveRolesAndOrigins: effectiveRoles,
|
242 | passwordChanged: new Date(data.password_change_date),
|
243 | externalGroups: data.external_groups,
|
244 | });
|
245 | }
|
246 | }
|
247 | exports.UserAndMetadata = UserAndMetadata;
|
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 | class Group {
|
254 | |
255 |
|
256 |
|
257 | constructor(data) {
|
258 | this.name = data.name;
|
259 | this.description = data.description;
|
260 | this.roles = data.roles;
|
261 | this.ldapGroupReference = data.ldapGroupReference;
|
262 | }
|
263 | |
264 |
|
265 |
|
266 | static _fromNsData(data) {
|
267 | let roles;
|
268 | if (data.roles) {
|
269 | roles = data.roles.map((roleData) => Role._fromNsData(roleData));
|
270 | }
|
271 | else {
|
272 | roles = [];
|
273 | }
|
274 | return new Group({
|
275 | name: data.id,
|
276 | description: data.description,
|
277 | roles: roles,
|
278 | ldapGroupReference: data.ldap_group_reference,
|
279 | });
|
280 | }
|
281 | |
282 |
|
283 |
|
284 | static _toNsData(group) {
|
285 | let roles = undefined;
|
286 | if (group.roles && group.roles.length > 0) {
|
287 | roles = group.roles.map((role) => Role._toNsStr(role)).join(',');
|
288 | }
|
289 | return {
|
290 | description: group.description,
|
291 | roles: roles,
|
292 | ldap_group_reference: group.ldapGroupReference,
|
293 | };
|
294 | }
|
295 | }
|
296 | exports.Group = Group;
|
297 |
|
298 |
|
299 |
|
300 |
|
301 |
|
302 |
|
303 | class UserManager {
|
304 | |
305 |
|
306 |
|
307 | constructor(cluster) {
|
308 | this._cluster = cluster;
|
309 | }
|
310 | get _http() {
|
311 | return new httpexecutor_1.HttpExecutor(this._cluster.conn);
|
312 | }
|
313 | |
314 |
|
315 |
|
316 |
|
317 |
|
318 |
|
319 |
|
320 | async getUser(username, options, callback) {
|
321 | if (options instanceof Function) {
|
322 | callback = arguments[1];
|
323 | options = undefined;
|
324 | }
|
325 | if (!options) {
|
326 | options = {};
|
327 | }
|
328 | const domainName = options.domainName || 'local';
|
329 | const timeout = options.timeout || this._cluster.managementTimeout;
|
330 | return utilities_1.PromiseHelper.wrapAsync(async () => {
|
331 | const res = await this._http.request({
|
332 | type: httpexecutor_1.HttpServiceType.Management,
|
333 | method: httpexecutor_1.HttpMethod.Get,
|
334 | path: `/settings/rbac/users/${domainName}/${username}`,
|
335 | timeout: timeout,
|
336 | });
|
337 | if (res.statusCode !== 200) {
|
338 | const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
|
339 | if (res.statusCode === 404) {
|
340 | throw new errors_1.UserNotFoundError(undefined, errCtx);
|
341 | }
|
342 | throw new errors_1.CouchbaseError('failed to get the user', undefined, errCtx);
|
343 | }
|
344 | const userData = JSON.parse(res.body.toString());
|
345 | return UserAndMetadata._fromNsData(userData);
|
346 | }, callback);
|
347 | }
|
348 | |
349 |
|
350 |
|
351 |
|
352 |
|
353 |
|
354 | async getAllUsers(options, callback) {
|
355 | if (options instanceof Function) {
|
356 | callback = arguments[0];
|
357 | options = undefined;
|
358 | }
|
359 | if (!options) {
|
360 | options = {};
|
361 | }
|
362 | const domainName = options.domainName || 'local';
|
363 | const timeout = options.timeout || this._cluster.managementTimeout;
|
364 | return utilities_1.PromiseHelper.wrapAsync(async () => {
|
365 | const res = await this._http.request({
|
366 | type: httpexecutor_1.HttpServiceType.Management,
|
367 | method: httpexecutor_1.HttpMethod.Get,
|
368 | path: `/settings/rbac/users/${domainName}`,
|
369 | timeout: timeout,
|
370 | });
|
371 | if (res.statusCode !== 200) {
|
372 | const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
|
373 | throw new errors_1.CouchbaseError('failed to get users', undefined, errCtx);
|
374 | }
|
375 | const usersData = JSON.parse(res.body.toString());
|
376 | const users = usersData.map((userData) => UserAndMetadata._fromNsData(userData));
|
377 | return users;
|
378 | }, callback);
|
379 | }
|
380 | |
381 |
|
382 |
|
383 |
|
384 |
|
385 |
|
386 |
|
387 | async upsertUser(user, options, callback) {
|
388 | if (options instanceof Function) {
|
389 | callback = arguments[1];
|
390 | options = undefined;
|
391 | }
|
392 | if (!options) {
|
393 | options = {};
|
394 | }
|
395 | const domainName = options.domainName || 'local';
|
396 | const timeout = options.timeout || this._cluster.managementTimeout;
|
397 | return utilities_1.PromiseHelper.wrapAsync(async () => {
|
398 | const userData = User._toNsData(user);
|
399 | const res = await this._http.request({
|
400 | type: httpexecutor_1.HttpServiceType.Management,
|
401 | method: httpexecutor_1.HttpMethod.Put,
|
402 | path: `/settings/rbac/users/${domainName}/${user.username}`,
|
403 | contentType: 'application/x-www-form-urlencoded',
|
404 | body: (0, utilities_1.cbQsStringify)(userData),
|
405 | timeout: timeout,
|
406 | });
|
407 | if (res.statusCode !== 200) {
|
408 | const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
|
409 | throw new errors_1.CouchbaseError('failed to upsert user', undefined, errCtx);
|
410 | }
|
411 | }, callback);
|
412 | }
|
413 | |
414 |
|
415 |
|
416 |
|
417 |
|
418 |
|
419 |
|
420 | async changePassword(newPassword, options, callback) {
|
421 | if (options instanceof Function) {
|
422 | callback = arguments[1];
|
423 | options = undefined;
|
424 | }
|
425 | if (!options) {
|
426 | options = {};
|
427 | }
|
428 | const timeout = options.timeout || this._cluster.managementTimeout;
|
429 | return utilities_1.PromiseHelper.wrapAsync(async () => {
|
430 | const passwordData = { password: newPassword };
|
431 | const res = await this._http.request({
|
432 | type: httpexecutor_1.HttpServiceType.Management,
|
433 | method: httpexecutor_1.HttpMethod.Post,
|
434 | path: `/controller/changePassword`,
|
435 | contentType: 'application/x-www-form-urlencoded',
|
436 | body: (0, utilities_1.cbQsStringify)(passwordData),
|
437 | timeout: timeout,
|
438 | });
|
439 | if (res.statusCode !== 200) {
|
440 | const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
|
441 | if (res.statusCode === 404) {
|
442 | throw new errors_1.UserNotFoundError(undefined, errCtx);
|
443 | }
|
444 | throw new errors_1.CouchbaseError('failed to change password for the current user', undefined, errCtx);
|
445 | }
|
446 | }, callback);
|
447 | }
|
448 | |
449 |
|
450 |
|
451 |
|
452 |
|
453 |
|
454 |
|
455 | async dropUser(username, options, callback) {
|
456 | if (options instanceof Function) {
|
457 | callback = arguments[1];
|
458 | options = undefined;
|
459 | }
|
460 | if (!options) {
|
461 | options = {};
|
462 | }
|
463 | const domainName = options.domainName || 'local';
|
464 | const timeout = options.timeout || this._cluster.managementTimeout;
|
465 | return utilities_1.PromiseHelper.wrapAsync(async () => {
|
466 | const res = await this._http.request({
|
467 | type: httpexecutor_1.HttpServiceType.Management,
|
468 | method: httpexecutor_1.HttpMethod.Delete,
|
469 | path: `/settings/rbac/users/${domainName}/${username}`,
|
470 | timeout: timeout,
|
471 | });
|
472 | if (res.statusCode !== 200) {
|
473 | const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
|
474 | if (res.statusCode === 404) {
|
475 | throw new errors_1.UserNotFoundError(undefined, errCtx);
|
476 | }
|
477 | throw new errors_1.CouchbaseError('failed to drop the user', undefined, errCtx);
|
478 | }
|
479 | }, callback);
|
480 | }
|
481 | |
482 |
|
483 |
|
484 |
|
485 |
|
486 |
|
487 | async getRoles(options, callback) {
|
488 | if (options instanceof Function) {
|
489 | callback = arguments[0];
|
490 | options = undefined;
|
491 | }
|
492 | if (!options) {
|
493 | options = {};
|
494 | }
|
495 | const timeout = options.timeout || this._cluster.managementTimeout;
|
496 | return utilities_1.PromiseHelper.wrapAsync(async () => {
|
497 | const res = await this._http.request({
|
498 | type: httpexecutor_1.HttpServiceType.Management,
|
499 | method: httpexecutor_1.HttpMethod.Get,
|
500 | path: `/settings/rbac/roles`,
|
501 | timeout: timeout,
|
502 | });
|
503 | if (res.statusCode !== 200) {
|
504 | const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
|
505 | throw new errors_1.CouchbaseError('failed to get roles', undefined, errCtx);
|
506 | }
|
507 | const rolesData = JSON.parse(res.body.toString());
|
508 | const roles = rolesData.map((roleData) => RoleAndDescription._fromNsData(roleData));
|
509 | return roles;
|
510 | }, callback);
|
511 | }
|
512 | |
513 |
|
514 |
|
515 |
|
516 |
|
517 |
|
518 |
|
519 | async getGroup(groupName, options, callback) {
|
520 | if (options instanceof Function) {
|
521 | callback = arguments[1];
|
522 | options = undefined;
|
523 | }
|
524 | if (!options) {
|
525 | options = {};
|
526 | }
|
527 | const timeout = options.timeout || this._cluster.managementTimeout;
|
528 | return utilities_1.PromiseHelper.wrapAsync(async () => {
|
529 | const res = await this._http.request({
|
530 | type: httpexecutor_1.HttpServiceType.Management,
|
531 | method: httpexecutor_1.HttpMethod.Get,
|
532 | path: `/settings/rbac/groups/${groupName}`,
|
533 | timeout: timeout,
|
534 | });
|
535 | if (res.statusCode !== 200) {
|
536 | const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
|
537 | if (res.statusCode === 404) {
|
538 | throw new errors_1.GroupNotFoundError(undefined, errCtx);
|
539 | }
|
540 | throw new errors_1.CouchbaseError('failed to get the group', undefined, errCtx);
|
541 | }
|
542 | const groupData = JSON.parse(res.body.toString());
|
543 | return Group._fromNsData(groupData);
|
544 | }, callback);
|
545 | }
|
546 | |
547 |
|
548 |
|
549 |
|
550 |
|
551 |
|
552 | async getAllGroups(options, callback) {
|
553 | if (options instanceof Function) {
|
554 | callback = arguments[0];
|
555 | options = undefined;
|
556 | }
|
557 | if (!options) {
|
558 | options = {};
|
559 | }
|
560 | const timeout = options.timeout || this._cluster.managementTimeout;
|
561 | return utilities_1.PromiseHelper.wrapAsync(async () => {
|
562 | const res = await this._http.request({
|
563 | type: httpexecutor_1.HttpServiceType.Management,
|
564 | method: httpexecutor_1.HttpMethod.Get,
|
565 | path: `/settings/rbac/groups`,
|
566 | timeout: timeout,
|
567 | });
|
568 | if (res.statusCode !== 200) {
|
569 | const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
|
570 | throw new errors_1.CouchbaseError('failed to get groups', undefined, errCtx);
|
571 | }
|
572 | const groupsData = JSON.parse(res.body.toString());
|
573 | const groups = groupsData.map((groupData) => Group._fromNsData(groupData));
|
574 | return groups;
|
575 | }, callback);
|
576 | }
|
577 | |
578 |
|
579 |
|
580 |
|
581 |
|
582 |
|
583 |
|
584 | async upsertGroup(group, options, callback) {
|
585 | if (options instanceof Function) {
|
586 | callback = arguments[1];
|
587 | options = undefined;
|
588 | }
|
589 | if (!options) {
|
590 | options = {};
|
591 | }
|
592 | const timeout = options.timeout || this._cluster.managementTimeout;
|
593 | return utilities_1.PromiseHelper.wrapAsync(async () => {
|
594 | const groupData = Group._toNsData(group);
|
595 | const res = await this._http.request({
|
596 | type: httpexecutor_1.HttpServiceType.Management,
|
597 | method: httpexecutor_1.HttpMethod.Put,
|
598 | path: `/settings/rbac/groups/${group.name}`,
|
599 | contentType: 'application/x-www-form-urlencoded',
|
600 | body: (0, utilities_1.cbQsStringify)(groupData),
|
601 | timeout: timeout,
|
602 | });
|
603 | if (res.statusCode !== 200) {
|
604 | const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
|
605 | throw new errors_1.CouchbaseError('failed to upsert group', undefined, errCtx);
|
606 | }
|
607 | }, callback);
|
608 | }
|
609 | |
610 |
|
611 |
|
612 |
|
613 |
|
614 |
|
615 |
|
616 | async dropGroup(groupName, options, callback) {
|
617 | if (options instanceof Function) {
|
618 | callback = arguments[1];
|
619 | options = undefined;
|
620 | }
|
621 | if (!options) {
|
622 | options = {};
|
623 | }
|
624 | const timeout = options.timeout || this._cluster.managementTimeout;
|
625 | return utilities_1.PromiseHelper.wrapAsync(async () => {
|
626 | const res = await this._http.request({
|
627 | type: httpexecutor_1.HttpServiceType.Management,
|
628 | method: httpexecutor_1.HttpMethod.Delete,
|
629 | path: `/settings/rbac/groups/${groupName}`,
|
630 | timeout: timeout,
|
631 | });
|
632 | if (res.statusCode !== 200) {
|
633 | const errCtx = httpexecutor_1.HttpExecutor.errorContextFromResponse(res);
|
634 | if (res.statusCode === 404) {
|
635 | throw new errors_1.GroupNotFoundError(undefined, errCtx);
|
636 | }
|
637 | throw new errors_1.CouchbaseError('failed to drop the group', undefined, errCtx);
|
638 | }
|
639 | }, callback);
|
640 | }
|
641 | }
|
642 | exports.UserManager = UserManager;
|