diff --git a/package-lock.json b/package-lock.json index 2fa967d7f79..5128b3a07c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48163,7 +48163,6 @@ "@mongodb-js/devtools-connect": "^3.2.5", "@mongodb-js/devtools-proxy-support": "^0.3.6", "bson": "^6.7.0", - "compass-preferences-model": "^2.27.0", "lodash": "^4.17.21", "mongodb": "^6.8.0", "mongodb-build-info": "^1.7.2", @@ -80670,7 +80669,6 @@ "bson": "^6.7.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", - "compass-preferences-model": "^2.27.0", "depcheck": "^1.4.1", "eslint": "^7.25.0", "kerberos": "^2.1.1", diff --git a/packages/compass-connections/src/stores/connections-store-redux.ts b/packages/compass-connections/src/stores/connections-store-redux.ts index 7453e858518..c7c2f5da7ff 100644 --- a/packages/compass-connections/src/stores/connections-store-redux.ts +++ b/packages/compass-connections/src/stores/connections-store-redux.ts @@ -18,7 +18,10 @@ import type { import { createConnectionAttempt } from 'mongodb-data-service'; import { UUID } from 'bson'; import { assign, cloneDeep, isEqual, merge } from 'lodash'; -import type { PreferencesAccess } from 'compass-preferences-model/provider'; +import { + proxyPreferenceToProxyOptions, + type PreferencesAccess, +} from 'compass-preferences-model/provider'; import { getNotificationTriggers } from '../components/connection-status-notifications'; import { openToast, showConfirmation } from '@mongodb-js/compass-components'; import { adjustConnectionOptionsBeforeConnect } from '@mongodb-js/connection-form'; @@ -1588,6 +1591,9 @@ export const connect = ( const connectionAttempt = createConnectionAttempt({ logger: log.unbound, + proxyOptions: proxyPreferenceToProxyOptions( + preferences.getPreferences().proxy + ), connectFn, }); diff --git a/packages/data-service/package.json b/packages/data-service/package.json index b9c45a27aed..477220e4788 100644 --- a/packages/data-service/package.json +++ b/packages/data-service/package.json @@ -56,7 +56,6 @@ "@mongodb-js/devtools-connect": "^3.2.5", "@mongodb-js/devtools-proxy-support": "^0.3.6", "bson": "^6.7.0", - "compass-preferences-model": "^2.27.0", "lodash": "^4.17.21", "mongodb": "^6.8.0", "mongodb-build-info": "^1.7.2", diff --git a/packages/data-service/src/connect-mongo-client.spec.ts b/packages/data-service/src/connect-mongo-client.spec.ts index a61e930c03b..dc11a07fe57 100644 --- a/packages/data-service/src/connect-mongo-client.spec.ts +++ b/packages/data-service/src/connect-mongo-client.spec.ts @@ -275,7 +275,9 @@ describe('connectMongoClient', function () { describe('prepareOIDCOptions', function () { it('defaults allowedFlows to "auth-code"', async function () { const options = prepareOIDCOptions({ - connectionString: 'mongodb://localhost:27017', + connectionOptions: { + connectionString: 'mongodb://localhost:27017', + }, }); expect(await (options.oidc.allowedFlows as any)()).to.deep.equal([ @@ -285,9 +287,11 @@ describe('prepareOIDCOptions', function () { it('does not override allowedFlows when set', async function () { const options = prepareOIDCOptions({ - connectionString: 'mongodb://localhost:27017', - oidc: { - allowedFlows: ['auth-code', 'device-auth'], + connectionOptions: { + connectionString: 'mongodb://localhost:27017', + oidc: { + allowedFlows: ['auth-code', 'device-auth'], + }, }, }); expect(await (options.oidc.allowedFlows as any)()).to.deep.equal([ @@ -299,9 +303,11 @@ describe('prepareOIDCOptions', function () { it('maps ALLOWED_HOSTS on the authMechanismProperties (non-url) when enableUntrustedEndpoints is true', function () { function actual(connectionString: string) { return prepareOIDCOptions({ - connectionString, - oidc: { - enableUntrustedEndpoints: true, + connectionOptions: { + connectionString, + oidc: { + enableUntrustedEndpoints: true, + }, }, }).authMechanismProperties; } @@ -341,7 +347,9 @@ describe('prepareOIDCOptions', function () { it('does not set ALLOWED_HOSTS on the authMechanismProperties (non-url) when enableUntrustedEndpoints is not set', function () { const options = prepareOIDCOptions({ - connectionString: 'mongodb://localhost:27017', + connectionOptions: { + connectionString: 'mongodb://localhost:27017', + }, }); expect(options.authMechanismProperties).to.deep.equal({}); @@ -349,12 +357,12 @@ describe('prepareOIDCOptions', function () { it('passes through a signal argument', function () { const signal = AbortSignal.abort(); - const options = prepareOIDCOptions( - { + const options = prepareOIDCOptions({ + connectionOptions: { connectionString: 'mongodb://localhost:27017', }, - signal - ); + signal, + }); expect(options.oidc.signal).to.equal(signal); }); diff --git a/packages/data-service/src/connect-mongo-client.ts b/packages/data-service/src/connect-mongo-client.ts index 5a10c735225..11d3c1a7495 100644 --- a/packages/data-service/src/connect-mongo-client.ts +++ b/packages/data-service/src/connect-mongo-client.ts @@ -10,18 +10,17 @@ import { hookLogger as hookProxyLogger, createAgent, } from '@mongodb-js/devtools-proxy-support'; -import type { Tunnel } from '@mongodb-js/devtools-proxy-support'; +import type { + DevtoolsProxyOptions, + Tunnel, +} from '@mongodb-js/devtools-proxy-support'; import EventEmitter from 'events'; import ConnectionString from 'mongodb-connection-string-url'; import _ from 'lodash'; import { redactConnectionOptions, redactConnectionString } from './redact'; import type { ConnectionOptions } from './connection-options'; -import { - getCurrentApplicationProxyOptions, - getTunnelOptions, - waitForTunnelError, -} from './ssh-tunnel-helpers'; +import { getTunnelOptions, waitForTunnelError } from './ssh-tunnel-helpers'; import { runCommand } from './run-command'; import type { UnboundDataServiceImplLogger } from './logger'; import { debug as _debug } from './logger'; @@ -65,11 +64,17 @@ function matchingAllowedHosts( return [...new Set(suffixes)]; } -export function prepareOIDCOptions( - connectionOptions: Readonly, - signal?: AbortSignal, - reauthenticationHandler?: ReauthenticationHandler -): Required< +export function prepareOIDCOptions({ + connectionOptions, + proxyOptions = {}, + signal, + reauthenticationHandler, +}: { + connectionOptions: Readonly; + proxyOptions?: DevtoolsProxyOptions; + signal?: AbortSignal; + reauthenticationHandler?: ReauthenticationHandler; +}): Required< Pick< DevtoolsConnectOptions, 'oidc' | 'authMechanismProperties' | 'applyProxyToOIDC' @@ -108,7 +113,7 @@ export function prepareOIDCOptions( options.applyProxyToOIDC = true; } else { options.oidc.customHttpOptions = { - agent: createAgent(getCurrentApplicationProxyOptions()), + agent: createAgent(proxyOptions), }; } @@ -119,6 +124,7 @@ export function prepareOIDCOptions( export async function connectMongoClientDataService({ connectionOptions, + proxyOptions = {}, setupListeners, signal, logger, @@ -127,6 +133,7 @@ export async function connectMongoClientDataService({ reauthenticationHandler, }: { connectionOptions: Readonly; + proxyOptions?: Readonly; setupListeners: (client: MongoClient) => void; signal?: AbortSignal; logger?: UnboundDataServiceImplLogger; @@ -147,11 +154,12 @@ export async function connectMongoClientDataService({ redactConnectionOptions(connectionOptions) ); - const oidcOptions = prepareOIDCOptions( + const oidcOptions = prepareOIDCOptions({ connectionOptions, + proxyOptions, signal, - reauthenticationHandler - ); + reauthenticationHandler, + }); const url = connectionOptions.connectionString; const options: DevtoolsConnectOptions = { @@ -189,7 +197,7 @@ export async function connectMongoClientDataService({ // If connectionOptions.sshTunnel is not defined, the tunnel // will also be undefined. const tunnel = createSocks5Tunnel( - getTunnelOptions(connectionOptions), + getTunnelOptions(connectionOptions, proxyOptions), 'generate-credentials', 'mongodb://' ); diff --git a/packages/data-service/src/connect.ts b/packages/data-service/src/connect.ts index 25c32864391..a7755e4af99 100644 --- a/packages/data-service/src/connect.ts +++ b/packages/data-service/src/connect.ts @@ -2,21 +2,28 @@ import type { ConnectionOptions } from './connection-options'; import type { DataService } from './data-service'; import type { DataServiceImplLogger } from './logger'; import { DataServiceImpl } from './data-service'; +import type { DevtoolsProxyOptions } from '@mongodb-js/devtools-proxy-support'; export default async function connect({ connectionOptions, + proxyOptions, signal, logger, productName, productDocsLink, }: { connectionOptions: ConnectionOptions; + proxyOptions?: DevtoolsProxyOptions; signal?: AbortSignal; logger?: DataServiceImplLogger; productName?: string; productDocsLink?: string; }): Promise { - const dataService = new DataServiceImpl(connectionOptions, logger); + const dataService = new DataServiceImpl( + connectionOptions, + logger, + proxyOptions + ); await dataService.connect({ signal, productName, diff --git a/packages/data-service/src/connection-attempt.ts b/packages/data-service/src/connection-attempt.ts index 9f77fd4b8c4..b370d20379f 100644 --- a/packages/data-service/src/connection-attempt.ts +++ b/packages/data-service/src/connection-attempt.ts @@ -5,6 +5,7 @@ import type { UnboundDataServiceImplLogger } from './logger'; import connect from './connect'; import type { DataService } from './data-service'; import type { ConnectionOptions } from './connection-options'; +import type { DevtoolsProxyOptions } from '@mongodb-js/devtools-proxy-support'; const { mongoLogId } = createLogger('CONNECTION-ATTEMPT'); @@ -18,16 +19,20 @@ export class ConnectionAttempt { _connectFn: typeof connect; _dataService: DataService | null = null; _logger: UnboundDataServiceImplLogger; + _proxyOptions: DevtoolsProxyOptions | undefined; constructor({ connectFn, logger, + proxyOptions, }: { connectFn: typeof connect; logger: UnboundDataServiceImplLogger; + proxyOptions?: DevtoolsProxyOptions; }) { this._logger = logger; this._connectFn = connectFn; + this._proxyOptions = proxyOptions; this._abortController = new AbortController(); } @@ -61,6 +66,7 @@ export class ConnectionAttempt { connectionOptions, signal: this._abortController.signal, logger: this._logger, + proxyOptions: this._proxyOptions, }); return this._dataService; } catch (err) { @@ -127,13 +133,16 @@ export class ConnectionAttempt { export function createConnectionAttempt({ logger, + proxyOptions, connectFn = connect, }: { logger: UnboundDataServiceImplLogger; + proxyOptions: DevtoolsProxyOptions; connectFn?: typeof connect; }): ConnectionAttempt { return new ConnectionAttempt({ logger, + proxyOptions, connectFn, }); } diff --git a/packages/data-service/src/data-service.ts b/packages/data-service/src/data-service.ts index 6d733295d62..f6c595ac145 100644 --- a/packages/data-service/src/data-service.ts +++ b/packages/data-service/src/data-service.ts @@ -1,4 +1,7 @@ -import type { Tunnel } from '@mongodb-js/devtools-proxy-support'; +import type { + DevtoolsProxyOptions, + Tunnel, +} from '@mongodb-js/devtools-proxy-support'; import { EventEmitter } from 'events'; import { ExplainVerbosity, ClientEncryption } from 'mongodb'; import type { @@ -926,6 +929,7 @@ function op( class DataServiceImpl extends WithLogContext implements DataService { private readonly _connectionOptions: Readonly; + private readonly _proxyOptions: Readonly; private _isConnecting = false; private _mongoClientConnectionOptions?: { url: string; @@ -970,11 +974,13 @@ class DataServiceImpl extends WithLogContext implements DataService { constructor( connectionOptions: Readonly, - logger?: DataServiceImplLogger + logger?: DataServiceImplLogger, + proxyOptions?: DevtoolsProxyOptions ) { super(); this._id = id++; this._connectionOptions = connectionOptions; + this._proxyOptions = proxyOptions ?? {}; const logComponent = 'COMPASS-DATA-SERVICE'; const logCtx = `Connection ${this._id}`; this._logger = { @@ -1465,6 +1471,7 @@ class DataServiceImpl extends WithLogContext implements DataService { const [metadataClient, crudClient, tunnel, state, connectionOptions] = await connectMongoClient({ connectionOptions: this._connectionOptions, + proxyOptions: this._proxyOptions, setupListeners: this._setupListeners.bind(this), signal, logger: this._unboundLogger, diff --git a/packages/data-service/src/ssh-tunnel-helpers.ts b/packages/data-service/src/ssh-tunnel-helpers.ts index 1b688f4190d..0f1422c2cf8 100644 --- a/packages/data-service/src/ssh-tunnel-helpers.ts +++ b/packages/data-service/src/ssh-tunnel-helpers.ts @@ -3,10 +3,6 @@ import type { DevtoolsProxyOptions, Tunnel, } from '@mongodb-js/devtools-proxy-support'; -import { - defaultPreferencesInstance, - proxyPreferenceToProxyOptions, -} from 'compass-preferences-model'; export async function waitForTunnelError( tunnel: Tunnel | undefined @@ -16,17 +12,12 @@ export async function waitForTunnelError( }); } -export function getCurrentApplicationProxyOptions() { - return proxyPreferenceToProxyOptions( - defaultPreferencesInstance.getPreferences().proxy - ); -} - export function getTunnelOptions( - connectionOptions: ConnectionOptions + connectionOptions: ConnectionOptions, + appLevelProxyOptions: DevtoolsProxyOptions ): DevtoolsProxyOptions { if (connectionOptions.useApplicationLevelProxy) { - return getCurrentApplicationProxyOptions(); + return appLevelProxyOptions; } if (connectionOptions.sshTunnel) { const {