diff --git a/README.md b/README.md index 2c451647d..c46661aa8 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,6 @@ const mongod = new MongoMemoryServer({ dbPath?: string, // by default create in temp directory storageEngine?: string, // by default `ephemeralForTest`, available engines: [ 'ephemeralForTest', 'wiredTiger' ] replSet?: string, // by default no replica set, replica set name - auth?: boolean, // by default `mongod` is started with '--noauth', start `mongod` with '--auth' args?: string[], // by default no additional arguments, any additional command line arguments for `mongod` `mongod` (ex. ['--notablescan']) }, binary: { @@ -173,7 +172,7 @@ const replSet = new MongoMemoryReplSet({ // unless otherwise noted below these values will be in common with all instances spawned: replSet: { name, // replica set name (default: 'testset') - auth, // enable auth support? (default: false) + auth, // enable auth support? (default: undefined / disabled) args, // any args specified here will be combined with any per instance args from `instanceOpts` count, // number of additional `mongod` processes to start (will not start any extra if instanceOpts.length > replSet.count); (default: 1) dbName, // default database for db URI strings. (default: uuid.v4()) diff --git a/docs/api/interfaces/mongo-memory-server-automaticauth.md b/docs/api/interfaces/mongo-memory-server-automaticauth.md index 728101901..22ff0a9fe 100644 --- a/docs/api/interfaces/mongo-memory-server-automaticauth.md +++ b/docs/api/interfaces/mongo-memory-server-automaticauth.md @@ -7,13 +7,12 @@ API Documentation of `AutomaticAuth`-Interface ## Values -### disable +### enable -Typings: `disable?: boolean` +Typings: `enable?: boolean` Default: `false` -Disable Authentication creation. -Normally authentication is enabled when the `auth` field a object, but with this option it can be explicitly disabled. +Enable or disable Authentication creation. ### extraUsers diff --git a/docs/guides/migration/migrate9.md b/docs/guides/migration/migrate9.md index 0dd25774d..645b24b4c 100644 --- a/docs/guides/migration/migrate9.md +++ b/docs/guides/migration/migrate9.md @@ -34,7 +34,15 @@ With 9.0.0 the option `instance.auth` option is going to be ignored, because its Example: -`new MongoMemoryServer({ instance: { auth: true } })` is going to be ignored, use `new MongoMemoryServer({ auth: {} })` +`new MongoMemoryServer({ instance: { auth: true } })` is going to be ignored, use `new MongoMemoryServer({ auth: { enable: true } })` + +### `AutomaticAuth` changes + +`AutomaticAuth` has been changed to **not** be enabled anymore by just having a empty object. Also property `disable` has been removed and `enable` has been added. + +Replace `auth: {}` with `auth: { enable: true }`. +Replace `auth: { disable: true }` with `auth: { enable: false }`. +Replace `auth: { disable: false }` with `auth: { enable: true }`. ### MongoMemoryServer and MongoReplSet `.cleanup(boolean)` and `.stop(boolean)` have been removed diff --git a/packages/mongodb-memory-server-core/src/MongoMemoryReplSet.ts b/packages/mongodb-memory-server-core/src/MongoMemoryReplSet.ts index dd998aa84..1b77d67dd 100644 --- a/packages/mongodb-memory-server-core/src/MongoMemoryReplSet.ts +++ b/packages/mongodb-memory-server-core/src/MongoMemoryReplSet.ts @@ -256,11 +256,11 @@ export class MongoMemoryReplSet extends EventEmitter implements ManagerAdvanced // setting this for sanity if (typeof this._replSetOpts.auth === 'boolean') { - this._replSetOpts.auth = { disable: !this._replSetOpts.auth }; + this._replSetOpts.auth = { enable: this._replSetOpts.auth }; } - // do not set default when "disable" is "true" to save execution and memory - if (!this._replSetOpts.auth.disable) { + // only set default is enabled + if (this._replSetOpts.auth.enable) { this._replSetOpts.auth = authDefault(this._replSetOpts.auth); } } @@ -277,9 +277,9 @@ export class MongoMemoryReplSet extends EventEmitter implements ManagerAdvanced assertion(typeof this._replSetOpts.auth === 'object', new AuthNotObjectError()); - return typeof this._replSetOpts.auth.disable === 'boolean' // if "this._replSetOpts.auth.disable" is defined, use that - ? !this._replSetOpts.auth.disable // invert the disable boolean, because "auth" should only be disabled if "disabled = true" - : true; // if "this._replSetOpts.auth.disable" is not defined, default to true because "this._replSetOpts.auth" is defined + return typeof this._replSetOpts.auth.enable === 'boolean' // if "this._replSetOpts.auth.enable" is defined, use that + ? this._replSetOpts.auth.enable + : false; // if "this._replSetOpts.auth.enable" is not defined, default to false } /** diff --git a/packages/mongodb-memory-server-core/src/MongoMemoryServer.ts b/packages/mongodb-memory-server-core/src/MongoMemoryServer.ts index 8c0de1625..a167fcc45 100644 --- a/packages/mongodb-memory-server-core/src/MongoMemoryServer.ts +++ b/packages/mongodb-memory-server-core/src/MongoMemoryServer.ts @@ -44,10 +44,10 @@ export interface MongoMemoryServerOpts { export interface AutomaticAuth { /** - * Disable Automatic User creation - * @default false because when defining this object it usually means that AutomaticAuth is wanted + * Enable Automatic User creation + * @default false */ - disable?: boolean; + enable?: boolean; /** * Extra Users to create besides the root user * @default [] @@ -246,7 +246,7 @@ export class MongoMemoryServer extends EventEmitter implements ManagerAdvanced { delete (this.opts.instance as MongoMemoryInstanceOpts | undefined)?.auth; } - if (!isNullOrUndefined(this.opts.auth)) { + if (this.opts.auth?.enable === true) { // assign defaults this.auth = authDefault(this.opts.auth); } @@ -484,13 +484,6 @@ export class MongoMemoryServer extends EventEmitter implements ManagerAdvanced { if (!isNullOrUndefined(this.auth) && createAuth) { this.debug(`_startUpInstance: Running "createAuth" (force: "${this.auth.force}")`); await this.createAuth(data); - } else { - // extra "if" to log when "disable" is set to "true" - if (this.opts.auth?.disable) { - this.debug( - '_startUpInstance: AutomaticAuth.disable is set to "true" skipping "createAuth"' - ); - } } } @@ -809,9 +802,9 @@ export class MongoMemoryServer extends EventEmitter implements ManagerAdvanced { return false; } - return typeof this.auth.disable === 'boolean' // if "this._replSetOpts.auth.disable" is defined, use that - ? !this.auth.disable // invert the disable boolean, because "auth" should only be disabled if "disabled = true" - : true; // if "this._replSetOpts.auth.disable" is not defined, default to true because "this._replSetOpts.auth" is defined + return typeof this.auth.enable === 'boolean' // if "this._replSetOpts.auth.enable" is defined, use that + ? this.auth.enable + : false; // if "this._replSetOpts.auth.enable" is not defined, default to false } } diff --git a/packages/mongodb-memory-server-core/src/__tests__/MongoMemoryReplSet.test.ts b/packages/mongodb-memory-server-core/src/__tests__/MongoMemoryReplSet.test.ts index 43b5fd9bf..0ae0af3f0 100644 --- a/packages/mongodb-memory-server-core/src/__tests__/MongoMemoryReplSet.test.ts +++ b/packages/mongodb-memory-server-core/src/__tests__/MongoMemoryReplSet.test.ts @@ -238,7 +238,7 @@ describe('single server replset', () => { jest.spyOn(MongoMemoryReplSet.prototype, 'initAllServers'); jest.spyOn(console, 'warn').mockImplementationOnce(() => void 0); const replSet = await MongoMemoryReplSet.create({ - replSet: { auth: {}, count: 3, storageEngine: 'ephemeralForTest' }, + replSet: { auth: { enable: true }, count: 3, storageEngine: 'ephemeralForTest' }, }); utils.assertion(!utils.isNullOrUndefined(replSet.replSetOpts.auth)); @@ -309,7 +309,7 @@ describe('single server replset', () => { jest.spyOn(MongoMemoryReplSet.prototype, 'initAllServers'); jest.spyOn(console, 'warn').mockImplementationOnce(() => void 0); const replSet = await MongoMemoryReplSet.create({ - replSet: { auth: {}, count: 3, storageEngine: 'wiredTiger' }, + replSet: { auth: { enable: true }, count: 3, storageEngine: 'wiredTiger' }, }); async function testConnections() { @@ -429,7 +429,7 @@ describe('MongoMemoryReplSet', () => { // @ts-expect-error because "_replSetOpts" is protected expect(replSet.replSetOpts).toEqual(replSet._replSetOpts); expect(replSet.replSetOpts).toEqual({ - auth: { disable: true }, + auth: { enable: false }, args: [], name: 'testset', count: 1, @@ -444,7 +444,7 @@ describe('MongoMemoryReplSet', () => { expect(replSet.replSetOpts).toEqual(replSet._replSetOpts); const authDefault = utils.authDefault(replSet.replSetOpts.auth as AutomaticAuth); expect(replSet.replSetOpts).toEqual({ - auth: { ...authDefault, disable: false }, + auth: { ...authDefault, enable: true }, args: [], name: 'testset', count: 1, diff --git a/packages/mongodb-memory-server-core/src/__tests__/MongoMemoryServer.test.ts b/packages/mongodb-memory-server-core/src/__tests__/MongoMemoryServer.test.ts index 233fb6b91..b7f3b32b5 100644 --- a/packages/mongodb-memory-server-core/src/__tests__/MongoMemoryServer.test.ts +++ b/packages/mongodb-memory-server-core/src/__tests__/MongoMemoryServer.test.ts @@ -71,7 +71,7 @@ describe('MongoMemoryServer', () => { jest.spyOn(MongoInstance.prototype, 'start'); jest.spyOn(console, 'warn').mockImplementationOnce(() => void 0); const mongoServer = await MongoMemoryServer.create({ - auth: {}, + auth: { enable: true }, instance: { storageEngine: 'ephemeralForTest', }, @@ -133,8 +133,8 @@ describe('MongoMemoryServer', () => { await mongoServer.stop(); }); - it('should make use of "AutomaticAuth" even when "instance.auth" is not set (wiredTiger)', async () => { - jest.spyOn(MongoInstance.prototype, 'start'); + it('should not start auth when "instance.auth" is not set (wiredTiger)', async () => { + jest.spyOn(MongoInstance.prototype, 'start').mockResolvedValueOnce(); jest.spyOn(console, 'warn').mockImplementationOnce(() => void 0); const mongoServer = await MongoMemoryServer.create({ auth: {}, @@ -143,67 +143,22 @@ describe('MongoMemoryServer', () => { }, }); - utils.assertion(!utils.isNullOrUndefined(mongoServer.instanceInfo)); - utils.assertion(!utils.isNullOrUndefined(mongoServer.auth)); - - // test unpriviliged connection - { - const con = await MongoClient.connect(mongoServer.getUri()); - - const db = con.db('somedb'); - const col = db.collection('somecol'); - - try { - await col.insertOne({ test: 1 }); - fail('Expected insertion to fail'); - } catch (err) { - expect(err).toBeInstanceOf(MongoServerError); - expect((err as MongoServerError).codeName).toEqual('Unauthorized'); - } finally { - await con.close(); - } - } - - // test priviliged connection - { - const con: MongoClient = await MongoClient.connect( - utils.uriTemplate(mongoServer.instanceInfo.ip, mongoServer.instanceInfo.port, 'admin'), - { - authSource: 'admin', - authMechanism: 'SCRAM-SHA-256', - auth: { - username: mongoServer.auth.customRootName, - password: mongoServer.auth.customRootPwd, - }, - } - ); - - const admindb = con.db('admin'); - const users: { users?: { user: string }[] } = await admindb.command({ - usersInfo: mongoServer.auth.customRootName, - }); - expect(users.users).toHaveLength(1); - expect(users.users?.[0].user).toEqual(mongoServer.auth.customRootName); - - const db = con.db('somedb'); - const col = db.collection('somecol'); - - expect(await col.insertOne({ test: 1 })).toHaveProperty('acknowledged', true); - - await con.close(); - } + const args = + // @ts-expect-error "_instanceInfo" is protected + mongoServer._instanceInfo?.instance + // separator comment + .prepareCommandArgs(); - expect(MongoInstance.prototype.start).toHaveBeenCalledTimes(1); - expect(console.warn).toHaveBeenCalledTimes(0); + utils.assertion(!utils.isNullOrUndefined(args)); - await mongoServer.stop(); + expect(args.includes('--noauth')).toBeTruthy(); }); it('should make use of "AutomaticAuth" (wiredTiger)', async () => { jest.spyOn(MongoInstance.prototype, 'start'); jest.spyOn(console, 'warn').mockImplementationOnce(() => void 0); const mongoServer = await MongoMemoryServer.create({ - auth: {}, + auth: { enable: true }, instance: { storageEngine: 'wiredTiger', }, @@ -276,6 +231,7 @@ describe('MongoMemoryServer', () => { jest.spyOn(console, 'warn').mockImplementationOnce(() => void 0); const mongoServer = await MongoMemoryServer.create({ auth: { + enable: true, extraUsers: [ readOnlyUser, { @@ -402,12 +358,12 @@ describe('MongoMemoryServer', () => { await mongoServer.stop(); }); - it('"createAuth" should not be called if "disabled" is true', async () => { + it('"createAuth" should not be called if "enabled" is false', async () => { jest.spyOn(MongoInstance.prototype, 'start'); jest.spyOn(MongoMemoryServer.prototype, 'createAuth'); const mongoServer = await MongoMemoryServer.create({ auth: { - disable: true, + enable: false, }, instance: { storageEngine: 'ephemeralForTest', @@ -415,8 +371,10 @@ describe('MongoMemoryServer', () => { }); utils.assertion(!utils.isNullOrUndefined(mongoServer.instanceInfo)); - utils.assertion(!utils.isNullOrUndefined(mongoServer.auth)); - expect(mongoServer.instanceInfo.instance.prepareCommandArgs().includes('--noauth')); + utils.assertion(utils.isNullOrUndefined(mongoServer.auth)); + expect( + mongoServer.instanceInfo.instance.prepareCommandArgs().includes('--noauth') + ).toBeTruthy(); const con: MongoClient = await MongoClient.connect( utils.uriTemplate(mongoServer.instanceInfo.ip, mongoServer.instanceInfo.port, 'admin'), @@ -439,7 +397,7 @@ describe('MongoMemoryServer', () => { jest.spyOn(MongoInstance.prototype, 'start'); jest.spyOn(MongoMemoryServer.prototype, 'createAuth'); const mongoServer = new MongoMemoryServer({ - auth: {}, + auth: { enable: true }, instance: { // @ts-expect-error "auth" is removed from the type auth: false, @@ -940,7 +898,7 @@ describe('MongoMemoryServer', () => { const mongoServer = new MongoMemoryServer({ instance: { dbPath: tmpDbPath }, - auth: {}, + auth: { enable: true }, }); // @ts-expect-error "getStartOptions" is protected @@ -968,7 +926,7 @@ describe('MongoMemoryServer', () => { const mongoServer = new MongoMemoryServer({ instance: { dbPath: tmpDbPath }, - auth: {}, + auth: { enable: true }, }); // @ts-expect-error "getStartOptions" is protected @@ -1101,22 +1059,22 @@ describe('MongoMemoryServer', () => { ).toStrictEqual(false); }); - it('should with defaults return "true" if empty object OR "disable: false"', () => { + it('should with defaults return "false" if empty object OR "enable: false"', () => { { const mongoServer = new MongoMemoryServer({ auth: {} }); expect( // @ts-expect-error "authObjectEnable" is protected mongoServer.authObjectEnable() - ).toStrictEqual(true); + ).toStrictEqual(false); } { - const mongoServer = new MongoMemoryServer({ auth: { disable: false } }); + const mongoServer = new MongoMemoryServer({ auth: { enable: false } }); expect( // @ts-expect-error "authObjectEnable" is protected mongoServer.authObjectEnable() - ).toStrictEqual(true); + ).toStrictEqual(false); } }); }); diff --git a/packages/mongodb-memory-server-core/src/util/utils.ts b/packages/mongodb-memory-server-core/src/util/utils.ts index 5ed333889..4867efe7b 100644 --- a/packages/mongodb-memory-server-core/src/util/utils.ts +++ b/packages/mongodb-memory-server-core/src/util/utils.ts @@ -181,7 +181,7 @@ export async function ensureAsync(): Promise { export function authDefault(opts: AutomaticAuth): Required { return { force: false, - disable: false, + enable: true, customRootName: 'mongodb-memory-server-root', customRootPwd: 'rootuser', extraUsers: [],