A focused Docker Compose management web application.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: better magic link

Brooke 7d130a9f 1aa01269

+71 -39
+3 -4
packages/panel/src/routes/(authenticated)/admin/UserList.svelte
··· 1 1 <script lang="ts"> 2 2 import { faBan, faKey, faPlus, faSignature, faUserCircle, faWrench } from "@fortawesome/free-solid-svg-icons"; 3 + import LoaderButton from "$lib/component/LoaderButton.svelte"; 4 + import CopyBox from "$lib/component/CopyBox.svelte"; 3 5 import { api, isMobile, openDialog } from "$lib"; 4 6 import Fa from "svelte-fa"; 5 - import LoaderButton from "$lib/component/LoaderButton.svelte"; 6 - import CopyBox from "$lib/component/CopyBox.svelte"; 7 - import { page } from "$app/state"; 8 7 9 8 type LuminaryUser = api.components["schemas"]["luminary_node.api.auth.LuminaryUser"]; 10 9 ··· 22 21 body: { username }, 23 22 }); 24 23 25 - let url = new URL(`reset?token=${response.data!}`, window.location.toString()).toString(); 24 + let url = new URL(`invite?token=${response.data!}`, window.location.toString()).toString(); 26 25 27 26 refresh(); 28 27 openDialog({
+30
packages/panel/src/routes/(magic_link)/+layout.ts
··· 1 + import type { LayoutLoad } from "./$types"; 2 + import { api } from "$lib"; 3 + import { redirect } from "@sveltejs/kit"; 4 + 5 + const TOKEN_KEY = "magic_link_token"; 6 + 7 + export const load: LayoutLoad = async ({ url }) => { 8 + const param = url.searchParams.get("token"); 9 + if (param) { 10 + sessionStorage.setItem(TOKEN_KEY, param); 11 + return redirect(302, url.pathname); 12 + } 13 + 14 + const token = sessionStorage.getItem(TOKEN_KEY); 15 + if (!token) return {}; 16 + 17 + try { 18 + const response = await api.client.GET("/api/auth/reset/{token}", { params: { path: { token } } }); 19 + 20 + return { 21 + magic: { 22 + username: response.data!, 23 + token, 24 + }, 25 + }; 26 + } catch (err) { 27 + sessionStorage.removeItem(TOKEN_KEY); 28 + return {}; 29 + } 30 + };
+16
packages/panel/src/routes/(magic_link)/invite/+page.svelte
··· 1 + <script lang="ts"> 2 + import Logo from "$lib/component/Crane.svelte"; 3 + let { data } = $props(); 4 + </script> 5 + 6 + <div class="flexc center"> 7 + <h2 class="sub"> 8 + <Logo /> 9 + Luminary 10 + </h2> 11 + <h1>Create Account</h1> 12 + </div> 13 + <h3> 14 + Welcome to Luminary {data.magic!.username}! 🎉 15 + </h3> 16 + <p>To get started, please set a password for your account.</p>
+15
packages/panel/src/routes/(magic_link)/reset/+page.svelte
··· 1 + <script lang="ts"> 2 + import Logo from "$lib/component/Crane.svelte"; 3 + let { data } = $props(); 4 + </script> 5 + 6 + <div class="flexc center"> 7 + <h2 class="sub"> 8 + <Logo /> 9 + Luminary 10 + </h2> 11 + <h1>Reset Password</h1> 12 + </div> 13 + <p> 14 + Hi {data.magic!.username}! Please enter a new password to access your account. 15 + </p>
-3
packages/panel/src/routes/Dialog.svelte
··· 95 95 display: flex; 96 96 flex-direction: column; 97 97 98 - min-width: 75vw; 99 - min-height: 25vh; 100 - 101 98 padding: 10px; 102 99 103 100 transition: opacity ease 300ms;
+7 -15
packages/panel/src/routes/reset/+page.svelte packages/panel/src/routes/(magic_link)/+layout.svelte
··· 1 1 <script lang="ts"> 2 2 import LoaderButton from "$lib/component/LoaderButton.svelte"; 3 - import Logo from "$lib/component/Crane.svelte"; 4 3 import { goto } from "$app/navigation"; 5 4 import { api } from "$lib"; 6 5 7 - let { data } = $props(); 6 + let { data, children } = $props(); 8 7 9 8 let loading = $state(false); 10 9 let password = $state(""); 11 10 12 11 async function set_password(e: SubmitEvent) { 12 + if (!data.magic) return; 13 + 13 14 e.preventDefault(); 14 15 loading = true; 15 16 try { 16 17 await api.client.POST("/api/auth/reset/{token}", { 17 - params: { path: { token: data.token } }, 18 + params: { path: { token: data.magic.token } }, 18 19 body: { password }, 19 20 }); 20 21 21 - console.log({ username: data.username, password }); 22 + console.log({ username: data.magic.username, password }); 22 23 23 - await api.login({ username: data.username, password }); 24 + await api.login({ username: data.magic.username, password }); 24 25 await goto("/"); 25 26 } finally { 26 27 loading = false; ··· 30 31 31 32 <main class="full flex center"> 32 33 <div class="island flexc center gap-20"> 33 - <div class="flexc center"> 34 - <h2 class="sub"> 35 - <Logo /> 36 - Luminary 37 - </h2> 38 - <h1>Reset Password</h1> 39 - </div> 40 - <p> 41 - Hi {data.username}! Please enter a new password to access your account. 42 - </p> 34 + {@render children()} 43 35 <form class="flexc gap-20" onsubmit={set_password}> 44 36 <div> 45 37 <label for="password">Password</label>
-17
packages/panel/src/routes/reset/+page.ts
··· 1 - import { error } from "@sveltejs/kit"; 2 - import type { PageLoad } from "./$types"; 3 - import { api } from "$lib"; 4 - 5 - export const load: PageLoad = async ({ url }) => { 6 - const token = url.searchParams.get("token"); 7 - if (!token) error(400, "Token is required"); 8 - 9 - const response = await api.client 10 - .GET("/api/auth/reset/{token}", { params: { path: { token } } }) 11 - .catch(() => error(401, "Invalid token")); 12 - 13 - return { 14 - username: response.data!, 15 - token, 16 - }; 17 - };