2023-03-15 23:28:57 +01:00
|
|
|
<script lang="ts">
|
2023-03-30 16:50:30 +02:00
|
|
|
import type { APIError } from "$lib/api/entities";
|
|
|
|
import { apiFetchClient, fastFetchClient } from "$lib/api/fetch";
|
2023-03-15 23:28:57 +01:00
|
|
|
import { DateTime } from "luxon";
|
2023-03-30 16:50:30 +02:00
|
|
|
import {
|
|
|
|
Button,
|
|
|
|
ButtonGroup,
|
|
|
|
Card,
|
|
|
|
CardBody,
|
|
|
|
CardHeader,
|
|
|
|
Modal,
|
|
|
|
ModalBody,
|
|
|
|
ModalFooter,
|
|
|
|
ModalHeader,
|
|
|
|
} from "sveltestrap";
|
2023-03-15 23:28:57 +01:00
|
|
|
import type { PageData } from "./$types";
|
2023-03-15 16:30:27 +01:00
|
|
|
|
2023-03-30 16:50:30 +02:00
|
|
|
interface Token {
|
|
|
|
token: string;
|
|
|
|
id: string;
|
|
|
|
api_only: boolean;
|
|
|
|
read_only: boolean;
|
|
|
|
created: string;
|
|
|
|
expires: string;
|
|
|
|
}
|
|
|
|
|
2023-03-15 23:28:57 +01:00
|
|
|
export let data: PageData;
|
|
|
|
|
2023-03-30 16:50:30 +02:00
|
|
|
let newToken: string | null = null;
|
|
|
|
let error: APIError | null = null;
|
|
|
|
|
|
|
|
let newTokenModalOpen = false;
|
|
|
|
const toggleNewTokenModalOpen = () => (newTokenModalOpen = !newTokenModalOpen);
|
|
|
|
|
|
|
|
const createToken = async (readOnly: boolean) => {
|
|
|
|
try {
|
|
|
|
const token = await apiFetchClient<Token>(`/auth/tokens?read_only=${readOnly}`, "POST");
|
|
|
|
newToken = token.token;
|
|
|
|
error = null;
|
|
|
|
data.tokens = [...data.tokens, token];
|
|
|
|
toggleNewTokenModalOpen();
|
|
|
|
} catch (e) {
|
|
|
|
error = e as APIError;
|
|
|
|
}
|
|
|
|
};
|
2023-03-15 23:28:57 +01:00
|
|
|
</script>
|
|
|
|
|
2023-03-30 16:50:30 +02:00
|
|
|
<h1>
|
|
|
|
Tokens ({data.tokens.length})
|
|
|
|
<ButtonGroup>
|
|
|
|
<Button color="success" on:click={() => createToken(false)}>New API token</Button>
|
|
|
|
<Button color="success" on:click={() => createToken(true)}>New read-only API token</Button>
|
|
|
|
</ButtonGroup>
|
|
|
|
</h1>
|
|
|
|
|
|
|
|
{#each data.tokens as token}
|
|
|
|
<Card class="my-2">
|
|
|
|
<CardHeader>{token.id}</CardHeader>
|
|
|
|
<CardBody>
|
|
|
|
<ul class="list-unstyled">
|
|
|
|
<li>
|
|
|
|
<strong>Created at:</strong>
|
|
|
|
{DateTime.fromISO(token.created).toLocal().toLocaleString(DateTime.DATETIME_MED)}
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<strong>Expires at:</strong>
|
|
|
|
{DateTime.fromISO(token.expires).toLocal().toLocaleString(DateTime.DATETIME_MED)}
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<strong>Read-only:</strong>
|
|
|
|
{token.read_only ? "yes" : "no"}
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</CardBody>
|
|
|
|
</Card>
|
|
|
|
{:else}
|
|
|
|
You don't have any unexpired API tokens right now.
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
<Modal isOpen={newTokenModalOpen}>
|
|
|
|
<ModalHeader toggle={toggleNewTokenModalOpen}>New token created</ModalHeader>
|
|
|
|
<ModalBody>
|
|
|
|
<p>Created a new API token! Please save it somewhere secure, as it will only be shown once.</p>
|
|
|
|
<p><code>{newToken}</code></p>
|
|
|
|
</ModalBody>
|
|
|
|
<ModalFooter>
|
|
|
|
<Button color="secondary" on:click={toggleNewTokenModalOpen}>Close</Button>
|
|
|
|
</ModalFooter>
|
|
|
|
</Modal>
|