103 lines
2.6 KiB
Svelte
103 lines
2.6 KiB
Svelte
<script lang="ts">
|
|
import { Alert, Button, Input, Label, Spinner } from "flowbite-svelte";
|
|
import InternalAPI from "../../../../helper/api";
|
|
|
|
import type { TFANewTOTP } from "@hibas123/openauth-internalapi";
|
|
import { createEventDispatcher } from "svelte";
|
|
|
|
const dispatch = createEventDispatcher();
|
|
|
|
let stage = "get-name";
|
|
let name: string = "";
|
|
let code: string = "";
|
|
let totp: TFANewTOTP;
|
|
|
|
let creatingTOTP = false;
|
|
let verifingTOTP = false;
|
|
|
|
async function createTOTP() {
|
|
creatingTOTP = true;
|
|
try {
|
|
totp = await InternalAPI.TwoFactor.AddTOTP(name);
|
|
stage = "verify";
|
|
} catch (err) {
|
|
} finally {
|
|
creatingTOTP = false;
|
|
}
|
|
}
|
|
|
|
let verifyError = undefined;
|
|
async function verifyTOTP() {
|
|
verifingTOTP = true;
|
|
verifyError = undefined;
|
|
try {
|
|
await InternalAPI.TwoFactor.VerifyTOTP(totp.id, code.replace(/\s/g, ""));
|
|
stage = "done";
|
|
dispatch("reload");
|
|
} catch (err) {
|
|
verifyError = err.message;
|
|
code = "";
|
|
} finally {
|
|
verifingTOTP = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
{#if stage == "get-name"}
|
|
<h3 class="text-xl font-medium text-gray-900 dark:text-white p-0">
|
|
Select a name
|
|
</h3>
|
|
<div class="mb-6">
|
|
<Label for="name-input" class="block mb-2">Name</Label>
|
|
<Input id="name-input" placeholder="Name" bind:value={name} />
|
|
</div>
|
|
|
|
<Button disabled={creatingTOTP} on:click={createTOTP}>
|
|
{#if creatingTOTP}
|
|
<Spinner class="mr-3" size="4" color="white" /> Creating...
|
|
{:else}
|
|
Create
|
|
{/if}
|
|
</Button>
|
|
{:else if stage == "verify"}
|
|
<h3 class="text-xl font-medium text-gray-900 dark:text-white p-0">
|
|
Save secret and verify
|
|
</h3>
|
|
<div class="flex flex-col justify-center items-center">
|
|
<img class="w-64" src={totp.qr} alt="Secret {totp.secret}" />
|
|
<div>Manually:</div>
|
|
<div class="text-sm">
|
|
{totp.secret}
|
|
</div>
|
|
</div>
|
|
<div class="mb-6">
|
|
<Label for="code-input" class="block mb-2">Code</Label>
|
|
<Input id="code-input" placeholder="Code" bind:value={code} />
|
|
</div>
|
|
|
|
{#if verifyError}
|
|
<Alert color="red">
|
|
<h2 class="text-lg font-bold">Error</h2>
|
|
<p class="mt-2">{verifyError}</p>
|
|
</Alert>
|
|
{/if}
|
|
|
|
<Button disabled={verifingTOTP} on:click={verifyTOTP}>
|
|
{#if verifingTOTP}
|
|
<Spinner class="mr-3" size="4" color="white" /> Verify...
|
|
{:else}
|
|
Verify
|
|
{/if}
|
|
</Button>
|
|
{:else if stage == "done"}
|
|
<Alert color="green">
|
|
<h2 class="text-lg font-bold">Success</h2>
|
|
<p class="mt-2">Your TOTP has been created.</p>
|
|
</Alert>
|
|
{:else}
|
|
<Alert color="red">
|
|
<h2 class="text-lg font-bold">Error</h2>
|
|
<p class="mt-2">An unknown error occured.</p>
|
|
</Alert>
|
|
{/if}
|