2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-17 20:45:44 +00:00

[FR] Add Tokens to PUI (#7693)

* [FR] Add Tokens to PUI
Fixes #6500

* fix name / call pattern

* cleanup

* add "revoke" action

* Lock currently used token

* Update serializers.py

* bump api version
This commit is contained in:
Matthias Mair
2024-07-22 12:25:45 +02:00
committed by GitHub
parent 69298c365a
commit d46ed4af6f
5 changed files with 158 additions and 5 deletions

View File

@ -14,6 +14,7 @@ export enum ApiEndpoints {
user_me = 'user/me/',
user_roles = 'user/roles/',
user_token = 'user/token/',
user_tokens = 'user/tokens/',
user_simple_login = 'email/generate/',
user_reset = 'auth/password/reset/',
user_reset_set = 'auth/password/reset/confirm/',

View File

@ -8,6 +8,7 @@ import {
Loader,
Radio,
Stack,
Table,
Text,
TextInput,
Title,
@ -15,9 +16,10 @@ import {
} from '@mantine/core';
import { IconAlertCircle, IconAt } from '@tabler/icons-react';
import { useQuery } from '@tanstack/react-query';
import { useEffect, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { api, queryClient } from '../../../../App';
import { YesNoButton } from '../../../../components/buttons/YesNoButton';
import { PlaceholderPill } from '../../../../components/items/Placeholder';
import { ApiEndpoints } from '../../../../enums/ApiEndpoints';
import { apiUrl } from '../../../../states/ApiState';
@ -85,6 +87,11 @@ export function SecurityContent() {
)}
</>
)}
<Title order={5}>
<Trans>Token</Trans>
</Title>
<TokenContent />
</Stack>
);
}
@ -329,3 +336,85 @@ function MfaContent() {
</>
);
}
function TokenContent() {
const { isLoading, data, refetch } = useQuery({
queryKey: ['token-list'],
queryFn: () =>
api.get(apiUrl(ApiEndpoints.user_tokens)).then((res) => res.data)
});
function revokeToken(id: string) {
api
.delete(apiUrl(ApiEndpoints.user_tokens, id))
.then(() => {
refetch();
})
.catch((res) => console.log(res.data));
}
const rows = useMemo(() => {
if (isLoading || data === undefined) return null;
return data.map((token: any) => (
<Table.Tr key={token.id}>
<Table.Td>
<YesNoButton value={token.active} />
</Table.Td>
<Table.Td>{token.expiry}</Table.Td>
<Table.Td>{token.last_seen}</Table.Td>
<Table.Td>{token.token}</Table.Td>
<Table.Td>{token.name}</Table.Td>
<Table.Td>
{token.in_use ? (
<Trans>Token is used - no actions</Trans>
) : (
<Button
onClick={() => revokeToken(token.id)}
color="red"
disabled={!token.active}
>
<Trans>Revoke</Trans>
</Button>
)}
</Table.Td>
</Table.Tr>
));
}, [data, isLoading]);
/* renderer */
if (isLoading) return <Loader />;
if (data.length == 0)
return (
<Alert icon={<IconAlertCircle size="1rem" />} color="green">
<Trans>No tokens configured</Trans>
</Alert>
);
return (
<Table stickyHeader striped highlightOnHover withTableBorder>
<Table.Thead>
<Table.Tr>
<Table.Th>
<Trans>Active</Trans>
</Table.Th>
<Table.Th>
<Trans>Expiry</Trans>
</Table.Th>
<Table.Th>
<Trans>Last Seen</Trans>
</Table.Th>
<Table.Th>
<Trans>Token</Trans>
</Table.Th>
<Table.Th>
<Trans>Name</Trans>
</Table.Th>
<Table.Th>
<Trans>Actions</Trans>
</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
);
}