Skip to content

Commit

Permalink
feat(auth): delete system keys (#4426)
Browse files Browse the repository at this point in the history
* feat(auth): delete system keys

* Fix
  • Loading branch information
mikeldking authored Aug 28, 2024
1 parent 7faaba2 commit a6fa21e
Show file tree
Hide file tree
Showing 8 changed files with 379 additions and 15 deletions.
9 changes: 8 additions & 1 deletion app/src/pages/settings/APIKeysCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
TabPane,
Tabs,
TextField,
View,
} from "@arizeai/components";

import { CopyToClipboardButton, Loading } from "@phoenix/components";
Expand Down Expand Up @@ -71,7 +72,13 @@ export function APIKeysCard() {
</Button>
}
>
<Suspense fallback={<Loading />}>
<Suspense
fallback={
<View padding="size-100">
<Loading />
</View>
}
>
<APIKeysCardContent />
</Suspense>
</TabbedCard>
Expand Down
100 changes: 100 additions & 0 deletions app/src/pages/settings/DeleteSystemAPIKeyButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, { ReactNode, useCallback, useState } from "react";
import { graphql, useMutation } from "react-relay";

import {
Button,
Dialog,
DialogContainer,
Flex,
Icon,
Icons,
Text,
View,
} from "@arizeai/components";

import { useNotifySuccess } from "@phoenix/contexts";

export function DeleteSystemAPIKeyButton({
id,
onDeleted,
}: {
id: string;
onDeleted: () => void;
}) {
const [dialog, setDialog] = useState<ReactNode>(null);
const notifySuccess = useNotifySuccess();
const [commit] = useMutation(graphql`
mutation DeleteSystemAPIKeyButtonMutation($input: DeleteApiKeyInput!) {
deleteSystemApiKey(input: $input) {
__typename
id
}
}
`);
const handleDelete = useCallback(() => {
commit({
variables: {
input: {
id,
},
},
onCompleted: () => {
notifySuccess({
title: "System key deleted",
message: "The system key has been deleted and is no longer active.",
});
setDialog(null);
onDeleted();
},
});
}, [commit, id, notifySuccess, setDialog]);
const onDelete = () => {
setDialog(
<Dialog title="Delete System Key">
<View padding="size-200">
<Text color="danger">
{`Are you sure you want to delete this system key? This cannot be undone and will disable all services using this key.`}
</Text>
</View>
<View
paddingEnd="size-200"
paddingTop="size-100"
paddingBottom="size-100"
borderTopColor="light"
borderTopWidth="thin"
>
<Flex direction="row" justifyContent="end">
<Button
variant="danger"
onClick={() => {
handleDelete();
setDialog(null);
}}
>
Delete Key
</Button>
</Flex>
</View>
</Dialog>
);
};
return (
<>
<Button
variant="danger"
size="compact"
icon={<Icon svg={<Icons.TrashOutline />} />}
aria-label="Delete System Key"
onClick={onDelete}
/>
<DialogContainer
isDismissable
onDismiss={() => {
setDialog(null);
}}
>
{dialog}
</DialogContainer>
</>
);
}
2 changes: 1 addition & 1 deletion app/src/pages/settings/SettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const settingsPageCSS = css`

const settingsPageInnerCSS = css`
padding: var(--ac-global-dimension-size-400);
max-width: 800px;
max-width: 1000px;
min-width: 500px;
box-sizing: border-box;
width: 100%;
Expand Down
54 changes: 46 additions & 8 deletions app/src/pages/settings/SystemAPIKeysTable.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
import React, { useMemo } from "react";
import { graphql, useFragment } from "react-relay";
import React, { startTransition, useMemo } from "react";
import { graphql, useRefetchableFragment } from "react-relay";
import {
ColumnDef,
flexRender,
getCoreRowModel,
useReactTable,
} from "@tanstack/react-table";

import { Icon, Icons } from "@arizeai/components";
import { Flex, Icon, Icons } from "@arizeai/components";

import { TextCell } from "@phoenix/components/table";
import { tableCSS } from "@phoenix/components/table/styles";
import { TableEmpty } from "@phoenix/components/table/TableEmpty";
import { TimestampCell } from "@phoenix/components/table/TimestampCell";

import { SystemAPIKeysTableFragment$key } from "./__generated__/SystemAPIKeysTableFragment.graphql";
import { SystemAPIKeysTableQuery } from "./__generated__/SystemAPIKeysTableQuery.graphql";
import { DeleteSystemAPIKeyButton } from "./DeleteSystemAPIKeyButton";

export function SystemAPIKeysTable({
query,
}: {
query: SystemAPIKeysTableFragment$key;
}) {
const data = useFragment<SystemAPIKeysTableFragment$key>(
const [data, refetch] = useRefetchableFragment<
SystemAPIKeysTableQuery,
SystemAPIKeysTableFragment$key
>(
graphql`
fragment SystemAPIKeysTableFragment on Query {
fragment SystemAPIKeysTableFragment on Query
@refetchable(queryName: "SystemAPIKeysTableQuery") {
systemApiKeys {
id
name
Expand All @@ -40,8 +47,8 @@ export function SystemAPIKeysTable({
}, [data]);

type TableRow = (typeof tableData)[number];
const table = useReactTable<TableRow>({
columns: [
const columns = useMemo(() => {
const cols: ColumnDef<TableRow>[] = [
{
header: "Name",
accessorKey: "name",
Expand All @@ -61,7 +68,38 @@ export function SystemAPIKeysTable({
accessorKey: "expiresAt",
cell: TimestampCell,
},
],
{
header: "",
accessorKey: "id",
size: 10,
cell: ({ row }) => {
return (
<Flex direction="row" justifyContent="end" width="100%">
<DeleteSystemAPIKeyButton
id={row.original.id}
onDeleted={() => {
startTransition(() => {
refetch(
{},
{
fetchPolicy: "network-only",
}
);
});
}}
/>
</Flex>
);
},
meta: {
textAlign: "right",
},
},
];
return cols;
}, [refetch]);
const table = useReactTable<TableRow>({
columns,
data: tableData,
getCoreRowModel: getCoreRowModel(),
});
Expand Down
9 changes: 8 additions & 1 deletion app/src/pages/settings/UsersCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
DialogContainer,
Icon,
Icons,
View,
} from "@arizeai/components";

import { Loading } from "@phoenix/components";
Expand Down Expand Up @@ -74,7 +75,13 @@ export function UsersCard() {
</Button>
}
>
<Suspense fallback={<Loading />}>
<Suspense
fallback={
<View padding="size-e00">
<Loading />
</View>
}
>
<UsersTable query={data} />
</Suspense>
<DialogContainer
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit a6fa21e

Please sign in to comment.