Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sdk): add pages to delete service account and token #825

Merged
merged 5 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const AddServiceAccount = () => {
}
});
}
} catch ({ error }: any) {
} catch (error: any) {
toast.error('Something went wrong', {
description: error.message
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TrashIcon } from '@radix-ui/react-icons';
import { ApsaraColumnDef } from '@raystack/apsara';
import { Button, Flex, Text } from '@raystack/apsara/v1';
import { Link } from '@tanstack/react-router';
import { Link, useNavigate } from '@tanstack/react-router';
import dayjs from 'dayjs';
import { V1Beta1ServiceUser } from '~/api-client';

Expand Down Expand Up @@ -34,7 +34,7 @@
{
header: 'Created on',
accessorKey: 'created_at',
cell: ({ row, getValue }) => {

Check warning on line 37 in sdks/js/packages/core/react/components/organization/api-keys/columns.tsx

View workflow job for this annotation

GitHub Actions / JS SDK Lint

'row' is defined but never used
const value = getValue();
return (
<Flex direction="column">
Expand All @@ -52,17 +52,27 @@
padding: 0
}
},
cell: ({ row, getValue }) => {

Check warning on line 55 in sdks/js/packages/core/react/components/organization/api-keys/columns.tsx

View workflow job for this annotation

GitHub Actions / JS SDK Lint

'row' is defined but never used
return (
<Button
variant="text"
size="small"
data-test-id="frontier-sdk-delete-service-account-btn"
>
<TrashIcon />
</Button>
);
return <ServiceAccountDeleteAction id={getValue()} />;
}
}
];
};

function ServiceAccountDeleteAction({ id }: { id: string }) {
const navigate = useNavigate({ from: '/api-keys' });

function onDeleteClick() {
return navigate({ to: '/api-keys/$id/delete', params: { id: id } });
}
return (
<Button
variant="text"
size="small"
data-test-id="frontier-sdk-delete-service-account-btn"
onClick={onDeleteClick}
>
<TrashIcon />
</Button>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { Dialog, Separator, Image } from '@raystack/apsara';
import styles from './styles.module.css';
import { Button, Flex, Text, toast } from '@raystack/apsara/v1';
import cross from '~/react/assets/cross.svg';
import { useNavigate, useParams } from '@tanstack/react-router';
import { useFrontier } from '~/react/contexts/FrontierContext';
import { useState } from 'react';

export const DeleteServiceAccount = () => {
const { id } = useParams({ from: '/api-keys/$id/delete' });
const navigate = useNavigate({ from: '/api-keys/$id/delete' });
const { client, activeOrganization: organization } = useFrontier();
const [isLoading, setIsLoading] = useState(false);

const orgId = organization?.id;

async function onDeleteClick() {
try {
setIsLoading(true);
await client?.frontierServiceDeleteServiceUser(id, { org_id: orgId });
navigate({
to: '/api-keys',
state: {
refetch: true
}
});
toast.success('Service account deleted');
} catch (err: any) {
toast.error('Unable to delete service account', {
description: err?.message
});
} finally {
setIsLoading(false);
}
}

function onCancel() {
navigate({ to: '/api-keys' });
}

return (
<Dialog open={true}>
{/* @ts-ignore */}
<Dialog.Content
overlayClassname={styles.overlay}
className={styles.addDialogContent}
>
<Flex justify="between" className={styles.addDialogForm}>
<Text size={6} weight={500}>
Delete Service Account
</Text>

<Image
alt="cross"
style={{ cursor: 'pointer' }}
// @ts-ignore
src={cross}
onClick={() => navigate({ to: '/api-keys' })}
data-test-id="frontier-sdk-delete-service-account-close-btn"
/>
</Flex>
<Separator />

<Flex
direction="column"
gap="medium"
className={styles.addDialogFormContent}
>
<Text>
This is an irreversible and permanent action doing this might result
in deletion of the service account and the keys associated with it.
Do you wish to proceed?
</Text>
</Flex>
<Separator />
<Flex
justify="end"
className={styles.addDialogFormBtnWrapper}
gap={'medium'}
>
<Button
variant="secondary"
size="normal"
data-test-id="frontier-sdk-delete-service-account-cancel-btn"
onClick={onCancel}
>
Cancel
</Button>
<Button
variant="danger"
size="normal"
data-test-id="frontier-sdk-delete-service-account-confirm-btn"
loading={isLoading}
disabled={isLoading}
onClick={onDeleteClick}
loaderText="Deleting..."
>
I Understand and Delete
rsbh marked this conversation as resolved.
Show resolved Hide resolved
</Button>
</Flex>
</Dialog.Content>
</Dialog>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { ExclamationTriangleIcon } from '@radix-ui/react-icons';
import Skeleton from 'react-loading-skeleton';
import { getColumns } from './columns';
import { V1Beta1ServiceUser } from '~/api-client/dist';
import { Outlet, useNavigate } from '@tanstack/react-router';
import { Outlet, useLocation, useNavigate } from '@tanstack/react-router';

const NoServiceAccounts = ({
config
Expand Down Expand Up @@ -165,6 +165,8 @@ const ServiceAccountsTable = ({
export default function ApiKeys() {
const [serviceUsers, setServiceUsers] = useState<V1Beta1ServiceUser[]>([]);
const [isServiceUsersLoading, setIsServiceUsersLoading] = useState(false);
const location = useLocation();
const refetch = location?.state?.refetch;

const {
activeOrganization: organization,
Expand Down Expand Up @@ -196,7 +198,7 @@ export default function ApiKeys() {
if (organization?.id && canUpdateWorkspace) {
getServiceAccounts(organization?.id);
}
}, [organization?.id, client, canUpdateWorkspace]);
}, [organization?.id, client, canUpdateWorkspace, refetch]);

const isLoading =
isActiveOrganizationLoading ||
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { Dialog, Separator, Image } from '@raystack/apsara';
import styles from './styles.module.css';
import { Button, Flex, Text, toast } from '@raystack/apsara/v1';
import cross from '~/react/assets/cross.svg';
import { useNavigate, useParams } from '@tanstack/react-router';
import { useFrontier } from '~/react/contexts/FrontierContext';
import { useState } from 'react';
import { DEFAULT_API_PLATFORM_APP_NAME } from '~/react/utils/constants';

export const DeleteServiceAccountKey = () => {
const { id, tokenId } = useParams({
from: '/api-keys/$id/key/$tokenId/delete'
});
const navigate = useNavigate({ from: '/api-keys/$id/key/$tokenId/delete' });
const { client, config } = useFrontier();
const [isLoading, setIsLoading] = useState(false);

async function onDeleteClick() {
try {
setIsLoading(true);
await client?.frontierServiceDeleteServiceUserToken(id, tokenId);
navigate({
to: '/api-keys/$id',
params: {
id: id
},
state: {
refetch: true
}
});
toast.success('Service account key revoked');
} catch (err: any) {
toast.error('Unable to revoke service account key', {
description: err?.message
});
} finally {
setIsLoading(false);
}
}

function onCancel() {
navigate({
to: '/api-keys/$id',
params: {
id: id
}
});
}
const appName = config?.apiPlatform?.appName || DEFAULT_API_PLATFORM_APP_NAME;

return (
<Dialog open={true}>
{/* @ts-ignore */}
<Dialog.Content
overlayClassname={styles.overlay}
className={styles.addDialogContent}
>
<Flex justify="between" className={styles.addDialogForm}>
<Text size={6} weight={500}>
Revoke API Key
</Text>

<Image
alt="cross"
style={{ cursor: 'pointer' }}
// @ts-ignore
src={cross}
onClick={onCancel}
data-test-id="frontier-sdk-revoke-service-account-key-close-btn"
/>
</Flex>
<Separator />

<Flex
direction="column"
gap="medium"
className={styles.addDialogFormContent}
>
<Text>
This is an irreversible action doing this might lead to
discontinuation of access to the {appName} features. Do you wish to
proceed?
</Text>
</Flex>
<Separator />
<Flex
justify="end"
className={styles.addDialogFormBtnWrapper}
gap={'medium'}
>
<Button
variant="secondary"
size="normal"
data-test-id="frontier-sdk-revoke-service-account-key-cancel-btn"
onClick={onCancel}
>
Cancel
</Button>
<Button
variant="danger"
size="normal"
data-test-id="frontier-sdk-revoke-service-account-key-confirm-btn"
loading={isLoading}
disabled={isLoading}
onClick={onDeleteClick}
loaderText="Revoking..."
>
Revoke
</Button>
</Flex>
</Dialog.Content>
</Dialog>
);
};
Loading
Loading