| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- import * as crypto from 'crypto';
- import type { Document } from '../bson';
- import type { Db } from '../db';
- import { MongoInvalidArgumentError } from '../error';
- import type { Server } from '../sdam/server';
- import type { ClientSession } from '../sessions';
- import { type Callback, emitWarningOnce, getTopology } from '../utils';
- import { CommandCallbackOperation, type CommandOperationOptions } from './command';
- import { Aspect, defineAspects } from './operation';
- /**
- * @public
- * @deprecated Use the createUser command directly instead.
- */
- export interface RoleSpecification {
- /**
- * A role grants privileges to perform sets of actions on defined resources.
- * A given role applies to the database on which it is defined and can grant access down to a collection level of granularity.
- */
- role: string;
- /** The database this user's role should effect. */
- db: string;
- }
- /**
- * @public
- * @deprecated Use the createUser command directly instead.
- */
- export interface AddUserOptions extends CommandOperationOptions {
- /** Roles associated with the created user */
- roles?: string | string[] | RoleSpecification | RoleSpecification[];
- /** Custom data associated with the user (only Mongodb 2.6 or higher) */
- customData?: Document;
- }
- /** @internal */
- export class AddUserOperation extends CommandCallbackOperation<Document> {
- override options: AddUserOptions;
- db: Db;
- username: string;
- password?: string;
- constructor(db: Db, username: string, password: string | undefined, options?: AddUserOptions) {
- super(db, options);
- this.db = db;
- this.username = username;
- this.password = password;
- this.options = options ?? {};
- }
- override executeCallback(
- server: Server,
- session: ClientSession | undefined,
- callback: Callback<Document>
- ): void {
- const db = this.db;
- const username = this.username;
- const password = this.password;
- const options = this.options;
- // Error out if digestPassword set
- // v5 removed the digestPassword option from AddUserOptions but we still want to throw
- // an error when digestPassword is provided.
- if ('digestPassword' in options && options.digestPassword != null) {
- return callback(
- new MongoInvalidArgumentError(
- 'Option "digestPassword" not supported via addUser, use db.command(...) instead'
- )
- );
- }
- let roles;
- if (!options.roles || (Array.isArray(options.roles) && options.roles.length === 0)) {
- emitWarningOnce(
- 'Creating a user without roles is deprecated. Defaults to "root" if db is "admin" or "dbOwner" otherwise'
- );
- if (db.databaseName.toLowerCase() === 'admin') {
- roles = ['root'];
- } else {
- roles = ['dbOwner'];
- }
- } else {
- roles = Array.isArray(options.roles) ? options.roles : [options.roles];
- }
- let topology;
- try {
- topology = getTopology(db);
- } catch (error) {
- return callback(error);
- }
- const digestPassword = topology.lastHello().maxWireVersion >= 7;
- let userPassword = password;
- if (!digestPassword) {
- // Use node md5 generator
- const md5 = crypto.createHash('md5');
- // Generate keys used for authentication
- md5.update(`${username}:mongo:${password}`);
- userPassword = md5.digest('hex');
- }
- // Build the command to execute
- const command: Document = {
- createUser: username,
- customData: options.customData || {},
- roles: roles,
- digestPassword
- };
- // No password
- if (typeof password === 'string') {
- command.pwd = userPassword;
- }
- super.executeCommandCallback(server, session, command, callback);
- }
- }
- defineAspects(AddUserOperation, [Aspect.WRITE_OPERATION]);
|