feat(frontend): list tokens, use formatted dates
This commit is contained in:
parent
4fbbafc763
commit
bfa810fbb2
|
@ -43,6 +43,7 @@
|
||||||
"base64-arraybuffer": "^1.0.2",
|
"base64-arraybuffer": "^1.0.2",
|
||||||
"bootstrap": "5.3.0-alpha1",
|
"bootstrap": "5.3.0-alpha1",
|
||||||
"bootstrap-icons": "^1.10.3",
|
"bootstrap-icons": "^1.10.3",
|
||||||
|
"jose": "^4.13.1",
|
||||||
"luxon": "^3.3.0",
|
"luxon": "^3.3.0",
|
||||||
"marked": "^4.2.12",
|
"marked": "^4.2.12",
|
||||||
"sanitize-html": "^2.10.0",
|
"sanitize-html": "^2.10.0",
|
||||||
|
|
|
@ -20,6 +20,7 @@ specifiers:
|
||||||
eslint: ^8.28.0
|
eslint: ^8.28.0
|
||||||
eslint-config-prettier: ^8.5.0
|
eslint-config-prettier: ^8.5.0
|
||||||
eslint-plugin-svelte3: ^4.0.0
|
eslint-plugin-svelte3: ^4.0.0
|
||||||
|
jose: ^4.13.1
|
||||||
luxon: ^3.3.0
|
luxon: ^3.3.0
|
||||||
marked: ^4.2.12
|
marked: ^4.2.12
|
||||||
postcss: ^8.4.21
|
postcss: ^8.4.21
|
||||||
|
@ -40,6 +41,7 @@ dependencies:
|
||||||
base64-arraybuffer: 1.0.2
|
base64-arraybuffer: 1.0.2
|
||||||
bootstrap: 5.3.0-alpha1_@popperjs+core@2.11.6
|
bootstrap: 5.3.0-alpha1_@popperjs+core@2.11.6
|
||||||
bootstrap-icons: 1.10.3
|
bootstrap-icons: 1.10.3
|
||||||
|
jose: 4.13.1
|
||||||
luxon: 3.3.0
|
luxon: 3.3.0
|
||||||
marked: 4.2.12
|
marked: 4.2.12
|
||||||
sanitize-html: 2.10.0
|
sanitize-html: 2.10.0
|
||||||
|
@ -1546,6 +1548,10 @@ packages:
|
||||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/jose/4.13.1:
|
||||||
|
resolution: {integrity: sha512-MSJQC5vXco5Br38mzaQKiq9mwt7lwj2eXpgpRyQYNHYt2lq1PjkWa7DLXX0WVcQLE9HhMh3jPiufS7fhJf+CLQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/js-sdsl/4.3.0:
|
/js-sdsl/4.3.0:
|
||||||
resolution: {integrity: sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==}
|
resolution: {integrity: sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
|
@ -74,7 +74,7 @@ export interface MemberPartialUser {
|
||||||
|
|
||||||
export interface Invite {
|
export interface Invite {
|
||||||
code: string;
|
code: string;
|
||||||
created: Date;
|
created: string;
|
||||||
used: boolean;
|
used: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,5 +32,5 @@ interface CallbackResponse {
|
||||||
require_invite: boolean;
|
require_invite: boolean;
|
||||||
|
|
||||||
is_deleted: boolean;
|
is_deleted: boolean;
|
||||||
deleted_at?: Date;
|
deleted_at?: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
active={$page.url.pathname === "/settings/tokens"}
|
active={$page.url.pathname === "/settings/tokens"}
|
||||||
href="/settings/tokens"
|
href="/settings/tokens"
|
||||||
>
|
>
|
||||||
API tokens
|
Tokens
|
||||||
</ListGroupItem>
|
</ListGroupItem>
|
||||||
<ListGroupItem
|
<ListGroupItem
|
||||||
tag="a"
|
tag="a"
|
||||||
|
|
|
@ -5,16 +5,7 @@
|
||||||
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
|
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
|
||||||
import FallbackImage from "$lib/components/FallbackImage.svelte";
|
import FallbackImage from "$lib/components/FallbackImage.svelte";
|
||||||
import { userStore } from "$lib/store";
|
import { userStore } from "$lib/store";
|
||||||
import {
|
import { Button, Icon, Modal, ModalBody, ModalFooter, ModalHeader, Table } from "sveltestrap";
|
||||||
Alert,
|
|
||||||
Button,
|
|
||||||
Icon,
|
|
||||||
Modal,
|
|
||||||
ModalBody,
|
|
||||||
ModalFooter,
|
|
||||||
ModalHeader,
|
|
||||||
Table,
|
|
||||||
} from "sveltestrap";
|
|
||||||
import type { PageData } from "./$types";
|
import type { PageData } from "./$types";
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
|
@ -15,5 +15,5 @@ export const load = async () => {
|
||||||
|
|
||||||
interface ExportResponse {
|
interface ExportResponse {
|
||||||
path: string;
|
path: string;
|
||||||
created_at: Date;
|
created_at: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
import type { APIError, Invite } from "$lib/api/entities";
|
import type { APIError, Invite } from "$lib/api/entities";
|
||||||
import { apiFetchClient } from "$lib/api/fetch";
|
import { apiFetchClient } from "$lib/api/fetch";
|
||||||
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
|
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
|
||||||
import { Alert, Button, Modal, Table } from "sveltestrap";
|
import { DateTime } from "luxon";
|
||||||
|
import { Button, Modal, Table } from "sveltestrap";
|
||||||
import type { PageData } from "./$types";
|
import type { PageData } from "./$types";
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
@ -43,7 +44,11 @@
|
||||||
{#each data.invites as invite}
|
{#each data.invites as invite}
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>{invite.code}</code></td>
|
<td><code>{invite.code}</code></td>
|
||||||
<td>{invite.created}</td>
|
<td
|
||||||
|
>{DateTime.fromISO(invite.created)
|
||||||
|
.toLocal()
|
||||||
|
.toLocaleString(DateTime.DATETIME_MED)}</td
|
||||||
|
>
|
||||||
<td>{invite.used ? "yes" : "no"}</td>
|
<td>{invite.used ? "yes" : "no"}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
|
@ -1,3 +1,36 @@
|
||||||
<h1>API tokens</h1>
|
<script lang="ts">
|
||||||
|
import { DateTime } from "luxon";
|
||||||
|
import { Icon, Table } from "sveltestrap";
|
||||||
|
import type { PageData } from "./$types";
|
||||||
|
|
||||||
<p>This page is a work in progress, sorry!</p>
|
export let data: PageData;
|
||||||
|
|
||||||
|
import * as jose from "jose";
|
||||||
|
const claims = jose.decodeJwt(localStorage.getItem("pronouns-token")!);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1>Tokens ({data.tokens.length})</h1>
|
||||||
|
|
||||||
|
<Table bordered striped hover>
|
||||||
|
<thead>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Created at</th>
|
||||||
|
<th>Expires at</th>
|
||||||
|
<th>Current?</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each data.tokens as token}
|
||||||
|
<tr>
|
||||||
|
<td><code>{token.id}</code></td>
|
||||||
|
<td>{DateTime.fromISO(token.created).toLocal().toLocaleString(DateTime.DATETIME_MED)}</td>
|
||||||
|
<td>{DateTime.fromISO(token.expires).toLocal().toLocaleString(DateTime.DATETIME_MED)}</td>
|
||||||
|
<td
|
||||||
|
>{#if claims["jti"] === token.id}<Icon name="check-lg" alt="Current token" />{:else}<Icon
|
||||||
|
name="x-lg"
|
||||||
|
alt="Not current token"
|
||||||
|
/>{/if}</td
|
||||||
|
>
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</Table>
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { apiFetchClient } from "$lib/api/fetch";
|
||||||
|
|
||||||
|
export const load = async () => {
|
||||||
|
const tokens = await apiFetchClient<Token[]>("/auth/tokens");
|
||||||
|
return { tokens };
|
||||||
|
};
|
||||||
|
|
||||||
|
interface Token {
|
||||||
|
id: string;
|
||||||
|
created: string;
|
||||||
|
expires: string;
|
||||||
|
}
|
Loading…
Reference in New Issue