Skip to content

Commit

Permalink
[MD][Cred Mgr]PoC delete credentials (#10)
Browse files Browse the repository at this point in the history
1. PoC delete credentials
2. Resolve some UI feedbacks in #9
  • Loading branch information
noCharger authored Jul 11, 2022
1 parent ff5d568 commit 2fa92e0
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 24 deletions.
11 changes: 11 additions & 0 deletions src/plugins/credential_management/public/components/breadsrumbs.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Any modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

import { i18n } from '@osd/i18n';

export function getListBreadcrumbs() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const Header = ({
.docTitle.change;
const createCredentialHeader = i18n.translate('credentialManagement.createIndexPatternHeader',
{
defaultMessage: 'Create Credential',
defaultMessage: 'Save Your Credential',
}
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import {
EuiFieldText,
EuiSelect,
EuiLink,
EuiFilePicker,
// EuiFilePicker,
EuiButton,
EuiPageContent,
EuiFieldPassword,
} from '@elastic/eui';
import { DocLinksStart } from 'src/core/public';
import { getCreateBreadcrumbs } from '../breadsrumbs';
Expand All @@ -37,6 +38,7 @@ interface CreateCredentialWizardState {
credentialType: string;
user_name: string;
password: string;
dual: boolean;
toasts: EuiGlobalToastListToast[];
docLinks: DocLinksStart;
}
Expand All @@ -49,7 +51,7 @@ export class CreateCredentialWizard extends React.Component<
> {
static contextType = contextType;
public readonly context!: CredentialManagmentContextValue;

constructor(props: RouteComponentProps, context: CredentialManagmentContextValue) {
super(props, context);

Expand All @@ -60,6 +62,7 @@ export class CreateCredentialWizard extends React.Component<
credentialType: USERNAME_PASSWORD_TYPE,
user_name: '',
password: '',
dual: true,
toasts: [],
docLinks: context.services.docLinks,
};
Expand Down Expand Up @@ -142,18 +145,19 @@ export class CreateCredentialWizard extends React.Component<
/>
</EuiFormRow>
<EuiFormRow label="Password">
<EuiFieldText
<EuiFieldPassword
placeholder="Your Password"
value={this.redact(this.state.password.length) || ''}
type={this.state.dual ? 'dual' : undefined}
value={this.state.password || ''}
onChange={(e) => this.setState({ password: e.target.value })}
/>
</EuiFormRow>
<EuiFormRow label="Upload Credential File">
{/* <EuiFormRow label="Upload Credential File">
<EuiFilePicker />
</EuiFormRow>
</EuiFormRow> */}
</EuiDescribedFormGroup>
<EuiButton type="submit" fill onClick={this.createCredential}>
Create
Save
</EuiButton>
</EuiForm>
</EuiPageContent>
Expand All @@ -165,6 +169,7 @@ export class CreateCredentialWizard extends React.Component<
toasts: prevState.toasts.filter((toast) => toast.id !== id),
}));
};

render() {
const content = this.renderContent();

Expand All @@ -182,10 +187,6 @@ export class CreateCredentialWizard extends React.Component<
);
}

redact = (len: number) => {
return '*'.repeat(len);
};

createCredential = async () => {
const { http } = this.context.services;
try {
Expand All @@ -202,6 +203,8 @@ export class CreateCredentialWizard extends React.Component<
}),
})
.then((res) => {
// TODO: Fix routing
this.props.history.push('');
console.log(res);
});
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { FormattedMessage } from '@osd/i18n/react';
import {
EuiBadge,
EuiButtonEmpty,
EuiButton,
EuiFlexGroup,
EuiFlexItem,
EuiInMemoryTable,
Expand All @@ -34,7 +35,7 @@ import {
} from '../../../../opensearch_dashboards_react/public';

import { CredentialManagementContext } from '../../types';
import { getCredentials } from '../utils';
import { deleteCredentials, getCredentials } from '../utils';
import { CredentialsTableItem } from '../types';
import { CredentialCreationOption } from '../../service';
import { CreateButton } from '../create_button';
Expand Down Expand Up @@ -75,6 +76,7 @@ interface Props extends RouteComponentProps {
export const CredentialsTable = ({ canSave, history }: Props) => {
const [credentials, setCredentials] = React.useState<CredentialsTableItem[]>([]);
const [creationOptions, setCreationOptions] = React.useState<CredentialCreationOption[]>([]);
const [selectedCredentials, setSelectedCredentials] = React.useState<CredentialsTableItem[]>([]);

const {
savedObjects,
Expand All @@ -85,7 +87,7 @@ export const CredentialsTable = ({ canSave, history }: Props) => {
const columns = [
{
field: 'credentialName',
name: 'Credential',
name: 'Credential Name',
render: (
name: string,
index: {
Expand All @@ -112,8 +114,46 @@ export const CredentialsTable = ({ canSave, history }: Props) => {
dataType: 'string' as const,
sortable: ({ sort }: { sort: string }) => sort,
},
{
field: 'credentialType',
name: 'Credential Type',
truncateText: true,
mobileOptions: {
show: false,
},
},
];

const onSelectionChange = (selectedCredentials: CredentialsTableItem[]) => {
setSelectedCredentials(selectedCredentials);
};

const selection = {
onSelectionChange,
};

const renderDeleteButton = () => {
if (selectedCredentials.length === 0) {
return;
}

return (
<EuiButton color="danger" iconType="trash" onClick={onClickDelete}>
Delete {selectedCredentials.length} Credentials
</EuiButton>
);
};

const onClickDelete = () => {
Promise.resolve(deleteCredentials(savedObjects.client, selectedCredentials)).then(function () {
setSelectedCredentials([]);
// TODO: Fix routing
history.push('');
});
};

const deleteButton = renderDeleteButton();

React.useEffect(() => {
(async function () {
const options = await credentialManagementStart.creation.getCredentialCreationOptions(
Expand All @@ -138,7 +178,7 @@ export const CredentialsTable = ({ canSave, history }: Props) => {
<CreateButton options={creationOptions}>
<FormattedMessage
id="credentialManagement.credentialsTable.createBtn"
defaultMessage="Create credential"
defaultMessage="Save your credential"
/>
</CreateButton>
) : (
Expand All @@ -163,12 +203,14 @@ export const CredentialsTable = ({ canSave, history }: Props) => {
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>{createButton}</EuiFlexItem>
{deleteButton}
</EuiFlexGroup>
<EuiSpacer />
<EuiInMemoryTable
allowNeutralSort={false}
itemId="id"
isSelectable={false}
isSelectable={true}
selection={selection}
items={credentials}
columns={columns}
pagination={pagination}
Expand Down
17 changes: 11 additions & 6 deletions src/plugins/credential_management/public/components/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,13 @@

import { SavedObjectsClientContract } from 'src/core/public';
import { Credential } from '../../common';
// import { CredentialManagementStart } from '../plugin';
import { CredentialsTableItem } from './types';

export async function getCredentials(
savedObjectsClient: SavedObjectsClientContract,
defaultIndex: string
// credentialManagementStart: CredentialManagementStart
) {
return await (
savedObjectsClient
return await (savedObjectsClient
.find<Credential.ICredential>({
type: 'credential',
fields: ['id', 'credential_name', 'credential_type'],
Expand Down Expand Up @@ -49,6 +47,13 @@ return await (
return 0;
}
})
) || []
);
) || []);
}

export async function deleteCredentials(
savedObjectsClient: SavedObjectsClientContract,
selectedCredentials: CredentialsTableItem[]) {
selectedCredentials.forEach(function (selectedCredential) {
savedObjectsClient.delete('credential', selectedCredential.id);
});
}
8 changes: 6 additions & 2 deletions src/plugins/credential_management/server/routes/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
import { IRouter } from '../../../../core/server';
import { schema } from '@osd/config-schema';
import { createHandler } from '../credential';
import { Credential } from '../../common';

const USERNAME_PASSWORD_TYPE: Credential.USERNAME_PASSWORD_TYPE = 'username_password_credential';
const AWS_IAM_TYPE: Credential.AWS_IAM_TYPE = 'aws_iam_credential';

export function registerCreateRoute(router: IRouter) {
router.post(
Expand All @@ -21,8 +25,8 @@ export function registerCreateRoute(router: IRouter) {
body: schema.object({
credential_name: schema.string(),
credential_type: schema.oneOf([
schema.literal('username_password_credential'),
schema.literal('aws_iam_credential'),
schema.literal(USERNAME_PASSWORD_TYPE),
schema.literal(AWS_IAM_TYPE),
]),
username_password_credential_materials: schema.maybe(
schema.object({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export const credentialSavedObjectType: SavedObjectsType = {
getCredentialName(obj) {
return obj.attributes.credential_name;
},
getCredentialType(obj) {
return obj.attributes.credential_type;
},
getUserName(obj) {
return obj.attributes.user_name;
},
Expand Down

0 comments on commit 2fa92e0

Please sign in to comment.