diff options
| author | Adam Soltys <[email protected]> | 2025-01-09 23:44:40 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2025-01-09 23:44:40 -0800 |
| commit | 8588de25f16486b56ef0ad533013bd8cb48ff120 (patch) | |
| tree | 4c1e39704e2edb332c5fe8c58fb0d81c8154af2b /src/routes/(static)/login | |
| parent | 2358d1bf39c34a508db6c50f0f6312ee411a8a17 (diff) | |
| download | coinos-ui-8588de25f16486b56ef0ad533013bd8cb48ff120.tar.gz coinos-ui-8588de25f16486b56ef0ad533013bd8cb48ff120.zip | |
nostr signing
Diffstat (limited to 'src/routes/(static)/login')
| -rw-r--r-- | src/routes/(static)/login/+page.server.ts | 8 | ||||
| -rw-r--r-- | src/routes/(static)/login/+page.svelte | 76 |
2 files changed, 61 insertions, 23 deletions
diff --git a/src/routes/(static)/login/+page.server.ts b/src/routes/(static)/login/+page.server.ts index 6bf06ad2..f86f62e9 100644 --- a/src/routes/(static)/login/+page.server.ts +++ b/src/routes/(static)/login/+page.server.ts @@ -5,8 +5,8 @@ import { fail, redirect } from "@sveltejs/kit"; export const load = async ({ parent }) => { const { user } = await parent(); if (user?.pubkey) redirect(307, `/${user.username}`); - const { id } = await get("/challenge"); - return { id }; + const { challenge } = await get("/challenge"); + return { challenge }; }; export const actions = { @@ -29,7 +29,7 @@ export const actions = { nostr: async ({ cookies, fetch, request }) => { const form = await fd(request); - let { id, event, loginRedirect } = form; + let { challenge, event, loginRedirect } = form; if (loginRedirect === "null") loginRedirect = undefined; event = JSON.parse(event); @@ -37,7 +37,7 @@ export const actions = { const res = await fetch(`${PUBLIC_COINOS_URL}/nostrLogin`, { method: "POST", - body: JSON.stringify({ id, event }), + body: JSON.stringify({ challenge, event }), headers: { "content-type": "application/json", accept: "application/json", diff --git a/src/routes/(static)/login/+page.svelte b/src/routes/(static)/login/+page.svelte index 7e8234ee..e4dcbf15 100644 --- a/src/routes/(static)/login/+page.svelte +++ b/src/routes/(static)/login/+page.svelte @@ -1,39 +1,42 @@ <script> import { browser } from "$app/environment"; import handler from "$lib/handler"; - - import { onMount } from "svelte"; import { applyAction, deserialize } from "$app/forms"; - import { tick } from "svelte"; + import { onMount, tick } from "svelte"; import { fly } from "svelte/transition"; import { enhance } from "$app/forms"; - import Nostr from "$comp/Nostr.svelte"; import Pinpad from "$comp/Pinpad.svelte"; import PasswordInput from "$comp/PasswordInput.svelte"; + import Spinner from "$comp/Spinner.svelte"; import { focus, fail } from "$lib/utils"; - import { password, pin, loginRedirect } from "$lib/store"; + import { password, signer, pin, loginRedirect } from "$lib/store"; import { t } from "$lib/translations"; import { page } from "$app/stores"; + import { sign } from "$lib/nostr"; import { invalidateAll } from "$app/navigation"; let { data, form } = $props(); - onMount(() => { - $pin = undefined; - localStorage.clear(); - sessionStorage.clear(); + page.subscribe(async () => { + if (browser) { + setTimeout(() => { + password.set(undefined); + pin?.set(undefined); + signer.set(undefined); + localStorage.clear(); + sessionStorage.clear(); + }, 500); + } + }); + onMount(() => { let lang = $page.url.searchParams.get("lang"); if (lang) document.cookie = `lang=${lang} ;`; }); - let { id } = $derived(data); - let nostrSignin = $state(); - + let { challenge } = $derived(data); let token = $state(""); - $password = undefined; - let cancel = () => (need2fa = false); let username = $state(), @@ -81,13 +84,43 @@ let redirect = $derived( $loginRedirect || $page.url.searchParams.get("redirect"), ); + + let nostrLogin = async () => { + let event = { + kind: 1, + created_at: Date.now(), + content: challenge, + tags: [], + }; + + let signedEvent = await sign(event); + + const formData = new FormData(); + + try { + formData.append("loginRedirect", redirect); + formData.append("token", token); + formData.append("event", JSON.stringify(signedEvent)); + formData.append("challenge", challenge); + + let response = await fetch("/login?/nostr", { + method: "POST", + body: formData, + }); + + const result = deserialize(await response.text()); + + applyAction(result); + } catch (e) { + fail(e.message); + } + }; </script> <div class="mx-auto md:shadow-xl rounded-3xl max-w-xl w-full md:w-[480px] md:p-8 mb-20" > <h1 class="text-2xl font-bold text-center">{$t("login.signIn")}</h1> - {#if form?.error && !form?.message.includes("2fa")} <div class="text-red-600 text-center" in:fly> {form.error} @@ -126,10 +159,17 @@ {$t("login.signIn")} </button> - <button type="button" class="btn" onclick={() => (nostrSignin = true)}> - <img src="/images/nostr.png" class="w-8" /> + <button type="button" class="btn" onclick={nostrLogin}> + {#if $signer?.ready} + <div class="shrink"> + <Spinner /> + </div> + {:else} + <img src="/images/nostr.png" class="w-8" /> + {/if} <div class="my-auto">{$t("login.nostr")}</div> </button> + <p class="text-secondary text-center font-medium"> {$t("login.noAccount")} <a @@ -163,5 +203,3 @@ </div> </div> {/if} - -<Nostr {id} bind:nostrSignin {redirect} {token} /> |
