import { randomUUID } from "node:crypto"; import { jwt } from "@elysiajs/jwt"; import { Elysia, t } from "elysia"; import prisma from "../db/db"; import { ACCOUNT_REGISTRATION, ALLOW_UNAUTHENTICATED, HIDE_HISTORY, HTTP_ALLOWED, WEBROOT, } from "../helpers/env"; import { BaseHtml } from "../components/base"; import { Header } from "../components/header"; export let FIRST_RUN = (await prisma.user.findFirst()) === null || false; export const userService = new Elysia({ name: "user/service" }) .use( jwt({ name: "jwt", schema: t.Object({ id: t.String(), }), secret: process.env.JWT_SECRET ?? randomUUID(), exp: "7d", }), ) .model({ signIn: t.Object({ email: t.String(), password: t.String(), }), session: t.Cookie({ auth: t.String(), jobId: t.Optional(t.String()), }), optionalSession: t.Cookie({ auth: t.Optional(t.String()), jobId: t.Optional(t.String()), }), }) .macro("auth", { cookie: "session", async resolve({ status, jwt, cookie: { auth } }) { if (!auth.value) { return status(401, { success: false, message: "Unauthorized", }); } const user = await jwt.verify(auth.value); if (!user) { return status(401, { success: false, message: "Unauthorized", }); } return { success: true, user, }; }, }); export const user = new Elysia() .use(userService) .get("/setup", ({ redirect }) => { if (!FIRST_RUN) { return redirect(`${WEBROOT}/login`, 302); } return (

Welcome to ConvertX!

Create your account
); }) .get("/register", ({ redirect }) => { if (!ACCOUNT_REGISTRATION) { return redirect(`${WEBROOT}/login`, 302); } return ( <>
); }) .post( "/register", async ({ body: { email, password }, set, redirect, jwt, cookie: { auth } }) => { if (!ACCOUNT_REGISTRATION && !FIRST_RUN) { return redirect(`${WEBROOT}/login`, 302); } if (FIRST_RUN) { FIRST_RUN = false; } const existingUser = await prisma.user.findUnique({ where: { email } }); if (existingUser) { set.status = 400; return { message: "Email already in use.", }; } const savedPassword = await Bun.password.hash(password); const user = await prisma.user.create({ data: { email, password: savedPassword, }, }); if (!user) { set.status = 500; return { message: "Failed to create user.", }; } const accessToken = await jwt.sign({ id: String(user.id), }); if (!auth) { set.status = 500; return { message: "No auth cookie, perhaps your browser is blocking cookies.", }; } // set cookie auth.set({ value: accessToken, httpOnly: true, secure: !HTTP_ALLOWED, maxAge: 60 * 60 * 24 * 7, sameSite: "strict", }); return redirect(`${WEBROOT}/`, 302); }, { body: "signIn" }, ) .get( "/login", async ({ jwt, redirect, cookie: { auth } }) => { if (FIRST_RUN) { return redirect(`${WEBROOT}/setup`, 302); } // if already logged in, redirect to home if (auth?.value) { const user = await jwt.verify(auth.value); if (user) { return redirect(`${WEBROOT}/`, 302); } auth.remove(); } return ( <>
{ACCOUNT_REGISTRATION ? ( Register ) : null}
); }, { body: "signIn", cookie: "optionalSession" }, ) .post( "/login", async function handler({ body, set, redirect, jwt, cookie: { auth } }) { const existingUser = await prisma.user.findUnique({ where: { email: body.email } }); if (!existingUser) { set.status = 403; return { message: "Invalid credentials.", }; } const validPassword = await Bun.password.verify(body.password, existingUser.password); if (!validPassword) { set.status = 403; return { message: "Invalid credentials.", }; } const accessToken = await jwt.sign({ id: String(existingUser.id), }); if (!auth) { set.status = 500; return { message: "No auth cookie, perhaps your browser is blocking cookies.", }; } // set cookie auth.set({ value: accessToken, httpOnly: true, secure: !HTTP_ALLOWED, maxAge: 60 * 60 * 24 * 7, sameSite: "strict", }); return redirect(`${WEBROOT}/`, 302); }, { body: "signIn" }, ) .get("/logoff", ({ redirect, cookie: { auth } }) => { if (auth?.value) { auth.remove(); } return redirect(`${WEBROOT}/login`, 302); }) .post("/logoff", ({ redirect, cookie: { auth } }) => { if (auth?.value) { auth.remove(); } return redirect(`${WEBROOT}/login`, 302); }) .get( "/account", async ({ user, redirect }) => { if (!user) { return redirect(`${WEBROOT}/`, 302); } const userId = Number(user.id); const userData = await prisma.user.findUnique({ where: { id: userId } }); if (!userData) { return redirect(`${WEBROOT}/`, 302); } return ( <>
); }, { auth: true, }, ) .post( "/account", async function handler({ body, set, redirect, jwt, cookie: { auth } }) { if (!auth?.value) { return redirect(`${WEBROOT}/login`, 302); } const user = await jwt.verify(auth.value); if (!user) { return redirect(`${WEBROOT}/login`, 302); } const userId = Number(user.id); const existingUser = await prisma.user.findUnique({ where: { id: userId } }); if (!existingUser) { if (auth?.value) { auth.remove(); } return redirect(`${WEBROOT}/login`, 302); } const validPassword = await Bun.password.verify(body.password, existingUser.password); if (!validPassword) { set.status = 403; return { message: "Invalid credentials.", }; } const updates: { email?: string; password?: string } = {}; if (body.email) { const emailInUse = await prisma.user.findUnique({ where: { email: body.email } }); if (emailInUse && emailInUse.id !== userId) { set.status = 409; return { message: "Email already in use." }; } updates.email = body.email; } if (body.newPassword) { updates.password = await Bun.password.hash(body.newPassword); } if (Object.keys(updates).length > 0) { await prisma.user.update({ where: { id: userId }, data: updates }); } return redirect(`${WEBROOT}/`, 302); }, { body: t.Object({ email: t.MaybeEmpty(t.String()), newPassword: t.MaybeEmpty(t.String()), password: t.String(), }), cookie: "session", }, );