import { HandlerContext, Handlers, PageProps } from "$fresh/server.ts"; import { compare } from "https://deno.land/x/bcrypt@v0.4.1/mod.ts"; import { Page } from "@/components/Page.tsx"; import { query } from "@/db/mod.ts"; type UserID = string; interface LoginError { message: string; } async function invalidLogin(context: HandlerContext) { return await context.render({ message: "Invalid login" } as LoginError); } export const handler: Handlers = { async POST(request: Request, context) { const formData = (await request.formData()); const username = formData.get("username"); const password = formData.get("password"); if (!username) { return await context.render({ message: "no username provided" }); } if (!password) { return await context.render({ message: "no password provided" }); } const result = await query< { id: string; username: string; password_digest: string } >( `select * from "user" where username = $1`, [username], ); if (result == null || result.rows.length < 1) { return await invalidLogin(context); } const { rows: [{ id, password_digest }] } = result; if (await compare(password.toString(), password_digest)) { return await context.render(id); } else { return await invalidLogin(context); } }, }; export default function Login({ data }: PageProps) { if (typeof data == "string") { return LoginSuccessful(data); } else { return LoginForm(data); } } function LoginSuccessful(_userId: UserID) { return (

You are now logged in. Let's go to your{" "} dashboard!

); } function LoginForm(props?: LoginError | null) { return ( {props != null && (

Error: {props.message}

)}

Log in to your account

); }