diff --git a/auth/auth.ts b/auth/auth.ts new file mode 100644 index 0000000..1de0208 --- /dev/null +++ b/auth/auth.ts @@ -0,0 +1,72 @@ +import { assert } from "$std/assert/assert.ts"; +import { User } from "../storage/store.ts"; +import { generate } from "https://deno.land/std@0.224.0/uuid/v1.ts"; + +class Authentificator { + tokens; + user_storage; + constructor(user_storage: UserStorage) { + this.tokens = new TokenSet(); + this.user_storage = user_storage; + } +} + +interface UserStorage { + get_user(login: string): User | null; +} + +export class Token { + raw; + user_id; + constructor(raw: string, user_id: string) { + this.raw = raw; + this.user_id = user_id; + } +} + +class TokenSet { + tokens; + + constructor() { + this.tokens = new Map(); + } + + get(token: string) { + return this.tokens.get(token) ?? null; + } + + create(user_id: string) { + const raw = generate(); + assert(typeof raw == "string"); + const token = new Token(raw, user_id); + this.tokens.set(raw, token); + } +} + +class StaticUserStorage implements UserStorage { + users; + + constructor() { + this.users = new Map(); + } + + get_user(user_id: string) { + return this.users.get(user_id) ?? null; + } + + with(user: User) { + this.users.set(user.id, user); + return this; + } +} + +export const auth = new Authentificator( + new StaticUserStorage().with({ + id: "pleinplein", + email: "feur@feur.feur", + like_set: new Set(), + name: "Feur", + password: "feurfeur", + pfp_url: "https://feur.feur.feur/feur.feur", + }), +); diff --git a/doc/models.md b/doc/models.md index cb6e2a5..2852530 100644 --- a/doc/models.md +++ b/doc/models.md @@ -19,9 +19,9 @@ - email - password - pfp_url + - like_set * posts * comments - * like_set - Post - title diff --git a/routes/feur.tsx b/routes/feur.tsx new file mode 100644 index 0000000..e69de29 diff --git a/routes/index.tsx b/routes/index.tsx index c5990aa..59d2ca2 100644 --- a/routes/index.tsx +++ b/routes/index.tsx @@ -2,16 +2,14 @@ import { useSignal } from "@preact/signals"; import Counter from "../islands/Counter.tsx"; import { Handlers } from "$fresh/server.ts"; import { getCookies } from "$std/http/cookie.ts"; -import { User } from "../storage/models/User.ts"; - -interface Data { - user: User; -} +import { db, User } from "../storage/store.ts"; +import { auth } from "../auth/auth.ts"; export const handler: Handlers = { GET(req, ctx) { const cookies = getCookies(req.headers); - return ctx.render!({ allowed: cookies.auth === "bar" }); + const user = get_session_user(cookies); + return ctx.render!({ user }); }, }; diff --git a/routes/middleware.ts b/routes/middleware.ts new file mode 100644 index 0000000..6057b2e --- /dev/null +++ b/routes/middleware.ts @@ -0,0 +1,40 @@ +import { FreshContext } from "$fresh/server.ts"; +import { deleteCookie, getCookies, setCookie } from "$std/http/cookie.ts"; +import { auth, Token } from "../auth/auth.ts"; + +type State = { + user_id: string | null; +}; + +export async function handler( + req: Request, + ctx: FreshContext, +) { + const cookies = getCookies(req.headers); + const token = get_session_token(cookies); + + ctx.state.user_id = token?.user_id ?? null; + + const resp = await ctx.next(); + set_session_token(resp.headers, token); + return resp; +} + +function get_session_token(cookies: Record) { + const stored = cookies["auth_token"]; + if (stored === undefined) return null; + const token = auth.tokens.get(stored); + if (token === null) return null; + return token; +} + +function set_session_token(headers: Headers, token: Token | null) { + if (token === null) { + deleteCookie(headers, "auth_token"); + return; + } + setCookie(headers, { + name: "auth_token", + value: token.raw, + }); +} diff --git a/storage/store.ts b/storage/store.ts index aaddf15..2511b59 100644 --- a/storage/store.ts +++ b/storage/store.ts @@ -1,7 +1,6 @@ import { createPentagon } from "https://deno.land/x/pentagon@v0.1.5/mod.ts"; import { project_root_dir } from "../utils.ts"; import { z } from "https://deno.land/x/zod@v3.21.4/mod.ts"; -import mimeDbV1520 from "$std/media_types/vendor/mime-db.v1.52.0.ts"; const kv = await Deno.openKv(project_root_dir() + "local/kv");