diff --git a/package-lock.json b/package-lock.json
index cdc92a1ba2b..d1026bd957c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,9 +11,6 @@
"configs/*",
"scripts"
],
- "dependencies": {
- "electron": "^25.9.6"
- },
"devDependencies": {
"@babel/core": "7.16.0",
"@babel/parser": "7.16.0",
@@ -47874,7 +47871,6 @@
"@mongodb-js/compass-editor": "^0.18.0",
"@mongodb-js/connection-storage": "^0.6.6",
"@testing-library/react-hooks": "^7.0.2",
- "compass-preferences-model": "^2.15.6",
"lodash": "^4.17.21",
"mongodb-build-info": "^1.7.0",
"mongodb-connection-string-url": "^2.6.0",
@@ -61010,7 +61006,6 @@
"@types/sinon-chai": "^3.2.5",
"bson": "^6.2.0",
"chai": "^4.3.4",
- "compass-preferences-model": "^2.15.6",
"depcheck": "^1.4.1",
"eslint": "^7.25.0",
"lodash": "^4.17.21",
diff --git a/packages/compass-connections/src/components/connections.tsx b/packages/compass-connections/src/components/connections.tsx
index facda69124d..1ad5effe832 100644
--- a/packages/compass-connections/src/components/connections.tsx
+++ b/packages/compass-connections/src/components/connections.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback, useState } from 'react';
+import React, { useCallback, useMemo, useState } from 'react';
import {
ImportConnectionsModal,
ExportConnectionsModal,
@@ -23,6 +23,7 @@ import { useConnections } from '../stores/connections-store';
import { cloneDeep } from 'lodash';
import ConnectionList from './connection-list/connection-list';
import { LegacyConnectionsModal } from './legacy-connections-modal';
+import { usePreference } from 'compass-preferences-model';
const { log, mongoLogId } = createLoggerAndTelemetry(
'mongodb-compass:connections:connections'
@@ -123,6 +124,47 @@ function Connections({
[]
);
+ const protectConnectionStrings = usePreference(
+ 'protectConnectionStrings',
+ React
+ );
+ const forceConnectionOptions = usePreference('forceConnectionOptions', React);
+ const showKerberosPasswordField = usePreference(
+ 'showKerberosPasswordField',
+ React
+ );
+ const showOIDCDeviceAuthFlow = usePreference('showOIDCDeviceAuthFlow', React);
+ const enableOidc = usePreference('enableOidc', React);
+ const enableDebugUseCsfleSchemaMap = usePreference(
+ 'enableDebugUseCsfleSchemaMap',
+ React
+ );
+ const protectConnectionStringsForNewConnections = usePreference(
+ 'protectConnectionStringsForNewConnections',
+ React
+ );
+
+ const preferences = useMemo(
+ () => ({
+ protectConnectionStrings,
+ forceConnectionOptions,
+ showKerberosPasswordField,
+ showOIDCDeviceAuthFlow,
+ enableOidc,
+ enableDebugUseCsfleSchemaMap,
+ protectConnectionStringsForNewConnections,
+ }),
+ [
+ protectConnectionStrings,
+ forceConnectionOptions,
+ showKerberosPasswordField,
+ showOIDCDeviceAuthFlow,
+ enableOidc,
+ enableDebugUseCsfleSchemaMap,
+ protectConnectionStringsForNewConnections,
+ ]
+ );
+
return (
@@ -166,6 +208,7 @@ function Connections({
onSaveConnectionClicked={saveConnection}
initialConnectionInfo={activeConnectionInfo}
connectionErrorMessage={connectionErrorMessage}
+ preferences={preferences}
/>
diff --git a/packages/compass-connections/src/stores/connections-store.ts b/packages/compass-connections/src/stores/connections-store.ts
index d424043c0d3..3f3212b0b8a 100644
--- a/packages/compass-connections/src/stores/connections-store.ts
+++ b/packages/compass-connections/src/stores/connections-store.ts
@@ -541,11 +541,15 @@ export function useConnections({
};
}
+ const { forceConnectionOptions = [], browserCommandForOIDCAuth } =
+ preferences.getPreferences();
+
const newConnectionDataService = await newConnectionAttempt.connect(
adjustConnectionOptionsBeforeConnect({
connectionOptions: connectionInfo.connectionOptions,
defaultAppName: appName,
notifyDeviceFlow,
+ preferences: { forceConnectionOptions, browserCommandForOIDCAuth },
})
);
connectingConnectionAttempt.current = undefined;
diff --git a/packages/connection-form/package.json b/packages/connection-form/package.json
index 498a7edbcea..4ee8f2794ff 100644
--- a/packages/connection-form/package.json
+++ b/packages/connection-form/package.json
@@ -56,7 +56,6 @@
"@mongodb-js/compass-editor": "^0.18.0",
"@mongodb-js/connection-storage": "^0.6.6",
"@testing-library/react-hooks": "^7.0.2",
- "compass-preferences-model": "^2.15.6",
"lodash": "^4.17.21",
"mongodb-build-info": "^1.7.0",
"mongodb-connection-string-url": "^2.6.0",
diff --git a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.spec.tsx b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.spec.tsx
index 36736c14b02..ffbe3284c12 100644
--- a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.spec.tsx
+++ b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.spec.tsx
@@ -3,11 +3,11 @@ import { render, screen, fireEvent, cleanup } from '@testing-library/react';
import { expect } from 'chai';
import sinon from 'sinon';
import ConnectionStringUrl from 'mongodb-connection-string-url';
-import preferences from 'compass-preferences-model';
import AuthenticationGssapi from './authentication-gssapi';
import type { ConnectionFormError } from '../../../utils/validation';
import type { UpdateConnectionFormField } from '../../../hooks/use-connect-form';
+import { ConnectionFormPreferencesContext } from '../../../hooks/use-connect-form-preferences';
function renderComponent({
errors = [],
@@ -19,11 +19,15 @@ function renderComponent({
updateConnectionFormField: UpdateConnectionFormField;
}) {
render(
-
+
+
+
);
}
@@ -172,19 +176,6 @@ describe('AuthenticationGssapi Component', function () {
});
describe('Kerberos password support', function () {
- let sandbox: sinon.SinonSandbox;
-
- before(function () {
- sandbox = sinon.createSandbox();
- sandbox
- .stub(preferences, 'getPreferences')
- .returns({ showKerberosPasswordField: true } as any);
- });
-
- after(function () {
- return sandbox.restore();
- });
-
describe('when password is not in the connection string', function () {
beforeEach(function () {
renderComponent({
diff --git a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.tsx b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.tsx
index 8c841090224..88c9feecb44 100644
--- a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.tsx
+++ b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.tsx
@@ -7,7 +7,6 @@ import {
RadioBox,
Checkbox,
} from '@mongodb-js/compass-components';
-import { usePreference } from 'compass-preferences-model';
import type ConnectionStringUrl from 'mongodb-connection-string-url';
import type { UpdateConnectionFormField } from '../../../hooks/use-connect-form';
@@ -18,6 +17,7 @@ import {
getConnectionStringUsername,
parseAuthMechanismProperties,
} from '../../../utils/connection-string-helpers';
+import { useConnectionFormPreference } from '../../../hooks/use-connect-form-preferences';
const GSSAPI_CANONICALIZE_HOST_NAME_OPTIONS: Record<
string,
@@ -56,9 +56,8 @@ function AuthenticationGSSAPI({
const [showPassword, setShowPassword] = useState(false);
- const showKerberosPasswordField = !!usePreference(
- 'showKerberosPasswordField',
- React
+ const showKerberosPasswordField = !!useConnectionFormPreference(
+ 'showKerberosPasswordField'
);
useEffect(() => {
diff --git a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.spec.tsx b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.spec.tsx
index 9c5c55173e9..b8c93f646e2 100644
--- a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.spec.tsx
+++ b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.spec.tsx
@@ -9,13 +9,15 @@ import {
import { expect } from 'chai';
import sinon from 'sinon';
import type { ConnectionOptions } from 'mongodb-data-service';
-import preferences from 'compass-preferences-model';
import ConnectionForm from '../../../';
const deviceAuthFlowText = 'Enable Device Authentication Flow';
-async function renderConnectionForm(connectSpy) {
+async function renderConnectionForm(
+ connectSpy,
+ { showOIDCDeviceAuthFlow }: { showOIDCDeviceAuthFlow: boolean }
+) {
render(
{
connectSpy(connectionInfo.connectionOptions);
}}
+ preferences={{ enableOidc: true, showOIDCDeviceAuthFlow }}
/>
);
@@ -55,23 +58,10 @@ const openOptionsAccordion = () =>
describe('AuthenticationOIDC Connection Form', function () {
let expectToConnectWith;
- let sandbox: sinon.SinonSandbox;
- let getPreferencesStub: sinon.SinonStub;
let connectSpy: sinon.SinonSpy;
beforeEach(function () {
connectSpy = sinon.spy();
-
- sandbox = sinon.createSandbox();
- getPreferencesStub = sinon.stub();
- getPreferencesStub.returns({
- enableOidc: true,
- });
- // TODO(COMPASS-6803): Remove feature flag, remove this sandbox.
- sandbox
- .stub(preferences, 'getPreferences')
- .callsFake(() => getPreferencesStub());
-
expectToConnectWith = async (
expected: ConnectionOptions | ((ConnectionOptions) => void)
): Promise => {
@@ -93,14 +83,14 @@ describe('AuthenticationOIDC Connection Form', function () {
}
};
});
+
afterEach(function () {
- sandbox.restore();
cleanup();
});
describe('when rendered', function () {
beforeEach(async function () {
- await renderConnectionForm(connectSpy);
+ await renderConnectionForm(connectSpy, { showOIDCDeviceAuthFlow: false });
});
it('handles principal (username) changes', async function () {
@@ -156,12 +146,7 @@ describe('AuthenticationOIDC Connection Form', function () {
describe('when rendered and the showOIDCDeviceAuthFlow setting is enabled', function () {
beforeEach(async function () {
- getPreferencesStub.returns({
- enableOidc: true,
- showOIDCDeviceAuthFlow: true,
- });
-
- await renderConnectionForm(connectSpy);
+ await renderConnectionForm(connectSpy, { showOIDCDeviceAuthFlow: true });
});
it('handles the enable device authentication flow checkbox', async function () {
diff --git a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.tsx b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.tsx
index 318f11f07a2..9ac91596774 100644
--- a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.tsx
+++ b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.tsx
@@ -9,13 +9,13 @@ import {
} from '@mongodb-js/compass-components';
import type ConnectionStringUrl from 'mongodb-connection-string-url';
import type { ConnectionOptions } from 'mongodb-data-service';
-import { usePreference } from 'compass-preferences-model';
import type { UpdateConnectionFormField } from '../../../hooks/use-connect-form';
import type { ConnectionFormError } from '../../../utils/validation';
import { errorMessageByFieldName } from '../../../utils/validation';
import { getConnectionStringUsername } from '../../../utils/connection-string-helpers';
import type { OIDCOptions } from '../../../utils/oidc-handler';
+import { useConnectionFormPreference } from '../../../hooks/use-connect-form-preferences';
type AuthFlowType = NonNullable[number];
@@ -47,9 +47,8 @@ function AuthenticationOIDC({
const hasEnabledDeviceAuthFlow =
!!connectionOptions.oidc?.allowedFlows?.includes?.('device-auth');
- const showOIDCDeviceAuthFlow = !!usePreference(
- 'showOIDCDeviceAuthFlow',
- React
+ const showOIDCDeviceAuthFlow = !!useConnectionFormPreference(
+ 'showOIDCDeviceAuthFlow'
);
return (
diff --git a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-tab.tsx b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-tab.tsx
index 9cd54f5f37b..3e321ac85e1 100644
--- a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-tab.tsx
+++ b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-tab.tsx
@@ -9,7 +9,6 @@ import {
} from '@mongodb-js/compass-components';
import type ConnectionStringUrl from 'mongodb-connection-string-url';
import { AuthMechanism } from 'mongodb';
-import { usePreference } from 'compass-preferences-model';
import type { ConnectionOptions } from 'mongodb-data-service';
import type { UpdateConnectionFormField } from '../../../hooks/use-connect-form';
@@ -21,6 +20,7 @@ import AuthenticationGSSAPI from './authentication-gssapi';
import AuthenticationPlain from './authentication-plain';
import AuthenticationAWS from './authentication-aws';
import AuthenticationOidc from './authentication-oidc';
+import { useConnectionFormPreference } from '../../../hooks/use-connect-form-preferences';
type AUTH_TABS =
| 'DEFAULT' // Username/Password (SCRAM-SHA-1 + SCRAM-SHA-256 + DEFAULT)
@@ -108,7 +108,7 @@ function AuthenticationTab({
updateConnectionFormField: UpdateConnectionFormField;
connectionOptions: ConnectionOptions;
}): React.ReactElement {
- const enableOIDC = !!usePreference('enableOidc', React);
+ const enableOIDC = !!useConnectionFormPreference('enableOidc');
const enabledAuthOptions = useMemo(() => {
if (enableOIDC) {
return options;
diff --git a/packages/connection-form/src/components/advanced-options-tabs/csfle-tab/csfle-tab.tsx b/packages/connection-form/src/components/advanced-options-tabs/csfle-tab/csfle-tab.tsx
index 39b4e59c3b3..bd02f2eec32 100644
--- a/packages/connection-form/src/components/advanced-options-tabs/csfle-tab/csfle-tab.tsx
+++ b/packages/connection-form/src/components/advanced-options-tabs/csfle-tab/csfle-tab.tsx
@@ -32,7 +32,7 @@ import type {
KMSField,
} from '../../../utils/csfle-kms-fields';
import { KMSProviderFields } from '../../../utils/csfle-kms-fields';
-import { usePreference } from 'compass-preferences-model';
+import { useConnectionFormPreference } from '../../../hooks/use-connect-form-preferences';
const kmsProviderComponentWrapperStyles = css({
paddingLeft: spacing[3],
@@ -96,9 +96,8 @@ function CSFLETab({
const autoEncryptionOptions =
connectionOptions.fleOptions?.autoEncryption ?? {};
- const enableSchemaMapDebugFlag = usePreference(
- 'enableDebugUseCsfleSchemaMap',
- React
+ const enableSchemaMapDebugFlag = useConnectionFormPreference(
+ 'enableDebugUseCsfleSchemaMap'
);
const errors = errorsByFieldTab(errors_, 'csfle');
diff --git a/packages/connection-form/src/components/connection-form.spec.tsx b/packages/connection-form/src/components/connection-form.spec.tsx
index 6ee691b2b6f..ab0c6a666bd 100644
--- a/packages/connection-form/src/components/connection-form.spec.tsx
+++ b/packages/connection-form/src/components/connection-form.spec.tsx
@@ -11,7 +11,6 @@ import { expect } from 'chai';
import ConnectionForm from './connection-form';
import type { ConnectionFormProps } from './connection-form';
import Sinon from 'sinon';
-import preferences from 'compass-preferences-model';
import { defaultConnectionString } from '../constants/default-connection';
import type { ConnectionInfo } from '@mongodb-js/connection-storage/renderer';
@@ -82,14 +81,14 @@ describe('ConnectionForm Component', function () {
'and preferences.protectConnectionStrings === false',
function () {
it('should render the toggle button in the off state for default connection', function () {
- sandbox.stub(preferences, 'getPreferences').callsFake(() => {
- return {
+ renderForm({
+ initialConnectionInfo: DEFAULT_CONNECTION,
+ preferences: {
protectConnectionStringsForNewConnections: true,
protectConnectionStrings: false,
- } as any;
+ },
});
- renderForm({ initialConnectionInfo: DEFAULT_CONNECTION });
expect(screen.queryByTestId('toggle-edit-connection-string')).to
.not.be.null;
expect(
@@ -100,14 +99,12 @@ describe('ConnectionForm Component', function () {
});
it('should render the toggle button in the off state for existing connection', function () {
- sandbox.stub(preferences, 'getPreferences').callsFake(() => {
- return {
+ renderForm({
+ preferences: {
protectConnectionStringsForNewConnections: true,
protectConnectionStrings: false,
- } as any;
+ },
});
-
- renderForm();
expect(screen.queryByTestId('toggle-edit-connection-string')).to
.not.be.null;
expect(
@@ -123,14 +120,13 @@ describe('ConnectionForm Component', function () {
'and preferences.protectConnectionStrings === true',
function () {
it('should render the toggle button in the off state for default connection', function () {
- sandbox.stub(preferences, 'getPreferences').callsFake(() => {
- return {
+ renderForm({
+ initialConnectionInfo: DEFAULT_CONNECTION,
+ preferences: {
protectConnectionStringsForNewConnections: true,
protectConnectionStrings: true,
- } as any;
+ },
});
-
- renderForm({ initialConnectionInfo: DEFAULT_CONNECTION });
expect(screen.queryByTestId('toggle-edit-connection-string')).to
.not.be.null;
expect(
@@ -141,14 +137,12 @@ describe('ConnectionForm Component', function () {
});
it('should not render the toggle button for existing connection', function () {
- sandbox.stub(preferences, 'getPreferences').callsFake(() => {
- return {
+ renderForm({
+ preferences: {
protectConnectionStringsForNewConnections: true,
protectConnectionStrings: true,
- } as any;
+ },
});
-
- renderForm();
expect(screen.queryByTestId('toggle-edit-connection-string')).to
.be.null;
});
@@ -164,14 +158,13 @@ describe('ConnectionForm Component', function () {
'and preferences.protectConnectionStrings === false',
function () {
it('should render the toggle button in the on state for default connection', function () {
- sandbox.stub(preferences, 'getPreferences').callsFake(() => {
- return {
+ renderForm({
+ initialConnectionInfo: DEFAULT_CONNECTION,
+ preferences: {
protectConnectionStringsForNewConnections: false,
protectConnectionStrings: false,
- } as any;
+ },
});
-
- renderForm({ initialConnectionInfo: DEFAULT_CONNECTION });
expect(screen.queryByTestId('toggle-edit-connection-string')).to
.not.be.null;
expect(
@@ -182,14 +175,12 @@ describe('ConnectionForm Component', function () {
});
it('should render the toggle button in the off state for existing connection', function () {
- sandbox.stub(preferences, 'getPreferences').callsFake(() => {
- return {
+ renderForm({
+ preferences: {
protectConnectionStringsForNewConnections: false,
protectConnectionStrings: false,
- } as any;
+ },
});
-
- renderForm();
expect(screen.queryByTestId('toggle-edit-connection-string')).to
.not.be.null;
expect(
@@ -205,14 +196,13 @@ describe('ConnectionForm Component', function () {
'and preferences.protectConnectionStrings === true',
function () {
it('should render the toggle button in the on state for default connection', function () {
- sandbox.stub(preferences, 'getPreferences').callsFake(() => {
- return {
+ renderForm({
+ initialConnectionInfo: DEFAULT_CONNECTION,
+ preferences: {
protectConnectionStringsForNewConnections: false,
protectConnectionStrings: true,
- } as any;
+ },
});
-
- renderForm({ initialConnectionInfo: DEFAULT_CONNECTION });
expect(screen.queryByTestId('toggle-edit-connection-string')).to
.not.be.null;
expect(
@@ -223,14 +213,12 @@ describe('ConnectionForm Component', function () {
});
it('should not render the toggle button for existing connection', function () {
- sandbox.stub(preferences, 'getPreferences').callsFake(() => {
- return {
+ renderForm({
+ preferences: {
protectConnectionStringsForNewConnections: false,
protectConnectionStrings: true,
- } as any;
+ },
});
-
- renderForm();
expect(screen.queryByTestId('toggle-edit-connection-string')).to
.be.null;
});
diff --git a/packages/connection-form/src/components/connection-form.tsx b/packages/connection-form/src/components/connection-form.tsx
index 2b219aded14..31bcaf7cb14 100644
--- a/packages/connection-form/src/components/connection-form.tsx
+++ b/packages/connection-form/src/components/connection-form.tsx
@@ -28,7 +28,11 @@ import ConnectionFormActions from './connection-form-actions';
import { useConnectForm } from '../hooks/use-connect-form';
import { validateConnectionOptionsErrors } from '../utils/validation';
import SaveConnectionModal from './save-connection-modal';
-import { usePreference } from 'compass-preferences-model';
+import type { ConnectionFormPreferences } from '../hooks/use-connect-form-preferences';
+import {
+ ConnectionFormPreferencesContext,
+ useConnectionFormPreference,
+} from '../hooks/use-connect-form-preferences';
const formContainerStyles = css({
margin: 0,
@@ -116,7 +120,7 @@ const connectionStringErrorStyles = css({
marginBottom: spacing[3],
});
-export type ConnectionFormProps = {
+type ConnectionFormPropsWithoutPreferences = {
darkMode?: boolean;
initialConnectionInfo: ConnectionInfo;
connectionErrorMessage?: string | null;
@@ -124,6 +128,10 @@ export type ConnectionFormProps = {
onSaveConnectionClicked?: (connectionInfo: ConnectionInfo) => Promise;
};
+export type ConnectionFormProps = ConnectionFormPropsWithoutPreferences & {
+ preferences?: Partial;
+};
+
function ConnectionForm({
initialConnectionInfo,
connectionErrorMessage,
@@ -131,7 +139,7 @@ function ConnectionForm({
// The connect form will not always used in an environment where
// the connection info can be saved.
onSaveConnectionClicked,
-}: ConnectionFormProps): React.ReactElement {
+}: ConnectionFormPropsWithoutPreferences): React.ReactElement {
const darkMode = useDarkMode();
const [
@@ -151,12 +159,14 @@ function ConnectionForm({
const [saveConnectionModal, setSaveConnectionModal] =
useState('hidden');
const protectConnectionStrings =
- !!usePreference('protectConnectionStrings', React) &&
+ !!useConnectionFormPreference('protectConnectionStrings') &&
!allowEditingIfProtected;
const enableEditingConnectionString =
_enableEditingConnectionString && !protectConnectionStrings;
- const forceConnectionOptions = usePreference('forceConnectionOptions', React);
+ const forceConnectionOptions = useConnectionFormPreference(
+ 'forceConnectionOptions'
+ );
const warnings = useMemo(() => {
if (!forceConnectionOptions?.length) return _warnings;
const overriddenKeys = forceConnectionOptions.map(([key]) => key);
@@ -368,4 +378,18 @@ function ConnectionForm({
);
}
-export default ConnectionForm;
+const ConnectionFormWithPreferences = (
+ props: ConnectionFormPropsWithoutPreferences & {
+ preferences?: Partial;
+ }
+) => {
+ const { preferences, ...rest } = props;
+
+ return (
+
+
+
+ );
+};
+
+export default ConnectionFormWithPreferences;
diff --git a/packages/connection-form/src/hooks/use-connect-form-preferences.tsx b/packages/connection-form/src/hooks/use-connect-form-preferences.tsx
new file mode 100644
index 00000000000..6503b61345f
--- /dev/null
+++ b/packages/connection-form/src/hooks/use-connect-form-preferences.tsx
@@ -0,0 +1,35 @@
+import { createContext, useContext } from 'react';
+
+export type ConnectionFormPreferences = {
+ protectConnectionStrings: boolean;
+ forceConnectionOptions: [key: string, value: string][];
+ showKerberosPasswordField: boolean;
+ showOIDCDeviceAuthFlow: boolean;
+ enableOidc: boolean;
+ enableDebugUseCsfleSchemaMap: boolean;
+ protectConnectionStringsForNewConnections: boolean;
+};
+
+const defaultPreferences = {
+ protectConnectionStrings: false,
+ forceConnectionOptions: [],
+ showKerberosPasswordField: false,
+ showOIDCDeviceAuthFlow: false,
+ enableOidc: false,
+ enableDebugUseCsfleSchemaMap: false,
+ protectConnectionStringsForNewConnections: false,
+};
+
+export const ConnectionFormPreferencesContext = createContext<
+ Partial
+>({});
+
+export const useConnectionFormPreference = <
+ K extends keyof ConnectionFormPreferences
+>(
+ preferenceKey: K
+): ConnectionFormPreferences[K] => {
+ const preferences = useContext(ConnectionFormPreferencesContext);
+
+ return preferences[preferenceKey] ?? defaultPreferences[preferenceKey];
+};
diff --git a/packages/connection-form/src/hooks/use-connect-form.ts b/packages/connection-form/src/hooks/use-connect-form.ts
index c75a208b36f..5e711295e33 100644
--- a/packages/connection-form/src/hooks/use-connect-form.ts
+++ b/packages/connection-form/src/hooks/use-connect-form.ts
@@ -1,11 +1,9 @@
-import type { Dispatch } from 'react';
-import React, { useCallback, useEffect, useReducer } from 'react';
+import { useReducer, type Dispatch, useCallback, useEffect } from 'react';
import type { ConnectionOptions } from 'mongodb-data-service';
import type { ConnectionInfo } from '@mongodb-js/connection-storage/renderer';
import type { MongoClientOptions, ProxyOptions } from 'mongodb';
import { cloneDeep, isEqual } from 'lodash';
import type ConnectionStringUrl from 'mongodb-connection-string-url';
-import { usePreference } from 'compass-preferences-model';
import type {
ConnectionFormError,
@@ -62,6 +60,7 @@ import {
import type { UpdateOIDCAction } from '../utils/oidc-handler';
import { setAppNameParamIfMissing } from '../utils/set-app-name-if-missing';
import { applyForceConnectionOptions } from '../utils/force-connection-options';
+import { useConnectionFormPreference } from './use-connect-form-preferences';
export interface ConnectFormState {
connectionOptions: ConnectionOptions;
@@ -577,8 +576,9 @@ export function useConnectForm(
const initialFormState: ConnectFormState = {
...derivedFormState,
enableEditingConnectionString:
- !usePreference('protectConnectionStringsForNewConnections', React) &&
- derivedFormState.enableEditingConnectionString,
+ !useConnectionFormPreference(
+ 'protectConnectionStringsForNewConnections'
+ ) && derivedFormState.enableEditingConnectionString,
};
const [state, dispatch] = useReducer(connectFormReducer, initialFormState);
@@ -653,9 +653,8 @@ function setInitialState({
setErrors: (errors: ConnectionFormError[]) => void;
dispatch: Dispatch;
}) {
- const protectConnectionStringsForNewConnections = usePreference(
- 'protectConnectionStringsForNewConnections',
- React
+ const protectConnectionStringsForNewConnections = useConnectionFormPreference(
+ 'protectConnectionStringsForNewConnections'
);
useEffect(() => {
// When the initial connection options change, like a different
@@ -696,6 +695,7 @@ export function adjustConnectionOptionsBeforeConnect({
connectionOptions,
defaultAppName,
notifyDeviceFlow,
+ preferences,
}: {
connectionOptions: Readonly;
defaultAppName?: string;
@@ -703,14 +703,21 @@ export function adjustConnectionOptionsBeforeConnect({
verificationUrl: string;
userCode: string;
}) => void;
+ preferences: {
+ browserCommandForOIDCAuth?: string;
+ forceConnectionOptions: [string, string][];
+ };
}): ConnectionOptions {
const transformers: ((
connectionOptions: Readonly
) => ConnectionOptions)[] = [
adjustCSFLEParams,
setAppNameParamIfMissing(defaultAppName),
- adjustOIDCConnectionOptionsBeforeConnect(notifyDeviceFlow),
- applyForceConnectionOptions,
+ adjustOIDCConnectionOptionsBeforeConnect({
+ browserCommandForOIDCAuth: preferences.browserCommandForOIDCAuth,
+ notifyDeviceFlow,
+ }),
+ applyForceConnectionOptions(preferences.forceConnectionOptions),
];
for (const transformer of transformers) {
connectionOptions = transformer(connectionOptions);
diff --git a/packages/connection-form/src/utils/force-connection-options.spec.ts b/packages/connection-form/src/utils/force-connection-options.spec.ts
index 83925a31b51..8bfde33e17e 100644
--- a/packages/connection-form/src/utils/force-connection-options.spec.ts
+++ b/packages/connection-form/src/utils/force-connection-options.spec.ts
@@ -1,24 +1,17 @@
import { expect } from 'chai';
import { applyForceConnectionOptions } from './force-connection-options';
-import type { AllPreferences } from 'compass-preferences-model';
-import preferences from 'compass-preferences-model';
import sinon from 'sinon';
import type { ConnectionOptions } from 'mongodb-data-service';
describe('applyForceConnectionOptions', function () {
let sandbox: sinon.SinonSandbox;
let options: ConnectionOptions;
- let prefs: Partial;
beforeEach(function () {
sandbox = sinon.createSandbox();
options = {
connectionString: 'mongodb://localhost/',
};
- prefs = {};
- sandbox
- .stub(preferences, 'getPreferences')
- .returns(prefs as AllPreferences);
});
afterEach(function () {
@@ -26,42 +19,48 @@ describe('applyForceConnectionOptions', function () {
});
it('does not change options by default', function () {
- expect(applyForceConnectionOptions(options)).to.deep.equal(options);
+ expect(applyForceConnectionOptions([])(options)).to.deep.equal(options);
});
it('overrides set username and password', function () {
options.connectionString = 'mongodb://a:b@localhost/';
- prefs.forceConnectionOptions = [
- ['username', 'user'],
- ['password', 's€cr!t'],
- ];
- expect(applyForceConnectionOptions(options)).to.deep.equal({
+
+ expect(
+ applyForceConnectionOptions([
+ ['username', 'user'],
+ ['password', 's€cr!t'],
+ ])(options)
+ ).to.deep.equal({
connectionString: 'mongodb://user:s%E2%82%ACcr!t@localhost/',
});
});
it('url-encodes username and password', function () {
options.connectionString = 'mongodb://a:b@localhost/';
- prefs.forceConnectionOptions = [
- ['username', 'user'],
- ['password', 's%22'], // this only makes a difference in already-url-encoded cases
- ];
- expect(applyForceConnectionOptions(options)).to.deep.equal({
+ expect(
+ applyForceConnectionOptions([
+ ['username', 'user'],
+ ['password', 's%22'], // this only makes a difference in already-url-encoded cases
+ ])(options)
+ ).to.deep.equal({
connectionString: 'mongodb://user:s%2522@localhost/',
});
});
it('can set connection string options', function () {
- prefs.forceConnectionOptions = [['readPreference', 'secondary']];
- expect(applyForceConnectionOptions(options)).to.deep.equal({
+ expect(
+ applyForceConnectionOptions([['readPreference', 'secondary']])(options)
+ ).to.deep.equal({
connectionString: 'mongodb://localhost/?readPreference=secondary',
});
});
it('can override connection string options', function () {
options.connectionString = 'mongodb://localhost/?readPreference=primary';
- prefs.forceConnectionOptions = [['readPreference', 'secondary']];
- expect(applyForceConnectionOptions(options)).to.deep.equal({
+
+ expect(
+ applyForceConnectionOptions([['readPreference', 'secondary']])(options)
+ ).to.deep.equal({
connectionString: 'mongodb://localhost/?readPreference=secondary',
});
});
@@ -69,13 +68,14 @@ describe('applyForceConnectionOptions', function () {
it('can override and set repeated connection string options', function () {
options.connectionString =
'mongodb://localhost/?readPreference=primary&READPREFERENCETAGS=nodeType:NONE';
- prefs.forceConnectionOptions = [
- ['readPreference', 'secondary'],
- ['readPreferenceTags', 'nodeType:ANALYTICS'],
- ['readPreferenceTags', 'nodeType:READ_ONLY'],
- ];
- expect(applyForceConnectionOptions(options)).to.deep.equal({
+ expect(
+ applyForceConnectionOptions([
+ ['readPreference', 'secondary'],
+ ['readPreferenceTags', 'nodeType:ANALYTICS'],
+ ['readPreferenceTags', 'nodeType:READ_ONLY'],
+ ])(options)
+ ).to.deep.equal({
connectionString:
'mongodb://localhost/?readPreference=secondary&readPreferenceTags=nodeType%3AANALYTICS&readPreferenceTags=nodeType%3AREAD_ONLY',
});
diff --git a/packages/connection-form/src/utils/force-connection-options.ts b/packages/connection-form/src/utils/force-connection-options.ts
index eedbf01f04f..6fc3baef9f6 100644
--- a/packages/connection-form/src/utils/force-connection-options.ts
+++ b/packages/connection-form/src/utils/force-connection-options.ts
@@ -1,4 +1,3 @@
-import preferences from 'compass-preferences-model';
import { ConnectionString } from 'mongodb-connection-string-url';
import type { ConnectionOptions } from 'mongodb-data-service';
@@ -7,22 +6,23 @@ function isSpecialKey(key: string): key is 'username' | 'password' {
}
export function applyForceConnectionOptions(
- options: Readonly
-): ConnectionOptions {
- const url = new ConnectionString(options.connectionString);
- const { forceConnectionOptions = [] } = preferences.getPreferences();
+ forceConnectionOptions: [key: string, value: string][] = []
+) {
+ return (options: Readonly): ConnectionOptions => {
+ const url = new ConnectionString(options.connectionString);
- for (const [key] of forceConnectionOptions) {
- if (isSpecialKey(key)) continue;
- url.searchParams.delete(key);
- }
- for (const [key, value] of forceConnectionOptions) {
- if (isSpecialKey(key)) url[key] = encodeURIComponent(value);
- else url.searchParams.append(key, value);
- }
+ for (const [key] of forceConnectionOptions) {
+ if (isSpecialKey(key)) continue;
+ url.searchParams.delete(key);
+ }
+ for (const [key, value] of forceConnectionOptions) {
+ if (isSpecialKey(key)) url[key] = encodeURIComponent(value);
+ else url.searchParams.append(key, value);
+ }
- return {
- ...options,
- connectionString: url.toString(),
+ return {
+ ...options,
+ connectionString: url.toString(),
+ };
};
}
diff --git a/packages/connection-form/src/utils/oidc-handler.spec.ts b/packages/connection-form/src/utils/oidc-handler.spec.ts
index a2212ea87b5..ea77eb90adc 100644
--- a/packages/connection-form/src/utils/oidc-handler.spec.ts
+++ b/packages/connection-form/src/utils/oidc-handler.spec.ts
@@ -1,6 +1,4 @@
import { expect } from 'chai';
-import sinon from 'sinon';
-import preferences from 'compass-preferences-model';
import {
adjustOIDCConnectionOptionsBeforeConnect,
@@ -68,9 +66,9 @@ describe('#adjustOIDCConnectionOptionsBeforeConnect', function () {
it('returns oidc options with notify device flow when supplied', function () {
const notifyDeviceFlowMock = () => {};
- const result = adjustOIDCConnectionOptionsBeforeConnect(
- notifyDeviceFlowMock
- )({
+ const result = adjustOIDCConnectionOptionsBeforeConnect({
+ notifyDeviceFlow: notifyDeviceFlowMock,
+ })({
connectionString: 'http://localhost:27017',
useSystemCA: true,
oidc: {
@@ -89,7 +87,7 @@ describe('#adjustOIDCConnectionOptionsBeforeConnect', function () {
});
it('returns oidc options without notify device flow when not supplied', function () {
- const result = adjustOIDCConnectionOptionsBeforeConnect()({
+ const result = adjustOIDCConnectionOptionsBeforeConnect({})({
connectionString: 'http://localhost:27017',
useSystemCA: true,
oidc: {
@@ -107,27 +105,12 @@ describe('#adjustOIDCConnectionOptionsBeforeConnect', function () {
});
describe('with the `browserCommandForOIDCAuth` preference set', function () {
- let sandbox: sinon.SinonSandbox;
- let getPreferencesStub: sinon.SinonStub;
const mockBrowserCommand = '/usr/bin/browser';
- beforeEach(function () {
- sandbox = sinon.createSandbox();
- getPreferencesStub = sinon.stub();
- getPreferencesStub.returns({
- browserCommandForOIDCAuth: mockBrowserCommand,
- });
- sandbox
- .stub(preferences, 'getPreferences')
- .callsFake(() => getPreferencesStub());
- });
-
- afterEach(function () {
- sandbox.restore();
- });
-
it('returns oidc options with the browser command from settings when set', function () {
- const result = adjustOIDCConnectionOptionsBeforeConnect()({
+ const result = adjustOIDCConnectionOptionsBeforeConnect({
+ browserCommandForOIDCAuth: mockBrowserCommand,
+ })({
connectionString: 'http://localhost:27017',
useSystemCA: true,
oidc: {
diff --git a/packages/connection-form/src/utils/oidc-handler.ts b/packages/connection-form/src/utils/oidc-handler.ts
index 22bb226a94e..422d1b40b91 100644
--- a/packages/connection-form/src/utils/oidc-handler.ts
+++ b/packages/connection-form/src/utils/oidc-handler.ts
@@ -1,6 +1,5 @@
import type { ConnectionOptions } from 'mongodb-data-service';
import { cloneDeep } from 'lodash';
-import preferences from 'compass-preferences-model';
export type OIDCOptions = NonNullable;
@@ -39,15 +38,18 @@ export function handleUpdateOIDCParam({
};
}
-export function adjustOIDCConnectionOptionsBeforeConnect(
+export function adjustOIDCConnectionOptionsBeforeConnect({
+ browserCommandForOIDCAuth,
+ notifyDeviceFlow,
+}: {
+ browserCommandForOIDCAuth?: string;
notifyDeviceFlow?: (deviceFlowInformation: {
verificationUrl: string;
userCode: string;
- }) => void
-): (connectionOptions: Readonly) => ConnectionOptions {
+ }) => void;
+}): (connectionOptions: Readonly) => ConnectionOptions {
return (connectionOptions) => {
- const browserCommand =
- preferences.getPreferences().browserCommandForOIDCAuth;
+ const browserCommand = browserCommandForOIDCAuth;
return {
...cloneDeep(connectionOptions),