Service accounts: Add a confirm modal for migration actions (#52604)

* Service accounts: Add a confirm modal for migration actions

* Handle the error case when migrating fails, reload page afterwards so that the tab disappears
This commit is contained in:
Vardan Torosyan 2022-07-21 18:56:20 +02:00 committed by GitHub
parent 83c1756251
commit f571c46495
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 25 deletions

View File

@ -1,27 +1,36 @@
import { css } from '@emotion/css';
import React from 'react';
import React, { useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { Alert, LinkButton, useStyles2 } from '@grafana/ui';
import { Alert, ConfirmModal, useStyles2, Button } from '@grafana/ui';
interface Props {
onHideApiKeys: () => void;
}
export const APIKeysMigratedCard = ({ onHideApiKeys }: Props): JSX.Element => {
const [isModalOpen, setIsModalOpen] = useState(false);
const styles = useStyles2(getStyles);
return (
<Alert title="API keys were migrated to Service accounts. This tab is deprecated." severity="info">
<Alert title="API keys were migrated to Grafana service accounts. This tab is deprecated." severity="info">
<div className={styles.text}>
We have upgraded your API keys into more powerful Service accounts and tokens. All your keys are safe and
working - you will find them inside respective service accounts. Keys are now called tokens.
We have migrated API keys into Grafana service accounts. All API keys are safe and continue working as they used
to, you can find them inside the respective service account.
</div>
<div className={styles.actionRow}>
<LinkButton className={styles.actionButton} href="org/serviceaccounts" onClick={onHideApiKeys}>
Go to service accounts tab and never show API keys tab again
</LinkButton>
<a href="org/serviceaccounts">Go to service accounts tab</a>
<Button className={styles.actionButton} onClick={() => setIsModalOpen(true)}>
Hide API keys page forever
</Button>
<ConfirmModal
title={'Hide API Keys page forever'}
isOpen={isModalOpen}
body={'Are you sure you want to hide API keys page forever and use service accounts from now on?'}
confirmText={'Yes, hide API keys page.'}
onConfirm={onHideApiKeys}
onDismiss={() => setIsModalOpen(false)}
/>
<a href="org/serviceaccounts">View service accounts page</a>
</div>
</Alert>
);

View File

@ -3,6 +3,7 @@ import { connect, ConnectedProps } from 'react-redux';
// Utils
import { rangeUtil } from '@grafana/data';
import { locationService } from '@grafana/runtime';
import { InlineField, InlineSwitch, VerticalGroup } from '@grafana/ui';
import appEvents from 'app/core/app_events';
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
@ -142,8 +143,14 @@ export class ApiKeysPageUnconnected extends PureComponent<Props, State> {
};
onHideApiKeys = async () => {
await this.props.hideApiKeys();
window.location.reload();
try {
await this.props.hideApiKeys();
let serviceAccountsUrl = '/org/serviceaccounts';
locationService.push(serviceAccountsUrl);
window.location.reload();
} catch (err) {
console.error(err);
}
};
render() {

View File

@ -50,7 +50,7 @@ export const ApiKeysTable: FC<Props> = ({ apiKeys, timeZone, onDelete, onMigrate
<td>
<HorizontalGroup justify="flex-end">
<Button size="sm" onClick={() => onMigrate(key)}>
Migrate
Migrate to service account
</Button>
<DeleteButton
aria-label="Delete API key"

View File

@ -1,8 +1,8 @@
import { css } from '@emotion/css';
import React from 'react';
import React, { useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { Alert, Button, useStyles2 } from '@grafana/ui';
import { Alert, Button, ConfirmModal, useStyles2 } from '@grafana/ui';
interface Props {
onMigrate: () => void;
@ -10,22 +10,41 @@ interface Props {
}
export const MigrateToServiceAccountsCard = ({ onMigrate, disabled }: Props): JSX.Element => {
const [isModalOpen, setIsModalOpen] = useState(false);
const styles = useStyles2(getStyles);
const docsLink = (
<a
className="external-link"
href="https://grafana.com/docs/grafana/latest/administration/api-keys/#migrate-api-keys-to-grafana-service-accounts/"
target="_blank"
rel="noopener noreferrer"
>
here.
</a>
);
const migrationBoxDesc = (
<span>Are you sure you want to migrate all API keys to service accounts? Find out more {docsLink}</span>
);
return (
<Alert title="Switch from API keys to Service accounts" severity="info">
<Alert title="Switch from API keys to service accounts" severity="info">
<div className={styles.text}>
Service accounts give you more control. API keys will be automatically migrated into tokens inside respective
service accounts. The current API keys will still work, but will be called tokens and you will find them in the
detail view of a respective service account.
Each API key will be automatically migrated into a service account with a token. The service account will be
created with the same permission as the API Key and current API Keys will continue to work as they were.
</div>
<div className={styles.actionRow}>
{!disabled && (
<Button className={styles.actionButton} onClick={onMigrate}>
Migrate now
</Button>
)}
<span>Read more about Service accounts and how to turn them on</span>
<Button className={styles.actionButton} onClick={() => setIsModalOpen(true)}>
Migrate to service accounts now
</Button>
<ConfirmModal
title={'Migrate API keys to service accounts'}
isOpen={isModalOpen}
body={migrationBoxDesc}
confirmText={'Yes, migrate now'}
onConfirm={onMigrate}
onDismiss={() => setIsModalOpen(false)}
/>
</div>
</Alert>
);

View File

@ -219,7 +219,7 @@ export const ServiceAccountsListPageUnconnected = ({
<RadioButtonGroup
options={[
{ label: 'All', value: ServiceAccountStateFilter.All },
{ label: 'With expiring tokens', value: ServiceAccountStateFilter.WithExpiredTokens },
{ label: 'With expired tokens', value: ServiceAccountStateFilter.WithExpiredTokens },
{ label: 'Disabled', value: ServiceAccountStateFilter.Disabled },
]}
onChange={onStateFilterChange}