diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/auth.tsx | 26 | ||||
-rw-r--r-- | src/db/schema.ts | 3 | ||||
-rw-r--r-- | src/index.tsx | 19 |
3 files changed, 33 insertions, 15 deletions
diff --git a/src/auth.tsx b/src/auth.tsx index ebda74e..eef8b8f 100644 --- a/src/auth.tsx +++ b/src/auth.tsx @@ -1,19 +1,35 @@ import { Hono } from "hono"; import * as swa from "@simplewebauthn/server"; import { randomUUID } from "node:crypto"; -import { eq } from "drizzle-orm"; +import { and, eq, gt, sql } from "drizzle-orm"; import { RP_ID, ORIGIN, db } from "./index.js"; import { sessionTable, userTable, webauthnChallenges } from "./db/schema.js"; import { stringify, parse } from "superjson"; -import { setCookie } from "hono/cookie"; - -let app = new Hono(); +import { getCookie, setCookie } from "hono/cookie"; +import type { Context } from "hono"; export const LoginForm = () => <section class="register-form"> <button hx-post="/auth/register-begin" hx-target="closest .register-form" hx-swap="outerHTML">register</button> <button hx-post="/auth/login-begin" hx-target="closest .register-form" hx-swap="outerHTML">login</button> </section>; +export async function getSession(c: Context) { + let sessionId = getCookie(c, "session"); + if (!sessionId) return null; + + let [result] = await db + .select() + .from(sessionTable) + .innerJoin(userTable, eq(userTable.id, sessionTable.userId)) + .where(({ sessions: session }) => and(eq(session.uuid, sessionId), gt(session.lastUse, sql`unixepoch() - ${60 * 60 * 24 * 7}`))); + if (!result) return null; + await db.update(sessionTable).set({ lastUse: sql`unixepoch()` }).where(eq(sessionTable.id, result.sessions.id)); + return { user: result.users, lastUse: result.sessions.lastUse, uuid: result.sessions.uuid }; +} + +let app = new Hono(); +export default app; + app.post("/register-begin", async c => { const username = randomUUID(); let options = await swa.generateRegistrationOptions({ @@ -89,5 +105,3 @@ app.post("/login-finish", async c => { setCookie(c, "session", uuid); return c.html(<p>Logged in!</p>); }); - -export default app; diff --git a/src/db/schema.ts b/src/db/schema.ts index 01b7228..339dfc0 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -1,4 +1,4 @@ -import { relations } from "drizzle-orm"; +import { relations, sql } from "drizzle-orm"; import { text, sqliteTable, integer } from "drizzle-orm/sqlite-core"; export const groupTable = sqliteTable("groups", { @@ -17,6 +17,7 @@ export const sessionTable = sqliteTable("sessions", { id: integer().primaryKey(), uuid: text().unique().notNull(), userId: integer("user_id").notNull(), + lastUse: integer("last_use", { mode: "timestamp" }).notNull().default(sql`(unixepoch())`), }); export const sessionRelations = relations(sessionTable, ({ one }) => ({ diff --git a/src/index.tsx b/src/index.tsx index e029577..5975284 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,7 +3,7 @@ import { Hono } from "hono"; import { createClient } from "@libsql/client"; import { drizzle } from "drizzle-orm/libsql"; import { groupTable } from "./db/schema.js"; -import authRouter, { LoginForm } from "./auth.js"; +import authRouter, { getSession, LoginForm } from "./auth.js"; export const RP_ID = "localhost"; // "uneven.0m.nu"; export const ORIGIN = `http://${RP_ID}`; @@ -38,13 +38,16 @@ app.get("/", c => c.html( )); let colors = ["red", "green", "blue"]; -app.get("/button", c => c.html( - <button - hx-get="/button" - hx-swap="outerHTML" - style={{ backgroundColor: colors[Math.floor(Math.random() * colors.length)] }} - >disco button!</button> -)); +app.get("/button", async c => { + let session = await getSession(c); + return c.html( + <button + hx-get="/button" + hx-swap="outerHTML" + style={{ backgroundColor: colors[Math.floor(Math.random() * colors.length)] }} + >disco button! {session.user.name}</button> + ); +}); app.route("/auth", authRouter); |