feat(14-04): convert auth, OAuth, settings routes and auth middleware to async/await

- Add await before all service calls in auth, OAuth routes
- Convert settings.ts direct DB calls: remove .get()/.run(), use await + destructuring
- Auth middleware: await getUserCount, getSession, refreshSession
- Fix formatting in threads.ts for biome compliance
- All files pass lint
This commit is contained in:
2026-04-04 12:43:29 +02:00
parent 5edcc660e4
commit 22aaed76f2
5 changed files with 45 additions and 45 deletions

View File

@@ -11,7 +11,7 @@ export async function requireAuth(c: Context, next: Next) {
const db = c.get("db");
// Check if any users exist at all
if (getUserCount(db) === 0) {
if ((await getUserCount(db)) === 0) {
return c.json({ error: "setup_required" }, 403);
}
@@ -26,10 +26,10 @@ export async function requireAuth(c: Context, next: Next) {
// Check session cookie
const sessionId = getCookie(c, "gearbox_session");
if (sessionId) {
const session = getSession(db, sessionId);
const session = await getSession(db, sessionId);
if (session) {
// Refresh session expiry on use
refreshSession(db, sessionId);
await refreshSession(db, sessionId);
return next();
}
}

View File

@@ -43,12 +43,12 @@ const app = new Hono<Env>();
// ── Public routes ───────────────────────────────────────────────────
app.get("/me", (c) => {
app.get("/me", async (c) => {
const db = c.get("db");
const sessionId = getCookie(c, COOKIE_NAME);
if (sessionId) {
const session = getSession(db, sessionId);
const session = await getSession(db, sessionId);
if (session) {
return c.json({
user: { id: session.userId },
@@ -57,20 +57,20 @@ app.get("/me", (c) => {
}
}
const setupRequired = getUserCount(db) === 0;
const setupRequired = (await getUserCount(db)) === 0;
return c.json({ user: null, setupRequired });
});
app.post("/setup", rateLimit, zValidator("json", setupSchema), async (c) => {
const db = c.get("db");
if (getUserCount(db) > 0) {
if ((await getUserCount(db)) > 0) {
return c.json({ error: "Setup already completed" }, 403);
}
const { username, password } = c.req.valid("json");
const user = await createUser(db, username, password);
const session = createSession(db, user.id);
const session = await createSession(db, user.id);
setCookie(c, COOKIE_NAME, session.id, {
httpOnly: true,
@@ -91,7 +91,7 @@ app.post("/login", rateLimit, zValidator("json", loginSchema), async (c) => {
return c.json({ error: "Invalid credentials" }, 401);
}
const session = createSession(db, user.id);
const session = await createSession(db, user.id);
setCookie(c, COOKIE_NAME, session.id, {
httpOnly: true,
@@ -103,12 +103,12 @@ app.post("/login", rateLimit, zValidator("json", loginSchema), async (c) => {
return c.json({ username: user.username });
});
app.post("/logout", (c) => {
app.post("/logout", async (c) => {
const db = c.get("db");
const sessionId = getCookie(c, COOKIE_NAME);
if (sessionId) {
deleteSession(db, sessionId);
await deleteSession(db, sessionId);
}
deleteCookie(c, COOKIE_NAME, { path: "/" });
@@ -127,17 +127,16 @@ app.put(
if (!sessionId) {
return c.json({ error: "Session required for password change" }, 401);
}
const session = getSession(db, sessionId);
const session = await getSession(db, sessionId);
if (!session) {
return c.json({ error: "Session required for password change" }, 401);
}
const userRecord = db
const [userRecord] = await db
.select()
.from(users)
.where(eq(users.id, session.userId))
.get();
.where(eq(users.id, session.userId));
if (!userRecord) {
return c.json({ error: "User not found" }, 404);
@@ -159,9 +158,9 @@ app.put(
},
);
app.get("/keys", requireAuth, (c) => {
app.get("/keys", requireAuth, async (c) => {
const db = c.get("db");
const keys = listApiKeys(db);
const keys = await listApiKeys(db);
return c.json(keys);
});
@@ -186,11 +185,11 @@ app.post(
},
);
app.delete("/keys/:id", requireAuth, (c) => {
app.delete("/keys/:id", requireAuth, async (c) => {
const db = c.get("db");
const id = parseId(c.req.param("id"));
if (!id) return c.json({ error: "Invalid key ID" }, 400);
deleteApiKey(db, id);
await deleteApiKey(db, id);
return c.json({ ok: true });
});

View File

@@ -129,7 +129,7 @@ oauthRoutes.post("/register", async (c) => {
}
const clientName = body.client_name || "Unknown Client";
const { clientId } = registerClient(db, clientName, body.redirect_uris);
const { clientId } = await registerClient(db, clientName, body.redirect_uris);
return c.json(
{
@@ -159,7 +159,7 @@ oauthRoutes.get("/authorize", async (c) => {
return c.json({ error: "Missing required parameters" }, 400);
}
const client = getClient(db, clientId);
const client = await getClient(db, clientId);
if (!client) {
return c.json({ error: "Unknown client_id" }, 400);
}
@@ -196,7 +196,7 @@ oauthRoutes.post("/authorize", async (c) => {
const user = await verifyPassword(db, username, password);
if (!user) {
const client = getClient(db, clientId);
const client = await getClient(db, clientId);
return c.html(
renderLoginForm({
clientName: client?.clientName ?? "Unknown",
@@ -210,7 +210,7 @@ oauthRoutes.post("/authorize", async (c) => {
);
}
const { code } = createAuthorizationCode(
const { code } = await createAuthorizationCode(
db,
clientId,
codeChallenge,
@@ -233,7 +233,7 @@ oauthRoutes.post("/token", async (c) => {
const grantType = body.grant_type as string;
// Opportunistic cleanup
cleanExpiredOAuthData(db);
await cleanExpiredOAuthData(db);
if (grantType === "authorization_code") {
const code = body.code as string;

View File

@@ -6,14 +6,13 @@ type Env = { Variables: { db?: any } };
const app = new Hono<Env>();
app.get("/:key", (c) => {
app.get("/:key", async (c) => {
const database = c.get("db");
const key = c.req.param("key");
const row = database
const [row] = await database
.select()
.from(settings)
.where(eq(settings.key, key))
.get();
.where(eq(settings.key, key));
if (!row) return c.json({ error: "Setting not found" }, 404);
return c.json(row);
});
@@ -27,17 +26,15 @@ app.put("/:key", async (c) => {
return c.json({ error: "value is required" }, 400);
}
database
await database
.insert(settings)
.values({ key, value: body.value })
.onConflictDoUpdate({ target: settings.key, set: { value: body.value } })
.run();
.onConflictDoUpdate({ target: settings.key, set: { value: body.value } });
const row = database
const [row] = await database
.select()
.from(settings)
.where(eq(settings.key, key))
.get();
.where(eq(settings.key, key));
return c.json(row);
});

View File

@@ -84,19 +84,23 @@ app.delete("/:id", async (c) => {
// Candidate CRUD (nested under thread)
app.post("/:id/candidates", zValidator("json", createCandidateSchema), async (c) => {
const db = c.get("db");
const threadId = parseId(c.req.param("id"));
if (!threadId) return c.json({ error: "Invalid thread ID" }, 400);
app.post(
"/:id/candidates",
zValidator("json", createCandidateSchema),
async (c) => {
const db = c.get("db");
const threadId = parseId(c.req.param("id"));
if (!threadId) return c.json({ error: "Invalid thread ID" }, 400);
// Verify thread exists
const thread = await getThreadWithCandidates(db, threadId);
if (!thread) return c.json({ error: "Thread not found" }, 404);
// Verify thread exists
const thread = await getThreadWithCandidates(db, threadId);
if (!thread) return c.json({ error: "Thread not found" }, 404);
const data = c.req.valid("json");
const candidate = await createCandidate(db, threadId, data);
return c.json(candidate, 201);
});
const data = c.req.valid("json");
const candidate = await createCandidate(db, threadId, data);
return c.json(candidate, 201);
},
);
app.put(
"/:threadId/candidates/:candidateId",