From 20631f6d5fe1823b1b17a5faf95c8dbd63e45083 Mon Sep 17 00:00:00 2001 From: Anemy Date: Mon, 20 Dec 2021 16:51:16 -0500 Subject: [PATCH 1/3] Add SSL/TLS default on off radio box group --- .../advanced-options-tabs.tsx | 4 +- .../advanced-options-tabs/ssl-tab.tsx | 7 - .../tls-ssl-tab/tls-ssl-tab.spec.tsx | 258 ++++++++++++++++++ .../tls-ssl-tab/tls-ssl-tab.tsx | 125 +++++++++ .../src/constants/ssl-tls-options.ts | 5 + .../src/hooks/use-connect-form.ts | 17 +- .../src/utils/tls-options.spec.ts | 178 ++++++++++++ .../connect-form/src/utils/tls-options.ts | 41 +++ 8 files changed, 625 insertions(+), 10 deletions(-) delete mode 100644 packages/connect-form/src/components/advanced-options-tabs/ssl-tab.tsx create mode 100644 packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.spec.tsx create mode 100644 packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.tsx create mode 100644 packages/connect-form/src/constants/ssl-tls-options.ts create mode 100644 packages/connect-form/src/utils/tls-options.spec.ts create mode 100644 packages/connect-form/src/utils/tls-options.ts diff --git a/packages/connect-form/src/components/advanced-options-tabs/advanced-options-tabs.tsx b/packages/connect-form/src/components/advanced-options-tabs/advanced-options-tabs.tsx index a88e59ef7a7..58f0888f9f7 100644 --- a/packages/connect-form/src/components/advanced-options-tabs/advanced-options-tabs.tsx +++ b/packages/connect-form/src/components/advanced-options-tabs/advanced-options-tabs.tsx @@ -5,7 +5,7 @@ import ConnectionStringUrl from 'mongodb-connection-string-url'; import GeneralTab from './general-tab'; import AuthenticationTab from './authentication-tab'; -import SSLTab from './ssl-tab'; +import TLSTab from './tls-ssl-tab/tls-ssl-tab'; import SSHTunnelTab from './ssh-tunnel-tab'; import AdvancedTab from './advanced-tab'; import { UpdateConnectionFormField } from '../../hooks/use-connect-form'; @@ -40,7 +40,7 @@ function AdvancedOptionsTabs({ const tabs: TabObject[] = [ { name: 'General', component: GeneralTab }, { name: 'Authentication', component: AuthenticationTab }, - { name: 'TLS/SSL', component: SSLTab }, + { name: 'TLS/SSL', component: TLSTab }, { name: 'SSH Tunnel', component: SSHTunnelTab }, { name: 'Advanced', component: AdvancedTab }, ]; diff --git a/packages/connect-form/src/components/advanced-options-tabs/ssl-tab.tsx b/packages/connect-form/src/components/advanced-options-tabs/ssl-tab.tsx deleted file mode 100644 index 47e4b0e131c..00000000000 --- a/packages/connect-form/src/components/advanced-options-tabs/ssl-tab.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; - -function SSLTab(): React.ReactElement { - return

SSL/TLS

; -} - -export default SSLTab; diff --git a/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.spec.tsx b/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.spec.tsx new file mode 100644 index 00000000000..d5f7bec51ee --- /dev/null +++ b/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.spec.tsx @@ -0,0 +1,258 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { expect } from 'chai'; +import sinon from 'sinon'; +import ConnectionStringUrl from 'mongodb-connection-string-url'; + +import SSLTab, { getTLSOptionForConnectionString } from './tls-ssl-tab'; + +describe('SchemaInput', function () { + let updateConnectionFormFieldSpy: sinon.SinonSpy; + + beforeEach(function () { + updateConnectionFormFieldSpy = sinon.spy(); + }); + + describe('with ssl=true', function () { + beforeEach(function () { + const connectionStringUrl = new ConnectionStringUrl( + 'mongodb+srv://0ranges:p!neapp1es@localhost/?ssl=true' + ); + render( + + ); + }); + + it('should render the TLS/SSL `On` radio box selected', function () { + const tlsOnRadioBox = screen.getAllByRole('radio')[1] as HTMLInputElement; + expect(tlsOnRadioBox.checked).to.equal(true); + expect(tlsOnRadioBox.getAttribute('aria-checked')).to.equal('true'); + }); + + it('should render TLS/SSL `Default` and `Off` radio boxes not selected', function () { + const tlsDefaultRadioBox = screen.getAllByRole( + 'radio' + )[0] as HTMLInputElement; + expect(tlsDefaultRadioBox.checked).to.equal(false); + expect(tlsDefaultRadioBox.getAttribute('aria-checked')).to.equal('false'); + + const tlsOffRadioBox = screen.getAllByRole( + 'radio' + )[2] as HTMLInputElement; + expect(tlsOffRadioBox.checked).to.equal(false); + expect(tlsOffRadioBox.getAttribute('aria-checked')).to.equal('false'); + }); + + describe('when TLS/SSL default is clicked', function () { + beforeEach(function () { + const tlsDefaultRadioBox = screen.getAllByRole('radio')[0]; + fireEvent.click(tlsDefaultRadioBox); + }); + + it('should call to update the connection configuration to TLS/SSL default', function () { + expect(updateConnectionFormFieldSpy.callCount).to.equal(1); + expect(updateConnectionFormFieldSpy.firstCall.args[0]).to.deep.equal({ + type: 'update-tls-option', + tlsOption: 'DEFAULT', + }); + }); + }); + + describe('when TLS/SSL off is clicked', function () { + beforeEach(function () { + const standardSchemaRadioBox = screen.getAllByRole('radio')[2]; + fireEvent.click(standardSchemaRadioBox); + }); + + it('should call to update the connection configuration to TLS/SSL off', function () { + expect(updateConnectionFormFieldSpy.callCount).to.equal(1); + expect(updateConnectionFormFieldSpy.firstCall.args[0]).to.deep.equal({ + type: 'update-tls-option', + tlsOption: 'OFF', + }); + }); + }); + + describe('when TLS/SSL on is clicked', function () { + beforeEach(function () { + const standardSchemaRadioBox = screen.getAllByRole('radio')[1]; + fireEvent.click(standardSchemaRadioBox); + }); + + it("shouldn't call to update anything", function () { + expect(updateConnectionFormFieldSpy.callCount).to.equal(0); + }); + }); + }); + + describe('with ssl=false', function () { + beforeEach(function () { + const connectionStringUrl = new ConnectionStringUrl( + 'mongodb+srv://0ranges:p!neapp1es@localhost/?ssl=false' + ); + render( + + ); + }); + + it('should render the TLS/SSL `Off` radio box selected', function () { + const tlsOnRadioBox = screen.getAllByRole('radio')[2] as HTMLInputElement; + expect(tlsOnRadioBox.checked).to.equal(true); + expect(tlsOnRadioBox.getAttribute('aria-checked')).to.equal('true'); + }); + + describe('when TLS/SSL off is clicked', function () { + beforeEach(function () { + const standardSchemaRadioBox = screen.getAllByRole('radio')[2]; + fireEvent.click(standardSchemaRadioBox); + }); + + it("shouldn't call to update anything", function () { + expect(updateConnectionFormFieldSpy.callCount).to.equal(0); + }); + }); + + describe('when TLS/SSL on is clicked', function () { + beforeEach(function () { + const standardSchemaRadioBox = screen.getAllByRole('radio')[1]; + fireEvent.click(standardSchemaRadioBox); + }); + + it('should call to update the connection configuration to TLS/SSL on', function () { + expect(updateConnectionFormFieldSpy.callCount).to.equal(1); + expect(updateConnectionFormFieldSpy.firstCall.args[0]).to.deep.equal({ + type: 'update-tls-option', + tlsOption: 'ON', + }); + }); + }); + }); + + describe('#getTLSOptionForConnectionString', function () { + let testUrl: ConnectionStringUrl; + + beforeEach(function () { + testUrl = new ConnectionStringUrl('mongodb://localhost'); + }); + + it('should return `DEFAULT` when tls and ssl are unset', function () { + expect(getTLSOptionForConnectionString(testUrl)).to.equal('DEFAULT'); + }); + + describe('when tls is `true`', function () { + beforeEach(function () { + testUrl.searchParams.set('tls', 'true'); + }); + + it('should return `ON`', function () { + expect(getTLSOptionForConnectionString(testUrl)).to.equal('ON'); + }); + + describe('when ssl is `false`', function () { + beforeEach(function () { + testUrl.searchParams.set('ssl', 'false'); + }); + + it('should return `undefined`', function () { + expect(getTLSOptionForConnectionString(testUrl)).to.equal(undefined); + }); + }); + }); + + describe('when ssl is `true`', function () { + beforeEach(function () { + testUrl.searchParams.set('ssl', 'true'); + }); + + it('should return `ON`', function () { + expect(getTLSOptionForConnectionString(testUrl)).to.equal('ON'); + }); + + describe('when tls is `false`', function () { + beforeEach(function () { + testUrl.searchParams.set('tls', 'false'); + }); + + it('should return `undefined`', function () { + expect(getTLSOptionForConnectionString(testUrl)).to.equal(undefined); + }); + }); + + describe('when tls is `true`', function () { + beforeEach(function () { + testUrl.searchParams.set('tls', 'true'); + }); + + it('should return `ON`', function () { + expect(getTLSOptionForConnectionString(testUrl)).to.equal('ON'); + }); + }); + }); + + describe('when ssl is `false`', function () { + beforeEach(function () { + testUrl.searchParams.set('ssl', 'false'); + }); + + it('should return `OFF`', function () { + expect(getTLSOptionForConnectionString(testUrl)).to.equal('OFF'); + }); + + describe('when tls is `true`', function () { + beforeEach(function () { + testUrl.searchParams.set('tls', 'true'); + }); + + it('should return `undefined`', function () { + expect(getTLSOptionForConnectionString(testUrl)).to.equal(undefined); + }); + }); + }); + + describe('when tls is `false`', function () { + beforeEach(function () { + testUrl.searchParams.set('tls', 'false'); + }); + + it('should return `ON`', function () { + expect(getTLSOptionForConnectionString(testUrl)).to.equal('OFF'); + }); + + describe('when ssl `false`', function () { + beforeEach(function () { + testUrl.searchParams.set('ssl', 'false'); + }); + + it('should return `OFF`', function () { + expect(getTLSOptionForConnectionString(testUrl)).to.equal('OFF'); + }); + }); + }); + + describe('when tls has a value not `true` or `false`', function () { + beforeEach(function () { + testUrl.searchParams.set('ssl', 'aaaa'); + }); + + it('should return `undefined`', function () { + expect(getTLSOptionForConnectionString(testUrl)).to.equal(undefined); + }); + }); + + describe('when ssl has a value not `true` or `false`', function () { + beforeEach(function () { + testUrl.searchParams.set('ssl', 'aaaa'); + }); + + it('should return `undefined`', function () { + expect(getTLSOptionForConnectionString(testUrl)).to.equal(undefined); + }); + }); + }); +}); diff --git a/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.tsx b/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.tsx new file mode 100644 index 00000000000..64e0039605b --- /dev/null +++ b/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.tsx @@ -0,0 +1,125 @@ +import { css } from '@emotion/css'; +import React, { useCallback } from 'react'; +import { + Description, + Label, + RadioBox, + RadioBoxGroup, + spacing, +} from '@mongodb-js/compass-components'; +import ConnectionStringUrl from 'mongodb-connection-string-url'; + +import { UpdateConnectionFormField } from '../../../hooks/use-connect-form'; +import FormFieldContainer from '../../form-field-container'; +import { TLS_OPTIONS } from '../../../constants/ssl-tls-options'; + +const descriptionStyles = css({ + marginTop: spacing[1], +}); + +const TLS_TYPES = [ + { + value: TLS_OPTIONS.DEFAULT, + label: 'Default', + description: + 'Default (unset) - TLS/SSL will be used when connecting using a DNS Seed List Connection Format (mongodb+srv://) and it will not be used when connecting using a standard connection string schema format (mongodb://).', + }, + { + value: TLS_OPTIONS.ON, + label: 'On', + description: 'On - TLS/SSL is enabled for this connection.', + }, + { + value: TLS_OPTIONS.OFF, + label: 'Off', + description: 'Off - TLS/SSL is disabled for this connection.', + }, +]; + +export function getTLSOptionForConnectionString( + connectionStringUrl: ConnectionStringUrl +): TLS_OPTIONS | undefined { + if ( + connectionStringUrl.searchParams.get('ssl') === null && + connectionStringUrl.searchParams.get('tls') === null + ) { + return TLS_OPTIONS.DEFAULT; + } + + if ( + connectionStringUrl.searchParams.get('tls') === 'true' && + (connectionStringUrl.searchParams.get('ssl') === null || + connectionStringUrl.searchParams.get('ssl') === 'true') + ) { + return TLS_OPTIONS.ON; + } + + if ( + connectionStringUrl.searchParams.get('tls') === 'false' && + (connectionStringUrl.searchParams.get('ssl') === null || + connectionStringUrl.searchParams.get('ssl') === 'false') + ) { + return TLS_OPTIONS.OFF; + } + + if ( + connectionStringUrl.searchParams.get('ssl') === 'true' && + connectionStringUrl.searchParams.get('tls') === null + ) { + return TLS_OPTIONS.ON; + } + + if ( + connectionStringUrl.searchParams.get('ssl') === 'false' && + connectionStringUrl.searchParams.get('tls') === null + ) { + return TLS_OPTIONS.OFF; + } + + // When the TLS/SSL options are a mismatching pair or not `true` or `false` + // we return undefined, as we can't map it to one of our three settings, + // although it may somehow be a valid configuration. +} + +function TLSTab({ + connectionStringUrl, + updateConnectionFormField, +}: { + connectionStringUrl: ConnectionStringUrl; + updateConnectionFormField: UpdateConnectionFormField; +}): React.ReactElement { + const tlsOption = getTLSOptionForConnectionString(connectionStringUrl); + + const onChangeTLSOption = useCallback( + (event: React.ChangeEvent) => { + updateConnectionFormField({ + type: 'update-tls-option', + tlsOption: event.target.value as TLS_OPTIONS, + }); + }, + [updateConnectionFormField] + ); + + return ( +
+ + + + {TLS_TYPES.map((tlsType) => ( + + {tlsType.label} + + ))} + + + {TLS_TYPES.find((tlsType) => tlsType.value === tlsOption) + ?.description || ''} + + +
+ ); +} + +export default TLSTab; diff --git a/packages/connect-form/src/constants/ssl-tls-options.ts b/packages/connect-form/src/constants/ssl-tls-options.ts new file mode 100644 index 00000000000..11ae6cafef7 --- /dev/null +++ b/packages/connect-form/src/constants/ssl-tls-options.ts @@ -0,0 +1,5 @@ +export enum TLS_OPTIONS { + DEFAULT = 'DEFAULT', + ON = 'ON', + OFF = 'OFF', +} diff --git a/packages/connect-form/src/hooks/use-connect-form.ts b/packages/connect-form/src/hooks/use-connect-form.ts index f1461567884..c046f4f4172 100644 --- a/packages/connect-form/src/hooks/use-connect-form.ts +++ b/packages/connect-form/src/hooks/use-connect-form.ts @@ -16,6 +16,8 @@ import { defaultHostname, defaultPort } from '../constants/default-connection'; import { MARKABLE_FORM_FIELD_NAMES } from '../constants/markable-form-fields'; import { checkForInvalidCharacterInHost } from '../utils/check-for-invalid-character-in-host'; import { tryUpdateConnectionStringSchema } from '../utils/connection-string-schema'; +import { handleUpdateTlsOption } from '../utils/tls-options'; +import { TLS_OPTIONS } from '../constants/ssl-tls-options'; export interface ConnectFormState { connectionStringInvalidError: string | null; @@ -88,6 +90,11 @@ interface UpdateHostAction { newHostValue: string; } +interface UpdateTlsOptionAction { + type: 'update-tls-option'; + tlsOption: TLS_OPTIONS; +} + type ConnectionFormFieldActions = | { type: 'add-new-host'; @@ -105,7 +112,8 @@ type ConnectionFormFieldActions = | { type: 'update-connection-schema'; isSrv: boolean; - }; + } + | UpdateTlsOptionAction; export type UpdateConnectionFormField = ( action: ConnectionFormFieldActions @@ -265,6 +273,13 @@ export function handleConnectionFormFieldUpdate({ errors: [], }; } + case 'update-tls-option': { + return handleUpdateTlsOption({ + tlsOption: action.tlsOption, + connectionStringUrl, + connectionOptions, + }); + } case 'update-host': { return handleUpdateHost({ action, diff --git a/packages/connect-form/src/utils/tls-options.spec.ts b/packages/connect-form/src/utils/tls-options.spec.ts new file mode 100644 index 00000000000..fcbad17b344 --- /dev/null +++ b/packages/connect-form/src/utils/tls-options.spec.ts @@ -0,0 +1,178 @@ +import { expect } from 'chai'; +import ConnectionStringUrl from 'mongodb-connection-string-url'; +import { TLS_OPTIONS } from '../constants/ssl-tls-options'; + +import { handleUpdateTlsOption } from './tls-options'; + +describe('#handleUpdateTlsOption', function () { + describe('when it is called to update to `ON`', function () { + it('should update tls to `true` when `ON` is passed', function () { + const connectionStringUrl = new ConnectionStringUrl( + 'mongodb://a:b@outerspace:123/?directConnection=true&ssl=false' + ); + + const res = handleUpdateTlsOption({ + tlsOption: TLS_OPTIONS.ON, + connectionStringUrl, + connectionOptions: { + connectionString: connectionStringUrl.toString(), + }, + }); + expect(res.connectionStringUrl.toString()).to.equal( + 'mongodb://a:b@outerspace:123/?directConnection=true&tls=true' + ); + expect(res.connectionStringUrl.searchParams.get('tls')).to.equal('true'); + }); + + it('should update the connection string', function () { + const connectionStringUrl = new ConnectionStringUrl( + 'mongodb://a:b@outerspace:123/?directConnection=true&ssl=false' + ); + + const res = handleUpdateTlsOption({ + tlsOption: TLS_OPTIONS.ON, + connectionStringUrl, + connectionOptions: { + connectionString: connectionStringUrl.toString(), + }, + }); + expect(res.connectionOptions.connectionString).to.equal( + 'mongodb://a:b@outerspace:123/?directConnection=true&tls=true' + ); + }); + + it('should unset the `ssl` option', function () { + const connectionStringUrl = new ConnectionStringUrl( + 'mongodb://a:b@outerspace:123/?directConnection=true&ssl=false' + ); + + const res = handleUpdateTlsOption({ + tlsOption: TLS_OPTIONS.ON, + connectionStringUrl, + connectionOptions: { + connectionString: connectionStringUrl.toString(), + }, + }); + expect(res.connectionStringUrl.searchParams.get('ssl')).to.equal(null); + }); + }); + + describe('when it is called to update to `OFF`', function () { + it('should update tls to `false` when `OFF` is passed', function () { + const connectionStringUrl = new ConnectionStringUrl( + 'mongodb://a:b@outerspace:123/?directConnection=true&ssl=false' + ); + + const res = handleUpdateTlsOption({ + tlsOption: TLS_OPTIONS.OFF, + connectionStringUrl, + connectionOptions: { + connectionString: connectionStringUrl.toString(), + }, + }); + expect(res.connectionStringUrl.toString()).to.equal( + 'mongodb://a:b@outerspace:123/?directConnection=true&tls=false' + ); + expect(res.connectionStringUrl.searchParams.get('tls')).to.equal('false'); + }); + + it('should update the connection string', function () { + const connectionStringUrl = new ConnectionStringUrl( + 'mongodb://a:b@outerspace:123/?directConnection=true&tls=true' + ); + + const res = handleUpdateTlsOption({ + tlsOption: TLS_OPTIONS.OFF, + connectionStringUrl, + connectionOptions: { + connectionString: connectionStringUrl.toString(), + }, + }); + expect(res.connectionOptions.connectionString).to.equal( + 'mongodb://a:b@outerspace:123/?directConnection=true&tls=false' + ); + }); + + it('should unset the `ssl` option when ssl=true', function () { + const connectionStringUrl = new ConnectionStringUrl( + 'mongodb://a:b@outerspace:123/?directConnection=true&ssl=true' + ); + + const res = handleUpdateTlsOption({ + tlsOption: TLS_OPTIONS.OFF, + connectionStringUrl, + connectionOptions: { + connectionString: connectionStringUrl.toString(), + }, + }); + expect(res.connectionStringUrl.searchParams.get('ssl')).to.equal(null); + }); + + it('should unset the `ssl` option when ssl=false', function () { + const connectionStringUrl = new ConnectionStringUrl( + 'mongodb://a:b@outerspace:123/?directConnection=true&ssl=false' + ); + + const res = handleUpdateTlsOption({ + tlsOption: TLS_OPTIONS.OFF, + connectionStringUrl, + connectionOptions: { + connectionString: connectionStringUrl.toString(), + }, + }); + expect(res.connectionStringUrl.searchParams.get('ssl')).to.equal(null); + }); + }); + + describe('when it is called to update to `DEFAULT`', function () { + it('should unset tls when `DEFAULT` is passed', function () { + const connectionStringUrl = new ConnectionStringUrl( + 'mongodb://a:b@outerspace:123/?directConnection=true&tls=true' + ); + + const res = handleUpdateTlsOption({ + tlsOption: TLS_OPTIONS.DEFAULT, + connectionStringUrl, + connectionOptions: { + connectionString: connectionStringUrl.toString(), + }, + }); + expect(res.connectionStringUrl.toString()).to.equal( + 'mongodb://a:b@outerspace:123/?directConnection=true' + ); + expect(res.connectionStringUrl.searchParams.get('tls')).to.equal(null); + }); + + it('should update the connection string', function () { + const connectionStringUrl = new ConnectionStringUrl( + 'mongodb://a:b@outerspace:123/?directConnection=true&ssl=false&tls=true' + ); + + const res = handleUpdateTlsOption({ + tlsOption: TLS_OPTIONS.DEFAULT, + connectionStringUrl, + connectionOptions: { + connectionString: connectionStringUrl.toString(), + }, + }); + expect(res.connectionOptions.connectionString).to.equal( + 'mongodb://a:b@outerspace:123/?directConnection=true' + ); + }); + + it('should unset the `ssl` option', function () { + const connectionStringUrl = new ConnectionStringUrl( + 'mongodb://a:b@outerspace:123/?directConnection=true&ssl=false' + ); + + const res = handleUpdateTlsOption({ + tlsOption: TLS_OPTIONS.DEFAULT, + connectionStringUrl, + connectionOptions: { + connectionString: connectionStringUrl.toString(), + }, + }); + expect(res.connectionStringUrl.searchParams.get('ssl')).to.equal(null); + }); + }); +}); diff --git a/packages/connect-form/src/utils/tls-options.ts b/packages/connect-form/src/utils/tls-options.ts new file mode 100644 index 00000000000..45154b6d6c5 --- /dev/null +++ b/packages/connect-form/src/utils/tls-options.ts @@ -0,0 +1,41 @@ +import ConnectionStringUrl from 'mongodb-connection-string-url'; +import { ConnectionOptions } from 'mongodb-data-service'; + +import { TLS_OPTIONS } from '../constants/ssl-tls-options'; +import { ConnectionFormError } from '../utils/connect-form-errors'; + +export function handleUpdateTlsOption({ + tlsOption, + connectionStringUrl, + connectionOptions, +}: { + tlsOption: TLS_OPTIONS; + connectionStringUrl: ConnectionStringUrl; + connectionOptions: ConnectionOptions; +}): { + connectionStringUrl: ConnectionStringUrl; + connectionOptions: ConnectionOptions; + errors: ConnectionFormError[]; +} { + const updatedConnectionString = connectionStringUrl.clone(); + + if (tlsOption === TLS_OPTIONS.ON) { + updatedConnectionString.searchParams.delete('ssl'); + updatedConnectionString.searchParams.set('tls', 'true'); + } else if (tlsOption === TLS_OPTIONS.OFF) { + updatedConnectionString.searchParams.delete('ssl'); + updatedConnectionString.searchParams.set('tls', 'false'); + } else if (tlsOption === TLS_OPTIONS.DEFAULT) { + updatedConnectionString.searchParams.delete('ssl'); + updatedConnectionString.searchParams.delete('tls'); + } + + return { + errors: [], + connectionStringUrl: updatedConnectionString, + connectionOptions: { + ...connectionOptions, + connectionString: updatedConnectionString.toString(), + }, + }; +} From 2ce854759611d2e3b2a7e3ed63da67a1e4f896da Mon Sep 17 00:00:00 2001 From: Anemy Date: Tue, 21 Dec 2021 10:01:17 -0500 Subject: [PATCH 2/3] =?UTF-8?q?Remove=20enum,=20replace=20with=20type,=20u?= =?UTF-8?q?pdate=20-=20to=20=E2=80=93=20in=20tls=20description,=20improved?= =?UTF-8?q?=20code=20comment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tls-ssl-tab/tls-ssl-tab.tsx | 28 +++++++++++-------- .../src/constants/ssl-tls-options.ts | 6 +--- .../src/utils/tls-options.spec.ts | 21 +++++++------- .../connect-form/src/utils/tls-options.ts | 6 ++-- 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.tsx b/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.tsx index 64e0039605b..d743f11a694 100644 --- a/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.tsx +++ b/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.tsx @@ -17,22 +17,26 @@ const descriptionStyles = css({ marginTop: spacing[1], }); -const TLS_TYPES = [ +const TLS_TYPES: { + value: TLS_OPTIONS; + label: string; + description: string; +}[] = [ { - value: TLS_OPTIONS.DEFAULT, + value: 'DEFAULT', label: 'Default', description: - 'Default (unset) - TLS/SSL will be used when connecting using a DNS Seed List Connection Format (mongodb+srv://) and it will not be used when connecting using a standard connection string schema format (mongodb://).', + 'Default (unset) – TLS/SSL will be used when connecting using a DNS Seed List Connection Format (mongodb+srv://) and it will not be used when connecting using a standard connection string schema format (mongodb://).', }, { - value: TLS_OPTIONS.ON, + value: 'ON', label: 'On', - description: 'On - TLS/SSL is enabled for this connection.', + description: 'On – TLS/SSL is enabled for this connection.', }, { - value: TLS_OPTIONS.OFF, + value: 'OFF', label: 'Off', - description: 'Off - TLS/SSL is disabled for this connection.', + description: 'Off – TLS/SSL is disabled for this connection.', }, ]; @@ -43,7 +47,7 @@ export function getTLSOptionForConnectionString( connectionStringUrl.searchParams.get('ssl') === null && connectionStringUrl.searchParams.get('tls') === null ) { - return TLS_OPTIONS.DEFAULT; + return 'DEFAULT'; } if ( @@ -51,7 +55,7 @@ export function getTLSOptionForConnectionString( (connectionStringUrl.searchParams.get('ssl') === null || connectionStringUrl.searchParams.get('ssl') === 'true') ) { - return TLS_OPTIONS.ON; + return 'ON'; } if ( @@ -59,21 +63,21 @@ export function getTLSOptionForConnectionString( (connectionStringUrl.searchParams.get('ssl') === null || connectionStringUrl.searchParams.get('ssl') === 'false') ) { - return TLS_OPTIONS.OFF; + return 'OFF'; } if ( connectionStringUrl.searchParams.get('ssl') === 'true' && connectionStringUrl.searchParams.get('tls') === null ) { - return TLS_OPTIONS.ON; + return 'ON'; } if ( connectionStringUrl.searchParams.get('ssl') === 'false' && connectionStringUrl.searchParams.get('tls') === null ) { - return TLS_OPTIONS.OFF; + return 'OFF'; } // When the TLS/SSL options are a mismatching pair or not `true` or `false` diff --git a/packages/connect-form/src/constants/ssl-tls-options.ts b/packages/connect-form/src/constants/ssl-tls-options.ts index 11ae6cafef7..3a352b77b7a 100644 --- a/packages/connect-form/src/constants/ssl-tls-options.ts +++ b/packages/connect-form/src/constants/ssl-tls-options.ts @@ -1,5 +1 @@ -export enum TLS_OPTIONS { - DEFAULT = 'DEFAULT', - ON = 'ON', - OFF = 'OFF', -} +export type TLS_OPTIONS = 'DEFAULT' | 'ON' | 'OFF'; diff --git a/packages/connect-form/src/utils/tls-options.spec.ts b/packages/connect-form/src/utils/tls-options.spec.ts index fcbad17b344..495b1990058 100644 --- a/packages/connect-form/src/utils/tls-options.spec.ts +++ b/packages/connect-form/src/utils/tls-options.spec.ts @@ -1,6 +1,5 @@ import { expect } from 'chai'; import ConnectionStringUrl from 'mongodb-connection-string-url'; -import { TLS_OPTIONS } from '../constants/ssl-tls-options'; import { handleUpdateTlsOption } from './tls-options'; @@ -12,7 +11,7 @@ describe('#handleUpdateTlsOption', function () { ); const res = handleUpdateTlsOption({ - tlsOption: TLS_OPTIONS.ON, + tlsOption: 'ON', connectionStringUrl, connectionOptions: { connectionString: connectionStringUrl.toString(), @@ -30,7 +29,7 @@ describe('#handleUpdateTlsOption', function () { ); const res = handleUpdateTlsOption({ - tlsOption: TLS_OPTIONS.ON, + tlsOption: 'ON', connectionStringUrl, connectionOptions: { connectionString: connectionStringUrl.toString(), @@ -47,7 +46,7 @@ describe('#handleUpdateTlsOption', function () { ); const res = handleUpdateTlsOption({ - tlsOption: TLS_OPTIONS.ON, + tlsOption: 'ON', connectionStringUrl, connectionOptions: { connectionString: connectionStringUrl.toString(), @@ -64,7 +63,7 @@ describe('#handleUpdateTlsOption', function () { ); const res = handleUpdateTlsOption({ - tlsOption: TLS_OPTIONS.OFF, + tlsOption: 'OFF', connectionStringUrl, connectionOptions: { connectionString: connectionStringUrl.toString(), @@ -82,7 +81,7 @@ describe('#handleUpdateTlsOption', function () { ); const res = handleUpdateTlsOption({ - tlsOption: TLS_OPTIONS.OFF, + tlsOption: 'OFF', connectionStringUrl, connectionOptions: { connectionString: connectionStringUrl.toString(), @@ -99,7 +98,7 @@ describe('#handleUpdateTlsOption', function () { ); const res = handleUpdateTlsOption({ - tlsOption: TLS_OPTIONS.OFF, + tlsOption: 'OFF', connectionStringUrl, connectionOptions: { connectionString: connectionStringUrl.toString(), @@ -114,7 +113,7 @@ describe('#handleUpdateTlsOption', function () { ); const res = handleUpdateTlsOption({ - tlsOption: TLS_OPTIONS.OFF, + tlsOption: 'OFF', connectionStringUrl, connectionOptions: { connectionString: connectionStringUrl.toString(), @@ -131,7 +130,7 @@ describe('#handleUpdateTlsOption', function () { ); const res = handleUpdateTlsOption({ - tlsOption: TLS_OPTIONS.DEFAULT, + tlsOption: 'DEFAULT', connectionStringUrl, connectionOptions: { connectionString: connectionStringUrl.toString(), @@ -149,7 +148,7 @@ describe('#handleUpdateTlsOption', function () { ); const res = handleUpdateTlsOption({ - tlsOption: TLS_OPTIONS.DEFAULT, + tlsOption: 'DEFAULT', connectionStringUrl, connectionOptions: { connectionString: connectionStringUrl.toString(), @@ -166,7 +165,7 @@ describe('#handleUpdateTlsOption', function () { ); const res = handleUpdateTlsOption({ - tlsOption: TLS_OPTIONS.DEFAULT, + tlsOption: 'DEFAULT', connectionStringUrl, connectionOptions: { connectionString: connectionStringUrl.toString(), diff --git a/packages/connect-form/src/utils/tls-options.ts b/packages/connect-form/src/utils/tls-options.ts index 45154b6d6c5..1ff42d60fb0 100644 --- a/packages/connect-form/src/utils/tls-options.ts +++ b/packages/connect-form/src/utils/tls-options.ts @@ -19,13 +19,13 @@ export function handleUpdateTlsOption({ } { const updatedConnectionString = connectionStringUrl.clone(); - if (tlsOption === TLS_OPTIONS.ON) { + if (tlsOption === 'ON') { updatedConnectionString.searchParams.delete('ssl'); updatedConnectionString.searchParams.set('tls', 'true'); - } else if (tlsOption === TLS_OPTIONS.OFF) { + } else if (tlsOption === 'OFF') { updatedConnectionString.searchParams.delete('ssl'); updatedConnectionString.searchParams.set('tls', 'false'); - } else if (tlsOption === TLS_OPTIONS.DEFAULT) { + } else if (tlsOption === 'DEFAULT') { updatedConnectionString.searchParams.delete('ssl'); updatedConnectionString.searchParams.delete('tls'); } From 8e22496ec1d15e7841d001d923e2d0e1ca600d5f Mon Sep 17 00:00:00 2001 From: Anemy Date: Wed, 22 Dec 2021 13:21:03 -0500 Subject: [PATCH 3/3] use typed connection search params --- .../tls-ssl-tab/tls-ssl-tab.tsx | 28 +++++++------------ .../connect-form/src/utils/tls-options.ts | 15 ++++++---- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.tsx b/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.tsx index d743f11a694..444b6993fcb 100644 --- a/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.tsx +++ b/packages/connect-form/src/components/advanced-options-tabs/tls-ssl-tab/tls-ssl-tab.tsx @@ -8,6 +8,7 @@ import { spacing, } from '@mongodb-js/compass-components'; import ConnectionStringUrl from 'mongodb-connection-string-url'; +import type { MongoClientOptions } from 'mongodb'; import { UpdateConnectionFormField } from '../../../hooks/use-connect-form'; import FormFieldContainer from '../../form-field-container'; @@ -43,40 +44,31 @@ const TLS_TYPES: { export function getTLSOptionForConnectionString( connectionStringUrl: ConnectionStringUrl ): TLS_OPTIONS | undefined { - if ( - connectionStringUrl.searchParams.get('ssl') === null && - connectionStringUrl.searchParams.get('tls') === null - ) { + const searchParams = + connectionStringUrl.typedSearchParams(); + if (searchParams.get('ssl') === null && searchParams.get('tls') === null) { return 'DEFAULT'; } if ( - connectionStringUrl.searchParams.get('tls') === 'true' && - (connectionStringUrl.searchParams.get('ssl') === null || - connectionStringUrl.searchParams.get('ssl') === 'true') + searchParams.get('tls') === 'true' && + (searchParams.get('ssl') === null || searchParams.get('ssl') === 'true') ) { return 'ON'; } if ( - connectionStringUrl.searchParams.get('tls') === 'false' && - (connectionStringUrl.searchParams.get('ssl') === null || - connectionStringUrl.searchParams.get('ssl') === 'false') + searchParams.get('tls') === 'false' && + (searchParams.get('ssl') === null || searchParams.get('ssl') === 'false') ) { return 'OFF'; } - if ( - connectionStringUrl.searchParams.get('ssl') === 'true' && - connectionStringUrl.searchParams.get('tls') === null - ) { + if (searchParams.get('ssl') === 'true' && searchParams.get('tls') === null) { return 'ON'; } - if ( - connectionStringUrl.searchParams.get('ssl') === 'false' && - connectionStringUrl.searchParams.get('tls') === null - ) { + if (searchParams.get('ssl') === 'false' && searchParams.get('tls') === null) { return 'OFF'; } diff --git a/packages/connect-form/src/utils/tls-options.ts b/packages/connect-form/src/utils/tls-options.ts index 1ff42d60fb0..1b2e11e5dce 100644 --- a/packages/connect-form/src/utils/tls-options.ts +++ b/packages/connect-form/src/utils/tls-options.ts @@ -1,5 +1,6 @@ import ConnectionStringUrl from 'mongodb-connection-string-url'; import { ConnectionOptions } from 'mongodb-data-service'; +import type { MongoClientOptions } from 'mongodb'; import { TLS_OPTIONS } from '../constants/ssl-tls-options'; import { ConnectionFormError } from '../utils/connect-form-errors'; @@ -18,16 +19,18 @@ export function handleUpdateTlsOption({ errors: ConnectionFormError[]; } { const updatedConnectionString = connectionStringUrl.clone(); + const updatedSearchParams = + updatedConnectionString.typedSearchParams(); if (tlsOption === 'ON') { - updatedConnectionString.searchParams.delete('ssl'); - updatedConnectionString.searchParams.set('tls', 'true'); + updatedSearchParams.delete('ssl'); + updatedSearchParams.set('tls', 'true'); } else if (tlsOption === 'OFF') { - updatedConnectionString.searchParams.delete('ssl'); - updatedConnectionString.searchParams.set('tls', 'false'); + updatedSearchParams.delete('ssl'); + updatedSearchParams.set('tls', 'false'); } else if (tlsOption === 'DEFAULT') { - updatedConnectionString.searchParams.delete('ssl'); - updatedConnectionString.searchParams.delete('tls'); + updatedSearchParams.delete('ssl'); + updatedSearchParams.delete('tls'); } return {