login.tsx (1880B)
1 import PasswordInput from "#http/islands/password_input.tsx"; 2 import { AppState } from "#http/routes/_middleware.ts"; 3 import { Handlers, PageProps } from "$fresh/src/server/types.ts"; 4 import * as V from "$valita"; 5 6 type Props = { 7 invalid: boolean; 8 delay: number; 9 }; 10 11 export const handler: Handlers<Props, AppState<"/login">> = { 12 GET(_req, ctx) { 13 const { forms, formContext } = ctx.state; 14 if (formContext === null) { 15 return forms.redirect({ 16 form: "/connect", 17 context: { back: "/" }, 18 }); 19 } 20 const { back } = formContext; 21 if (forms.session !== null) { 22 return forms.redirect(back); 23 } 24 return ctx.render({ invalid: false, delay: 0 }); 25 }, 26 27 async POST(req, ctx) { 28 const { app, forms, formContext } = ctx.state; 29 const { authLogin } = app; 30 if (formContext === null) { 31 return forms.redirect({ 32 form: "/connect", 33 context: { back: "/" }, 34 }); 35 } 36 const { uuid, back } = formContext; 37 if (forms.session !== null) { 38 return forms.redirect(back) 39 } 40 41 const { password } = await forms.inputs( 42 req, 43 V.object({ 44 password: V.string(), 45 }), 46 ); 47 const result = await authLogin.execute({ uuid, password }); 48 if (result.status === "loggedIn") { 49 return forms.redirectWithSession( 50 back, 51 result.sessionToken!, 52 ); 53 } 54 return ctx.render({ 55 invalid: result.status === "invalid", 56 delay: result.delay, 57 }); 58 }, 59 }; 60 61 export default function LoginPages({ data }: PageProps<Props>) { 62 return ( 63 <article> 64 <header style="text-align: center;"> 65 <b>Login</b> 66 </header> 67 <form method="POST"> 68 <PasswordInput error={data.invalid} confirm={false} /> 69 <div role="group"> 70 <button type="submit">Login</button> 71 </div> 72 </form> 73 </article> 74 ); 75 }