From ac18fcc92a2bb98e5987734f2df740fd359dd00a Mon Sep 17 00:00:00 2001 From: Kosztyk <36381705+Kosztyk@users.noreply.github.com> Date: Mon, 12 Jan 2026 23:38:50 +0200 Subject: [PATCH] Add files via upload --- src/pages/user.tsx | 157 ++++++++++++++++++++------------------------- 1 file changed, 69 insertions(+), 88 deletions(-) diff --git a/src/pages/user.tsx b/src/pages/user.tsx index c351df7..abcff49 100644 --- a/src/pages/user.tsx +++ b/src/pages/user.tsx @@ -13,20 +13,9 @@ import { WEBROOT, } from "../helpers/env"; -function computeFirstRun(): boolean { - // DB-driven, so it stays correct across reloads and per-request updates. - return db.query("SELECT 1 FROM users LIMIT 1").get() === null; -} - -// Kept as an exported boolean for backwards-compatibility (e.g. root.tsx imports FIRST_RUN), -// but it is refreshed per-request via userService. Do not rely on it being constant. -export let FIRST_RUN = computeFirstRun(); +export let FIRST_RUN = db.query("SELECT * FROM users").get() === null || false; export const userService = new Elysia({ name: "user/service" }) - .derive(() => { - FIRST_RUN = computeFirstRun(); - return {}; - }) .use( jwt({ name: "jwt", @@ -78,8 +67,7 @@ export const userService = new Elysia({ name: "user/service" }) export const user = new Elysia() .use(userService) .get("/setup", ({ redirect }) => { - const isFirstRun = computeFirstRun(); - if (!isFirstRun) { + if (!FIRST_RUN) { return redirect(`${WEBROOT}/login`, 302); } @@ -196,88 +184,72 @@ export const user = new Elysia() .post( "/register", async ({ body: { email, password }, set, redirect, jwt, cookie: { auth } }) => { - // DB-driven "first user" detection (no stale in-memory flag) + race-safe creation. - // We hash outside the write-lock to keep the lock window short. + // first user allowed even if ACCOUNT_REGISTRATION=false + const isFirstUser = FIRST_RUN; + + if (!ACCOUNT_REGISTRATION && !isFirstUser) { + return redirect(`${WEBROOT}/login`, 302); + } + + if (FIRST_RUN) { + FIRST_RUN = false; + } + + const existingUser = await db.query("SELECT * FROM users WHERE email = ?").get(email); + if (existingUser) { + set.status = 400; + return { + message: "Email already in use.", + }; + } const savedPassword = await Bun.password.hash(password); - // Acquire a write lock so only one instance can perform "count==0 then insert" at a time. - db.exec("BEGIN IMMEDIATE"); - try { - const isFirstUser = computeFirstRun(); + const role = isFirstUser ? "admin" : "user"; - // first user allowed even if ACCOUNT_REGISTRATION=false - if (!ACCOUNT_REGISTRATION && !isFirstUser) { - db.exec("ROLLBACK"); - return redirect(`${WEBROOT}/login`, 302); - } + db.query("INSERT INTO users (email, password, role) VALUES (?, ?, ?)").run( + email, + savedPassword, + role, + ); - const existingUser = db.query("SELECT 1 FROM users WHERE email = ?").get(email); - if (existingUser) { - db.exec("ROLLBACK"); - set.status = 400; - return { - message: "Email already in use.", - }; - } + const userRow = db.query("SELECT * FROM users WHERE email = ?").as(User).get(email); - const role = isFirstUser ? "admin" : "user"; - - db.query("INSERT INTO users (email, password, role) VALUES (?, ?, ?)").run( - email, - savedPassword, - role, - ); - - const userRow = db.query("SELECT * FROM users WHERE email = ?").as(User).get(email); - - if (!userRow) { - db.exec("ROLLBACK"); - set.status = 500; - return { - message: "Failed to create user.", - }; - } - - db.exec("COMMIT"); - FIRST_RUN = false; - - const accessToken = await jwt.sign({ - id: String(userRow.id), - role: userRow.role ?? "user", - }); - - 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); - } catch (e) { - try { - db.exec("ROLLBACK"); - } catch { - // ignore rollback errors - } - throw e; + if (!userRow) { + set.status = 500; + return { + message: "Failed to create user.", + }; } + + const accessToken = await jwt.sign({ + id: String(userRow.id), + role: userRow.role, + }); + + 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 (computeFirstRun()) { + if (FIRST_RUN) { return redirect(`${WEBROOT}/setup`, 302); } @@ -845,7 +817,9 @@ export const user = new Elysia()