import { Database } from 'bun:sqlite' import { createHash, randomUUID } from 'node:crypto' export interface TestUser { id: string username: string role: string accessToken: string } /** * Insert a user directly into the database (bypasses auth routes). */ export function createUserDirectly( db: Database, opts: { username: string; role?: string }, ): TestUser { const id = `usr_${randomUUID().replace(/-/g, '')}` const role = opts.role || 'member' const now = new Date().toISOString() const passwordHash = '$argon2id$v=19$m=65536,t=3,p=1$dGVzdHNhbHR0ZXN0$' + 'dGVzdGhhc2h0ZXN0aGFzaHRlc3RoYXNodGVzdGhhc2g' try { db.query( `INSERT INTO users (id, username, password_hash, role, created_at) VALUES ($id, $username, $hash, $role, $now)`, ).run({ $id: id, $username: opts.username, $hash: passwordHash, $role: role, $now: now, }) } catch { // users table may not exist } return { id, username: opts.username, role, accessToken: '' } } /** * Issue a session token for a user. * Falls back to manual token insertion if issueSessionToken is unavailable. */ export function issueTokenForUser(db: Database, userId: string): string { try { const { issueSessionToken } = require('../auth/session') as { issueSessionToken: ( userId: string, db: Database, ) => { accessToken: string; refreshToken: string } } const { accessToken } = issueSessionToken(userId, db) return accessToken } catch { const token = `rct_${randomUUID().replace(/-/g, '')}` const tokenHash = createHash('sha256').update(token).digest('hex') const now = new Date().toISOString() const expiresAt = new Date(Date.now() + 3600_000).toISOString() try { db.query( `INSERT INTO session_tokens (token_hash, user_id, kind, expires_at, created_at) VALUES ($hash, $userId, 'access', $exp, $now)`, ).run({ $hash: tokenHash, $userId: userId, $exp: expiresAt, $now: now, }) } catch { // session_tokens may not exist } return token } } /** * Build an Authorization header from a token. */ export function authHeader(token: string): Record { return { Authorization: `Bearer ${token}` } } /** * Create a user and issue them an access token. */ export function createAndLoginUser( db: Database, opts: { username: string; role?: string }, ): TestUser { const user = createUserDirectly(db, opts) user.accessToken = issueTokenForUser(db, user.id) return user }