160 lines
4.4 KiB
TypeScript
160 lines
4.4 KiB
TypeScript
import React from 'react';
|
|
|
|
import { Button, Stack } from '@grafana/ui';
|
|
import cn from 'classnames/bind';
|
|
import { observer } from 'mobx-react';
|
|
import moment from 'moment-timezone';
|
|
|
|
import { GTable } from 'components/GTable/GTable';
|
|
import { Text } from 'components/Text/Text';
|
|
import { WithConfirm } from 'components/WithConfirm/WithConfirm';
|
|
import { WithPermissionControlTooltip } from 'containers/WithPermissionControl/WithPermissionControlTooltip';
|
|
import { ApiToken } from 'models/api_token/api_token.types';
|
|
import { WithStoreProps } from 'state/types';
|
|
import { withMobXProviderContext } from 'state/withStore';
|
|
import { generateMissingPermissionMessage, isUserActionAllowed, UserActions } from 'utils/authorization/authorization';
|
|
|
|
import { ApiTokenForm } from './ApiTokenForm';
|
|
|
|
import styles from './ApiTokenSettings.module.css';
|
|
|
|
const cx = cn.bind(styles);
|
|
|
|
const MAX_TOKENS_PER_USER = 5;
|
|
const REQUIRED_PERMISSION_TO_VIEW = UserActions.APIKeysWrite;
|
|
|
|
interface ApiTokensProps extends WithStoreProps {}
|
|
|
|
@observer
|
|
class _ApiTokenSettings extends React.Component<ApiTokensProps, any> {
|
|
constructor(props: any) {
|
|
super(props);
|
|
|
|
this.state = { showCreateTokenModal: false };
|
|
}
|
|
|
|
componentDidMount() {
|
|
const {
|
|
store: { apiTokenStore },
|
|
} = this.props;
|
|
|
|
apiTokenStore.updateItems();
|
|
}
|
|
|
|
render() {
|
|
const { store } = this.props;
|
|
const { apiTokenStore } = store;
|
|
|
|
const { isMobile } = store;
|
|
|
|
const apiTokens = apiTokenStore.getSearchResult();
|
|
|
|
const { showCreateTokenModal } = this.state;
|
|
|
|
const columns = [
|
|
{
|
|
title: 'Name',
|
|
dataIndex: 'name',
|
|
},
|
|
{
|
|
title: 'Created At',
|
|
key: 'created_at',
|
|
render: this.renderCreatedAt,
|
|
},
|
|
{
|
|
width: 100,
|
|
key: 'action',
|
|
render: this.renderActionButtons,
|
|
},
|
|
];
|
|
|
|
const authorizedToViewAPIKeys = isUserActionAllowed(REQUIRED_PERMISSION_TO_VIEW);
|
|
|
|
let emptyText = 'Loading...';
|
|
if (!authorizedToViewAPIKeys) {
|
|
emptyText = `${generateMissingPermissionMessage(REQUIRED_PERMISSION_TO_VIEW)} to be able to view API tokens.`;
|
|
} else if (apiTokens) {
|
|
emptyText = 'No tokens found';
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<GTable
|
|
title={() => (
|
|
<div className={cx('header')}>
|
|
<Stack alignItems="flex-end">
|
|
<Text.Title level={3}>API Tokens</Text.Title>
|
|
</Stack>
|
|
<WithPermissionControlTooltip userAction={UserActions.APIKeysWrite}>
|
|
<Button
|
|
icon="plus"
|
|
disabled={apiTokens && apiTokens.length >= MAX_TOKENS_PER_USER}
|
|
onClick={() => {
|
|
this.setState({ showCreateTokenModal: true });
|
|
}}
|
|
>
|
|
Create
|
|
</Button>
|
|
</WithPermissionControlTooltip>
|
|
</div>
|
|
)}
|
|
rowKey="id"
|
|
className="api-keys"
|
|
showHeader={!isMobile}
|
|
data={apiTokens}
|
|
emptyText={emptyText}
|
|
columns={columns}
|
|
/>
|
|
{showCreateTokenModal && (
|
|
<ApiTokenForm
|
|
visible={showCreateTokenModal}
|
|
onUpdate={this.handleCreateToken}
|
|
onHide={() => {
|
|
this.setState({ showCreateTokenModal: false });
|
|
}}
|
|
/>
|
|
)}
|
|
</>
|
|
);
|
|
}
|
|
|
|
renderActionButtons = (record: ApiToken) => {
|
|
const revokeButton = (
|
|
<WithPermissionControlTooltip userAction={UserActions.APIKeysWrite}>
|
|
<WithConfirm title={`Are you sure to revoke "${record.name}" API token?`} confirmText="Revoke token">
|
|
<Button fill="text" variant="destructive" onClick={this.getRevokeTokenClickHandler(record.id)}>
|
|
Revoke
|
|
</Button>
|
|
</WithConfirm>
|
|
</WithPermissionControlTooltip>
|
|
);
|
|
|
|
return revokeButton;
|
|
};
|
|
|
|
renderCreatedAt = (record: ApiToken) => {
|
|
const date = moment(record.created_at);
|
|
return <span> {date.format('MMM DD, YYYY hh:mm')}</span>;
|
|
};
|
|
|
|
getRevokeTokenClickHandler = (id: ApiToken['id']) => {
|
|
const {
|
|
store: { apiTokenStore },
|
|
} = this.props;
|
|
|
|
return async () => {
|
|
await apiTokenStore.revokeApiToken(id);
|
|
apiTokenStore.updateItems();
|
|
};
|
|
};
|
|
|
|
handleCreateToken = () => {
|
|
const {
|
|
store: { apiTokenStore },
|
|
} = this.props;
|
|
|
|
apiTokenStore.updateItems();
|
|
};
|
|
}
|
|
|
|
export const ApiTokenSettings = withMobXProviderContext(_ApiTokenSettings);
|