From 0db750d4193a47aa09a3a81491d63ddcde68f33e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 14 Mar 2024 18:53:45 +0000 Subject: [PATCH] [Multiple DataSource] DataSource creation and edition page improvement to better support registered auth types (#6122) * [Token Exchange Unification] State update for createDataSource and editDataSource pages Signed-off-by: Xinrui Bai * [Token Exchange Unification] rectify state for dataSource creation page and edit page Signed-off-by: Xinrui Bai * [UT] Add more test cases for util functions Signed-off-by: Xinrui Bai * [Token Exchange Unification] Update dataSource bottom banner control Signed-off-by: Xinrui Bai * Update changefile.md Signed-off-by: Xinrui Bai * Add comments Signed-off-by: Xinrui Bai * Code review change, fix typo Signed-off-by: Xinrui Bai * Resolve comments, update typo in test cases Signed-off-by: Xinrui Bai --------- Signed-off-by: Xinrui Bai (cherry picked from commit 31e8481fd2c0bf185d34c1140724e9320f6a676c) Signed-off-by: github-actions[bot] # Conflicts: # CHANGELOG.md --- .../authentication_methods_registry.ts | 2 +- .../create_data_source_form.test.tsx | 2 +- .../create_form/create_data_source_form.tsx | 15 ++-- .../edit_form/edit_data_source_form.test.tsx | 2 +- .../edit_form/edit_data_source_form.tsx | 80 ++++++++++++++----- .../public/components/utils.test.ts | 70 +++++++++++++++- .../public/components/utils.ts | 5 +- .../datasource_form_validation.test.ts | 2 +- .../data_source_management/public/types.ts | 6 +- 9 files changed, 146 insertions(+), 38 deletions(-) diff --git a/src/plugins/data_source_management/public/auth_registry/authentication_methods_registry.ts b/src/plugins/data_source_management/public/auth_registry/authentication_methods_registry.ts index a4152cb0627..7d6bf38026a 100644 --- a/src/plugins/data_source_management/public/auth_registry/authentication_methods_registry.ts +++ b/src/plugins/data_source_management/public/auth_registry/authentication_methods_registry.ts @@ -13,7 +13,7 @@ export interface AuthenticationMethod { state: { [key: string]: any }, setState: React.Dispatch> ) => React.JSX.Element; - crendentialFormField?: { [key: string]: string }; + credentialFormField?: { [key: string]: string }; } export type IAuthenticationMethodRegistery = Omit< diff --git a/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.test.tsx b/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.test.tsx index 043f8026784..2c7778868bc 100644 --- a/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.test.tsx +++ b/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.test.tsx @@ -534,7 +534,7 @@ describe('Datasource Management: Create Datasource form with registered Auth Typ inputDisplay: 'some input', }, credentialForm: mockCredentialForm, - crendentialFormField: { + credentialFormField: { userNameRegistered: 'some filled in userName from registed auth credential form', passWordRegistered: 'some filled in password from registed auth credential form', }, diff --git a/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.tsx b/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.tsx index ab5df7220c7..180476e8b08 100644 --- a/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.tsx +++ b/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.tsx @@ -101,7 +101,7 @@ export class CreateDataSourceForm extends React.Component< auth: { type: initialSelectedAuthMethod?.name, credentials: { - ...initialSelectedAuthMethod?.crendentialFormField, + ...initialSelectedAuthMethod?.credentialFormField, }, }, }; @@ -153,15 +153,20 @@ export class CreateDataSourceForm extends React.Component< }; onChangeAuthType = (authType: AuthType) => { + const credentials = this.state.auth.credentials; + + const registeredAuthCredentials = extractRegisteredAuthTypeCredentials( + (credentials ?? {}) as { [key: string]: string }, + authType, + this.authenticationMethodRegistery + ); + this.setState({ auth: { ...this.state.auth, type: authType, credentials: { - ...this.state.auth.credentials, - service: - (this.state.auth.credentials.service as SigV4ServiceName) || - SigV4ServiceName.OpenSearch, + ...registeredAuthCredentials, }, }, }); diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.test.tsx b/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.test.tsx index 25ea22ef274..06d0af486bb 100644 --- a/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.test.tsx +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.test.tsx @@ -410,7 +410,7 @@ describe('With Registered Authentication', () => { inputDisplay: 'some input', }, credentialForm: mockedCredentialForm, - crendentialFormField: {}, + credentialFormField: {}, } as AuthenticationMethod; const mockedContext = mockManagementPlugin.createDataSourceManagementContext(); diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.tsx b/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.tsx index 0089e8f12af..2cb1db4515d 100644 --- a/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.tsx +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.tsx @@ -24,6 +24,7 @@ import { } from '@elastic/eui'; import { i18n } from '@osd/i18n'; import { FormattedMessage } from '@osd/i18n/react'; +import deepEqual from 'fast-deep-equal'; import { AuthenticationMethodRegistery } from '../../../../auth_registry'; import { SigV4Content, SigV4ServiceName } from '../../../../../../data_source/common/data_sources'; import { Header } from '../header'; @@ -100,11 +101,7 @@ export class EditDataSourceForm extends React.Component { + /* If the selected authentication type matches, utilize the existing data source's credentials directly.*/ + const credentials = + this.props.existingDataSource && authType === this.props.existingDataSource.auth.type + ? this.props.existingDataSource.auth.credentials + : this.state.auth.credentials; + const registeredAuthCredentials = extractRegisteredAuthTypeCredentials( + (credentials ?? {}) as { [key: string]: string }, + authType, + this.authenticationMethodRegistery + ); + this.setState( { auth: { ...this.state.auth, type: authType, credentials: { - ...this.state.auth.credentials, - service: - (this.state.auth.credentials?.service as SigV4ServiceName) || - SigV4ServiceName.OpenSearch, + ...registeredAuthCredentials, }, }, }, @@ -427,6 +426,14 @@ export class EditDataSourceForm extends React.Component { + const { auth } = this.props.existingDataSource; + const currentAuth = this.state.auth; + + if ( + currentAuth.type === AuthType.NoAuth || + currentAuth.type === AuthType.UsernamePasswordType || + currentAuth.type === AuthType.SigV4 + ) { + return false; + } + + const existingAuthCredentials = extractRegisteredAuthTypeCredentials( + (auth?.credentials ?? {}) as { [key: string]: string }, + currentAuth.type, + this.authenticationMethodRegistery + ); + + const registeredAuthCredentials = extractRegisteredAuthTypeCredentials( + (currentAuth?.credentials ?? {}) as { [key: string]: string }, + currentAuth.type, + this.authenticationMethodRegistery + ); + + return !deepEqual(existingAuthCredentials, registeredAuthCredentials); + }; + renderBottomBar = () => { return ( diff --git a/src/plugins/data_source_management/public/components/utils.test.ts b/src/plugins/data_source_management/public/components/utils.test.ts index cefaa628bf2..a327c22bf0c 100644 --- a/src/plugins/data_source_management/public/components/utils.test.ts +++ b/src/plugins/data_source_management/public/components/utils.test.ts @@ -285,7 +285,7 @@ describe('DataSourceManagement: Utils.ts', () => { value: authTypeToBeTested, inputDisplay: 'some input', }, - crendentialFormField: { + credentialFormField: { userNameRegistered: '', passWordRegistered: '', }, @@ -352,7 +352,7 @@ describe('DataSourceManagement: Utils.ts', () => { value: authTypeToBeTested, inputDisplay: 'some input', }, - crendentialFormField: { + credentialFormField: { userNameRegistered: '', passWordRegistered: '', }, @@ -380,5 +380,71 @@ describe('DataSourceManagement: Utils.ts', () => { expect(deepEqual(registedAuthTypeCredentials, expectExtractedAuthCredentials)); }); + + test('Should inherit value from registered field when credential state not have registered field', () => { + const authTypeToBeTested = 'Some Auth Type'; + + const authMethodToBeTested = { + name: authTypeToBeTested, + credentialSourceOption: { + value: authTypeToBeTested, + inputDisplay: 'some input', + }, + credentialFormField: { + registeredField: 'some value', + }, + } as AuthenticationMethod; + + const mockedCredentialState = {} as { [key: string]: string }; + + const expectExtractedAuthCredentials = { + registeredField: 'some value', + }; + + const authenticationMethodRegistery = new AuthenticationMethodRegistery(); + authenticationMethodRegistery.registerAuthenticationMethod(authMethodToBeTested); + + const registedAuthTypeCredentials = extractRegisteredAuthTypeCredentials( + mockedCredentialState, + authTypeToBeTested, + authenticationMethodRegistery + ); + + expect(deepEqual(registedAuthTypeCredentials, expectExtractedAuthCredentials)); + }); + + test('Should not inherit value from registered field when credentail state have registered field', () => { + const authTypeToBeTested = 'Some Auth Type'; + + const authMethodToBeTested = { + name: authTypeToBeTested, + credentialSourceOption: { + value: authTypeToBeTested, + inputDisplay: 'some input', + }, + credentialFormField: { + registeredField: 'Some value', + }, + } as AuthenticationMethod; + + const mockedCredentialState = { + registeredField: 'some other values', + } as { [key: string]: string }; + + const expectExtractedAuthCredentials = { + registeredField: 'some other values', + }; + + const authenticationMethodRegistery = new AuthenticationMethodRegistery(); + authenticationMethodRegistery.registerAuthenticationMethod(authMethodToBeTested); + + const registedAuthTypeCredentials = extractRegisteredAuthTypeCredentials( + mockedCredentialState, + authTypeToBeTested, + authenticationMethodRegistery + ); + + expect(deepEqual(registedAuthTypeCredentials, expectExtractedAuthCredentials)); + }); }); }); diff --git a/src/plugins/data_source_management/public/components/utils.ts b/src/plugins/data_source_management/public/components/utils.ts index 871abc1dc63..6f55b71b250 100644 --- a/src/plugins/data_source_management/public/components/utils.ts +++ b/src/plugins/data_source_management/public/components/utils.ts @@ -151,10 +151,11 @@ export const extractRegisteredAuthTypeCredentials = ( ) => { const registeredCredentials = {} as { [key: string]: string }; const registeredCredentialField = - authenticationMethodRegistery.getAuthenticationMethod(authType)?.crendentialFormField ?? {}; + authenticationMethodRegistery.getAuthenticationMethod(authType)?.credentialFormField ?? {}; Object.keys(registeredCredentialField).forEach((credentialFiled) => { - registeredCredentials[credentialFiled] = currentCredentialState[credentialFiled] ?? ''; + registeredCredentials[credentialFiled] = + currentCredentialState[credentialFiled] ?? registeredCredentialField[credentialFiled]; }); return registeredCredentials; diff --git a/src/plugins/data_source_management/public/components/validation/datasource_form_validation.test.ts b/src/plugins/data_source_management/public/components/validation/datasource_form_validation.test.ts index fbac18c7ddc..1eaaea0f567 100644 --- a/src/plugins/data_source_management/public/components/validation/datasource_form_validation.test.ts +++ b/src/plugins/data_source_management/public/components/validation/datasource_form_validation.test.ts @@ -82,7 +82,7 @@ describe('DataSourceManagement: Form Validation', () => { inputDisplay: 'some input', }, credentialForm: jest.fn(), - crendentialFormField: { + credentialFormField: { userNameRegistered: 'some filled in userName from registed auth credential form', passWordRegistered: 'some filled in password from registed auth credential form', }, diff --git a/src/plugins/data_source_management/public/types.ts b/src/plugins/data_source_management/public/types.ts index d8df61d304b..bf0743468fd 100644 --- a/src/plugins/data_source_management/public/types.ts +++ b/src/plugins/data_source_management/public/types.ts @@ -74,7 +74,7 @@ export const noAuthCredentialField = {}; export const noAuthCredentialAuthMethod = { name: AuthType.NoAuth, credentialSourceOption: noAuthCredentialOption, - crendentialFormField: noAuthCredentialField, + credentialFormField: noAuthCredentialField, }; export const usernamePasswordCredentialOption = { @@ -92,7 +92,7 @@ export const usernamePasswordCredentialField = { export const usernamePasswordAuthMethod = { name: AuthType.UsernamePasswordType, credentialSourceOption: usernamePasswordCredentialOption, - crendentialFormField: usernamePasswordCredentialField, + credentialFormField: usernamePasswordCredentialField, }; export const sigV4CredentialOption = { @@ -127,7 +127,7 @@ export const sigV4CredentialField = { export const sigV4AuthMethod = { name: AuthType.SigV4, credentialSourceOption: sigV4CredentialOption, - crendentialFormField: sigV4CredentialField, + credentialFormField: sigV4CredentialField, }; export const credentialSourceOptions = [