Files
pocket-id/frontend/src/routes/settings/admin/users/one-time-link-modal.svelte

90 lines
2.5 KiB
Svelte
Raw Normal View History

2024-08-12 11:00:25 +02:00
<script lang="ts">
import { page } from '$app/stores';
import { Button } from '$lib/components/ui/button';
2024-08-12 11:00:25 +02:00
import * as Dialog from '$lib/components/ui/dialog';
import Input from '$lib/components/ui/input/input.svelte';
import Label from '$lib/components/ui/label/label.svelte';
import * as Select from '$lib/components/ui/select/index.js';
import UserService from '$lib/services/user-service';
import { axiosErrorToast } from '$lib/utils/error-util';
2024-08-12 11:00:25 +02:00
let {
userId = $bindable()
2024-08-12 11:00:25 +02:00
}: {
userId: string | null;
2024-08-12 11:00:25 +02:00
} = $props();
const userService = new UserService();
let oneTimeLink: string | null = $state(null);
let selectedExpiration: keyof typeof availableExpirations = $state('1 hour');
let availableExpirations = {
'1 hour': 60 * 60,
'12 hours': 60 * 60 * 12,
'1 day': 60 * 60 * 24,
'1 week': 60 * 60 * 24 * 7,
'1 month': 60 * 60 * 24 * 30
};
async function createOneTimeAccessToken() {
try {
const expiration = new Date(Date.now() + availableExpirations[selectedExpiration] * 1000);
const token = await userService.createOneTimeAccessToken(userId!, expiration);
oneTimeLink = `${$page.url.origin}/login/${token}`;
} catch (e) {
axiosErrorToast(e);
}
}
2024-08-12 11:00:25 +02:00
function onOpenChange(open: boolean) {
if (!open) {
oneTimeLink = null;
userId = null;
2024-08-12 11:00:25 +02:00
}
}
</script>
<Dialog.Root open={!!userId} {onOpenChange}>
2024-08-12 11:00:25 +02:00
<Dialog.Content class="max-w-md">
<Dialog.Header>
<Dialog.Title>One Time Link</Dialog.Title>
<Dialog.Description
>Use this link to sign in once. This is needed for users who haven't added a passkey yet or
have lost it.</Dialog.Description
>
</Dialog.Header>
{#if oneTimeLink === null}
<div>
<Label for="expiration">Expiration</Label>
<Select.Root
selected={{
label: Object.keys(availableExpirations)[0],
value: Object.keys(availableExpirations)[0]
}}
onSelectedChange={(v) =>
(selectedExpiration = v!.value as keyof typeof availableExpirations)}
>
<Select.Trigger class="h-9 ">
<Select.Value>{selectedExpiration}</Select.Value>
</Select.Trigger>
<Select.Content>
{#each Object.keys(availableExpirations) as key}
<Select.Item value={key}>{key}</Select.Item>
{/each}
</Select.Content>
</Select.Root>
</div>
<Button
onclick={() => createOneTimeAccessToken()}
disabled={!selectedExpiration}
>
Generate Link
</Button>
{:else}
<Label for="one-time-link" class="sr-only">One Time Link</Label>
2024-08-12 11:00:25 +02:00
<Input id="one-time-link" value={oneTimeLink} readonly />
{/if}
2024-08-12 11:00:25 +02:00
</Dialog.Content>
</Dialog.Root>