diff options
Diffstat (limited to 'app/lib')
| -rw-r--r-- | app/lib/db.server.ts | 52 | ||||
| -rw-r--r-- | app/lib/passkey.server.ts | 11 | ||||
| -rw-r--r-- | app/lib/session.server.ts | 12 |
3 files changed, 75 insertions, 0 deletions
diff --git a/app/lib/db.server.ts b/app/lib/db.server.ts index b076ec7..cd8d198 100644 --- a/app/lib/db.server.ts +++ b/app/lib/db.server.ts @@ -22,9 +22,18 @@ function initSchema(db: Database.Database) { created_at TEXT NOT NULL DEFAULT (datetime('now')) ); CREATE INDEX IF NOT EXISTS idx_posts_created_at ON posts(created_at DESC); + + CREATE TABLE IF NOT EXISTS credentials ( + id TEXT PRIMARY KEY, + public_key TEXT NOT NULL, + counter INTEGER NOT NULL DEFAULT 0, + transports TEXT + ); `); } +/* ── Posts ── */ + export interface Post { id: string; content: string; @@ -48,3 +57,46 @@ export function createPost(input: CreatePostInput): Post { getDb().prepare("INSERT INTO posts (id, content) VALUES (?, ?)").run(input.id, input.content); return getPostById(input.id)!; } + +export function deletePost(id: string): void { + getDb().prepare("DELETE FROM posts WHERE id = ?").run(id); +} + +/* ── Credentials (passkey) ── */ + +export interface Credential { + id: string; + public_key: string; + counter: number; + transports: string | null; +} + +export function listCredentials(): Credential[] { + return getDb().prepare("SELECT * FROM credentials").all() as Credential[]; +} + +export function getCredentialById(id: string): Credential | null { + return getDb().prepare("SELECT * FROM credentials WHERE id = ?").get(id) as Credential | null; +} + +export function saveCredential(input: { + id: string; + publicKey: Uint8Array; + counter: number; + transports?: string[]; +}): void { + getDb() + .prepare( + "INSERT INTO credentials (id, public_key, counter, transports) VALUES (?, ?, ?, ?)" + ) + .run( + input.id, + Buffer.from(input.publicKey).toString("base64url"), + input.counter, + input.transports ? JSON.stringify(input.transports) : null + ); +} + +export function updateCredentialCounter(id: string, counter: number): void { + getDb().prepare("UPDATE credentials SET counter = ? WHERE id = ?").run(counter, id); +} diff --git a/app/lib/passkey.server.ts b/app/lib/passkey.server.ts new file mode 100644 index 0000000..e88c4f8 --- /dev/null +++ b/app/lib/passkey.server.ts @@ -0,0 +1,11 @@ +export const rpID = + process.env.WEBAUTHN_RP_ID ?? + (process.env.NODE_ENV === "production" ? "blog.yyamashita.com" : "localhost"); + +export const origin = + process.env.WEBAUTHN_ORIGIN ?? + (process.env.NODE_ENV === "production" + ? "https://blog.yyamashita.com" + : "http://localhost:5173"); + +export const rpName = "microblog"; diff --git a/app/lib/session.server.ts b/app/lib/session.server.ts new file mode 100644 index 0000000..13a7cd1 --- /dev/null +++ b/app/lib/session.server.ts @@ -0,0 +1,12 @@ +import { createCookieSessionStorage } from "react-router"; + +export const { getSession, commitSession, destroySession } = createCookieSessionStorage({ + cookie: { + name: "__session", + secrets: [process.env.SESSION_SECRET ?? "dev-secret-change-in-production"], + secure: process.env.NODE_ENV === "production", + httpOnly: true, + sameSite: "lax", + maxAge: 60 * 60 * 24 * 30, + }, +}); |
