diff --git a/src/cmap/connection_pool_events.ts b/src/cmap/connection_pool_events.ts index 0f56bf6bbb..92df40b7fd 100644 --- a/src/cmap/connection_pool_events.ts +++ b/src/cmap/connection_pool_events.ts @@ -28,12 +28,17 @@ export class ConnectionPoolMonitoringEvent { */ export class ConnectionPoolCreatedEvent extends ConnectionPoolMonitoringEvent { /** The options used to create this connection pool */ - options?: ConnectionPoolOptions; + options: Omit & { credentials?: Record }; /** @internal */ constructor(pool: ConnectionPool) { super(pool); - this.options = pool.options; + if (pool.options.credentials != null) { + // Intentionally remove credentials: NODE-5460 + this.options = { ...pool.options, credentials: {} }; + } else { + this.options = pool.options; + } } } diff --git a/src/operations/operation.ts b/src/operations/operation.ts index 573a896b1a..5bdd41477b 100644 --- a/src/operations/operation.ts +++ b/src/operations/operation.ts @@ -19,10 +19,6 @@ export const Aspect = { /** @public */ export type Hint = string | Document; -export interface OperationConstructor extends Function { - aspects?: Set; -} - /** @public */ export interface OperationOptions extends BSONSerializeOptions { /** Specify ClientSession for this command */ @@ -96,7 +92,7 @@ export abstract class AbstractOperation { ): void; hasAspect(aspect: symbol): boolean { - const ctor = this.constructor as OperationConstructor; + const ctor = this.constructor as { aspects?: Set }; if (ctor.aspects == null) { return false; } @@ -122,7 +118,7 @@ export abstract class AbstractOperation { } export function defineAspects( - operation: OperationConstructor, + operation: { new (...args: any[]): any }, aspects: symbol | symbol[] | Set ): Set { if (!Array.isArray(aspects) && !(aspects instanceof Set)) { diff --git a/test/integration/connection-monitoring-and-pooling/connection_monitoring_and_pooling.test.ts b/test/integration/connection-monitoring-and-pooling/connection_monitoring_and_pooling.test.ts index b76cd66a50..41a157b65e 100644 --- a/test/integration/connection-monitoring-and-pooling/connection_monitoring_and_pooling.test.ts +++ b/test/integration/connection-monitoring-and-pooling/connection_monitoring_and_pooling.test.ts @@ -1,3 +1,7 @@ +import { expect } from 'chai'; +import { once } from 'events'; + +import { MongoClient } from '../../../src'; import { loadSpecTests } from '../../spec'; import { CmapTest, runCmapTestSuite } from '../../tools/cmap_spec_runner'; @@ -16,4 +20,49 @@ describe('Connection Monitoring and Pooling (Node Driver)', function () { } ] }); + + describe('ConnectionPoolCreatedEvent', () => { + let client: MongoClient; + beforeEach(async function () { + client = this.configuration.newClient(); + }); + + afterEach(async function () { + await client.close(); + }); + + describe('constructor()', () => { + it('when auth is enabled redacts credentials from options', { + metadata: { requires: { auth: 'enabled' } }, + async test() { + const poolCreated = once(client, 'connectionPoolCreated'); + await client.connect(); + const [event] = await poolCreated; + expect(event).to.have.deep.nested.property('options.credentials', {}); + + const poolOptions = Array.from(client.topology?.s.servers.values() ?? []).map( + s => s.s.pool.options + ); + expect(poolOptions).to.have.length.of.at.least(1); + + for (const { credentials = {} } of poolOptions) { + expect( + Object.keys(credentials), + 'pool.options.credentials must exist and have keys' + ).to.not.equal(0); + } + } + }); + + it('when auth is disabled does not add a credentials property to options', { + metadata: { requires: { auth: 'disabled' } }, + async test() { + const poolCreated = once(client, 'connectionPoolCreated'); + await client.connect(); + const [event] = await poolCreated; + expect(event).to.not.have.nested.property('options.credentials'); + } + }); + }); + }); });