diff --git a/src/plugins/credential_management/public/components/common/components/header/edit_page_header.tsx b/src/plugins/credential_management/public/components/common/components/header/edit_page_header.tsx deleted file mode 100644 index 9c67f58f3a5c..000000000000 --- a/src/plugins/credential_management/public/components/common/components/header/edit_page_header.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; - -import { EuiBetaBadge, EuiSpacer, EuiTitle, EuiText, EuiCode, EuiLink } from '@elastic/eui'; - -import { i18n } from '@osd/i18n'; -import { useOpenSearchDashboards } from '../../../../../../opensearch_dashboards_react/public'; -import { CredentialManagementContext } from '../../../../types'; - -export const EditPageHeader = ({ - isBeta = false, - credentialName, -}: { - isBeta?: boolean; - credentialName: string; -}) => { - const changeTitle = useOpenSearchDashboards().services.chrome - .docTitle.change; - - changeTitle(credentialName); - - return ( -
- -

- {credentialName} - {isBeta ? ( - <> - - - ) : null} -

-
- -
- ); -}; diff --git a/src/plugins/credential_management/public/components/common/components/header/header.tsx b/src/plugins/credential_management/public/components/common/components/header/header.tsx index a78e24e45aa3..ec19d6cfbbef 100644 --- a/src/plugins/credential_management/public/components/common/components/header/header.tsx +++ b/src/plugins/credential_management/public/components/common/components/header/header.tsx @@ -17,10 +17,14 @@ export const Header = ({ prompt, docLinks, headerTitle, + isBeta = false, + isCreateCredential = false, }: { prompt?: React.ReactNode; - docLinks: DocLinksStart; + docLinks?: DocLinksStart; headerTitle: string; + isBeta?: boolean; + isCreateCredential: boolean; }) => { const changeTitle = useOpenSearchDashboards().services.chrome .docTitle.change; @@ -32,41 +36,50 @@ export const Header = ({

{headerTitle} - <> - {' '} - - + + {isBeta ? ( + <> + + + ) : null}

- -

- username-password-credential, - first: os-service-log, - second: os-application-log, - }} - /> -
- - - -

-
+ + {isCreateCredential ? ( + <> + +

+ username-password-credential, + first: os-service-log, + second: os-application-log, + }} + /> +
+ + + + +

+
+ + ) : null} + {prompt ? ( <> diff --git a/src/plugins/credential_management/public/components/common/text_content/text_content.ts b/src/plugins/credential_management/public/components/common/text_content/text_content.ts index f9543cee8243..9718866f8857 100644 --- a/src/plugins/credential_management/public/components/common/text_content/text_content.ts +++ b/src/plugins/credential_management/public/components/common/text_content/text_content.ts @@ -54,3 +54,24 @@ export const confirmButtonOnDeleteComfirmText = i18n.translate( defaultMessage: 'Delete', } ); + +export const credentialEditPagePassword = i18n.translate( + 'credentialManagement.textContent.credentialEditPagePassword', + { + defaultMessage: '*************', + } +); + +export const credentialEditPageAuthTitle = i18n.translate( + 'credentialManagement.textContent.credentialEditPageAuthTitle', + { + defaultMessage: 'Authentication Details', + } +); + +export const credentialEditPageInfoTitle = i18n.translate( + 'credentialManagement.textContent.credentialEditPageAuthTitle', + { + defaultMessage: 'Saved Credential Information', + } +); diff --git a/src/plugins/credential_management/public/components/credential_table/credentials_table.tsx b/src/plugins/credential_management/public/components/credential_table/credentials_table.tsx index 9d51bbe21d64..d63844ab555f 100644 --- a/src/plugins/credential_management/public/components/credential_table/credentials_table.tsx +++ b/src/plugins/credential_management/public/components/credential_table/credentials_table.tsx @@ -22,13 +22,11 @@ import { EuiBadgeGroup, EuiPageContent, EuiTitle, - EuiSearchBar, EuiConfirmModal, EuiLoadingSpinner, EuiOverlayMask, EuiGlobalToastList, EuiGlobalToastListToast, - Query, } from '@elastic/eui'; import { @@ -78,11 +76,8 @@ export const CredentialsTable = ({ canSave, history }: Props) => { const [isDeleting, setIsDeleting] = React.useState(false); const [confirmDeleteVisible, setConfirmDeleteVisible] = React.useState(false); const [toasts, setToasts] = React.useState([]); - const [searchText, setSearchText] = React.useState(''); - const { savedObjects, uiSettings } = useOpenSearchDashboards< - CredentialManagementContext - >().services; + const { savedObjects } = useOpenSearchDashboards().services; const columns = [ { @@ -136,10 +131,6 @@ export const CredentialsTable = ({ canSave, history }: Props) => { setSelectedCredentials(selected); }; - const selection = { - onSelectionChange, - }; - const renderDeleteButton = () => { let deleteButtonMsg = 'Delete'; @@ -162,6 +153,28 @@ export const CredentialsTable = ({ canSave, history }: Props) => { ); }; + const renderToolsRight = () => { + return ( + + {renderDeleteButton()} + + ); + }; + + const search = { + toolsRight: renderToolsRight(), + box: { + incremental: true, + schema: { + fields: { title: { type: 'string' } }, + }, + }, + }; + + const selection = { + onSelectionChange, + }; + const onClickDelete = async () => { try { setIsDeleting(true); @@ -193,24 +206,20 @@ export const CredentialsTable = ({ canSave, history }: Props) => { } }; - const deleteButton = renderDeleteButton(); - - React.useEffect(() => { + useEffectOnce(() => { (async () => { setIsLoading(true); const fetchedCredentials: CredentialsTableItem[] = await getCredentials(savedObjects.client); - const fetchedCredentialsResults = fetchedCredentials.filter((row) => { - return row.title.includes(searchText); - }); + setCredentials(fetchedCredentials); - setCredentials(fetchedCredentialsResults); setIsLoading(false); })(); - }, [history.push, credentials.length, uiSettings, savedObjects.client, searchText]); + }); const createButton = canSave ? : <>; + /* render delete modal*/ const tableRenderDeleteModal = () => { return confirmDeleteVisible ? ( { ) : null; }; - const onSearchChange = ({ - query, - }: { - query: Query | null; - error: { message: string } | null; - }) => { - setSearchText(query!.text); - }; - const removeToast = (id: string) => { setToasts(toasts.filter((toast) => toast.id !== id)); }; @@ -272,16 +272,6 @@ export const CredentialsTable = ({ canSave, history }: Props) => { {createButton} - onSearchChange(e)} - toolsRight={[ - - {deleteButton} - , - ]} - /> - {tableRenderDeleteModal()} @@ -295,6 +285,7 @@ export const CredentialsTable = ({ canSave, history }: Props) => { columns={columns} pagination={pagination} sorting={sorting} + search={search} loading={isLoading} /> diff --git a/src/plugins/credential_management/public/components/edit_credential_wizard/components/edit_credential.tsx b/src/plugins/credential_management/public/components/edit_credential_wizard/components/edit_credential.tsx index 8ca178072547..53dc6140cc96 100644 --- a/src/plugins/credential_management/public/components/edit_credential_wizard/components/edit_credential.tsx +++ b/src/plugins/credential_management/public/components/edit_credential_wizard/components/edit_credential.tsx @@ -42,11 +42,10 @@ import { import { getCreateBreadcrumbs } from '../../breadcrumbs'; import { CredentialManagmentContextValue } from '../../../types'; -// TODO: Add Header https://github.com/opensearch-project/OpenSearch-Dashboards/issues/2051 import { context as contextType } from '../../../../../opensearch_dashboards_react/public'; import { EditCredentialItem } from '../../types'; import { LocalizedContent } from '../../common/text_content'; -import { EditPageHeader } from '../../common/components/header/edit_page_header'; +import { Header } from '../../common/components/header'; interface EditCredentialState { credentialName: string; @@ -64,7 +63,6 @@ interface EditCredentialState { export interface EditCredentialProps extends RouteComponentProps { credential: EditCredentialItem; - originalCredential: EditCredentialItem; } export class EditCredentialComponent extends React.Component< @@ -91,7 +89,7 @@ export class EditCredentialComponent extends React.Component< isLoading: false, }; } - + /* Render methods */ delelteButtonRender() { return ( <> @@ -126,7 +124,7 @@ export class EditCredentialComponent extends React.Component< ); } renderHeader() { - return ; + return
; } updatePasswordRender() { @@ -157,7 +155,7 @@ export class EditCredentialComponent extends React.Component< this.updateCredential(true)} + onClick={this.updateCredentialPasswordField} fill > Update @@ -170,28 +168,23 @@ export class EditCredentialComponent extends React.Component< } renderContent = () => { - const options = [ - { - value: CredentialMaterialsType.UsernamePasswordType, - text: 'Username and Password Credential', - }, - ]; const header = this.renderHeader(); const deleteButton = this.delelteButtonRender(); return ( + {header} {deleteButton} - + -

Save Credentials

+

{LocalizedContent.credentialEditPageInfoTitle}

@@ -227,7 +220,7 @@ export class EditCredentialComponent extends React.Component< -

Authentication Details

+

{LocalizedContent.credentialEditPageAuthTitle}

@@ -255,7 +248,7 @@ export class EditCredentialComponent extends React.Component< - ********* + {LocalizedContent.credentialEditPagePassword} {this.updatePasswordRender()} @@ -270,12 +263,7 @@ export class EditCredentialComponent extends React.Component< - this.updateCredential(false)} - > + Save changes @@ -286,12 +274,6 @@ export class EditCredentialComponent extends React.Component< ); }; - removeToast = (id: string) => { - this.setState((prevState) => ({ - toasts: prevState.toasts.filter((toast) => toast.id !== id), - })); - }; - render() { const content = this.renderContent(); const { isLoading } = this.state; @@ -312,6 +294,12 @@ export class EditCredentialComponent extends React.Component< ); } + /* Events */ + removeToast = (id: string) => { + this.setState((prevState) => ({ + toasts: prevState.toasts.filter((toast) => toast.id !== id), + })); + }; removeCredential = async () => { this.setState({ isDeleteModalVisible: true }); @@ -321,61 +309,70 @@ export class EditCredentialComponent extends React.Component< this.setState({ isUpdateModalVisible: true }); }; - updateCredential = async (isUpdatePassword: boolean) => { + updateCredentialInformation = async () => { const { savedObjects } = this.context.services; - const { originalCredential } = this.props; - - this.setState({ isLoading: true, isUpdateModalVisible: false }); + this.setState({ isLoading: true }); try { const credentialAttributes = { - title: isUpdatePassword ? originalCredential.title : this.state.credentialName, - description: isUpdatePassword - ? originalCredential.description - : this.state.credentialDescription, + title: this.state.credentialName, + description: this.state.credentialDescription, credentialMaterials: { credentialMaterialsType: this.state.credentialMaterialsType, credentialMaterialsContent: { - username: isUpdatePassword ? originalCredential.username : this.state.username, - password: this.state.password, + username: this.state.username, }, }, }; - if (!isUpdatePassword) { - delete credentialAttributes.credentialMaterials.credentialMaterialsContent.password; - } await savedObjects.client.update( CREDENTIAL_SAVED_OBJECT_TYPE, this.props.credential.id, credentialAttributes ); - if (isUpdatePassword) { - this.setState({ password: '' }); + this.props.history.push(''); + } catch (e) { + const editCredentialFailMsg = ( + + ); + this.setState((prevState) => ({ + toasts: prevState.toasts.concat([ + { + title: editCredentialFailMsg, + id: editCredentialFailMsg.props.id, + color: 'warning', + iconType: 'alert', + }, + ]), + })); + } + this.setState({ isLoading: false }); + }; - const editCredentialSuccessMsg = ( - - ); - this.setState((prevState) => ({ - toasts: prevState.toasts.concat([ - { - title: editCredentialSuccessMsg, - id: editCredentialSuccessMsg.props.id, - color: 'success', - iconType: 'check', - }, - ]), - })); - } else { - this.props.history.push(''); - } + updateCredentialPasswordField = async () => { + const { savedObjects } = this.context.services; + this.setState({ isLoading: true, isUpdateModalVisible: false }); + try { + const credentialAttributes = { + credentialMaterials: { + credentialMaterialsContent: { + password: this.state.password, + }, + }, + }; + await savedObjects.client.update( + CREDENTIAL_SAVED_OBJECT_TYPE, + this.props.credential.id, + credentialAttributes + ); + this.props.history.push(''); } catch (e) { const editCredentialFailMsg = ( ); this.setState((prevState) => ({ diff --git a/src/plugins/credential_management/public/components/edit_credential_wizard/edit_credential_wizard.tsx b/src/plugins/credential_management/public/components/edit_credential_wizard/edit_credential_wizard.tsx index fe36a05c355e..8975c5542134 100644 --- a/src/plugins/credential_management/public/components/edit_credential_wizard/edit_credential_wizard.tsx +++ b/src/plugins/credential_management/public/components/edit_credential_wizard/edit_credential_wizard.tsx @@ -28,7 +28,6 @@ const EditCredentialWizard: React.FunctionComponent(); - const [originalCredential, setOriginalCredential] = useState(); const [toasts, setToasts] = useState([]); /* Fetch credential by id*/ @@ -50,7 +49,6 @@ const EditCredentialWizard: React.FunctionComponent; + if (credential) { + return ; } else { return

Credential not found!

; } diff --git a/src/plugins/data_source/common/credentials/types.ts b/src/plugins/data_source/common/credentials/types.ts index 4ee42e3d8f50..8888a1a1ba9f 100644 --- a/src/plugins/data_source/common/credentials/types.ts +++ b/src/plugins/data_source/common/credentials/types.ts @@ -25,5 +25,5 @@ export interface CredentialMaterials extends SavedObjectAttributes { export interface UsernamePasswordTypedContent extends SavedObjectAttributes { username: string; - password?: string; + password: string; } diff --git a/src/plugins/data_source/server/saved_objects/credential_saved_objects_client_wrapper.ts b/src/plugins/data_source/server/saved_objects/credential_saved_objects_client_wrapper.ts index 829b96d40d9a..b9edbb5221ef 100644 --- a/src/plugins/data_source/server/saved_objects/credential_saved_objects_client_wrapper.ts +++ b/src/plugins/data_source/server/saved_objects/credential_saved_objects_client_wrapper.ts @@ -20,7 +20,6 @@ import { SavedObjectsErrorHelpers } from '../../../../core/server'; import { CryptographyClient } from '../cryptography'; import { CredentialMaterialsType, CREDENTIAL_SAVED_OBJECT_TYPE } from '../../common'; -import { credential } from './credential_saved_objects_type'; /** * Describes the Credential Saved Objects Client Wrapper class, @@ -139,7 +138,20 @@ export class CredentialSavedObjectsClientWrapper { } private async validateAndEncryptPartialAttributes(attributes: T) { - this.validateAttributes(attributes); + const { credentialMaterials } = attributes; + const { credentialMaterialsContent } = credentialMaterials; + + if ('password' in credentialMaterialsContent) { + this.validatePassword(credentialMaterialsContent.password); + return { + ...attributes, + credentialMaterials: await this.encryptUsernamePasswordTypedCredentialMaterials( + credentialMaterials + ), + }; + } else { + this.validateAttributes(attributes); + } return await this.encryptCredentialMaterials(attributes); } @@ -179,21 +191,12 @@ export class CredentialSavedObjectsClientWrapper { const { credentialMaterials } = attributes; const { credentialMaterialsType, credentialMaterialsContent } = credentialMaterials; - const { username, password } = credentialMaterialsContent; + const { username } = credentialMaterialsContent; switch (credentialMaterialsType) { case CredentialMaterialsType.UsernamePasswordType: this.validateUsername(username); - if (password !== undefined) { - this.validatePassword(password); - return { - ...attributes, - credentialMaterials: await this.encryptUsernamePasswordTypedCredentialMaterials( - credentialMaterials - ), - }; - } return { ...attributes, credentialMaterials: {