/** * E2E test database seeder. * * Creates known test users and sessions in the test Postgres database. * Designed to be idempotent: uses INSERT ... ON CONFLICT DO NOTHING. * * Usage: npx tsx seed.ts */ import pg from 'pg'; import { createHash } from 'node:crypto'; const { Client } = pg; // --------------------------------------------------------------------------- // Known test tokens (raw values that go into cookies / URLs). // Their SHA-256 hashes are stored in the DB. // --------------------------------------------------------------------------- export const ADMIN_SESSION_TOKEN = 'e2e-admin-session-token-for-testing-only'; export const USER_SESSION_TOKEN = 'e2e-user-session-token-for-testing-only'; function sha256(input: string): string { return createHash('sha256').update(input).digest('hex'); } async function seed() { const databaseUrl = process.env.DATABASE_URL ?? 'postgres://ai_synth_test:testpassword@localhost:5433/ai_synth_test'; const client = new Client({ connectionString: databaseUrl }); await client.connect(); try { // ----------------------------------------------------------------------- // 1. Create admin user // ----------------------------------------------------------------------- const adminId = '00000000-0000-4000-a000-000000000001'; await client.query( `INSERT INTO users (id, email, display_name, role, created_at, updated_at) VALUES ($1, 'admin@test.local', 'Test Admin', 'admin', now(), now()) ON CONFLICT (id) DO NOTHING`, [adminId], ); // ----------------------------------------------------------------------- // 2. Create regular user // ----------------------------------------------------------------------- const userId = '00000000-0000-4000-a000-000000000002'; await client.query( `INSERT INTO users (id, email, display_name, role, created_at, updated_at) VALUES ($1, 'user@test.local', 'Test User', 'user', now(), now()) ON CONFLICT (id) DO NOTHING`, [userId], ); // ----------------------------------------------------------------------- // 3. Create sessions (hash tokens with SHA-256 before inserting) // ----------------------------------------------------------------------- const adminSessionHash = sha256(ADMIN_SESSION_TOKEN); const userSessionHash = sha256(USER_SESSION_TOKEN); const expiresAt = new Date( Date.now() + 30 * 24 * 60 * 60 * 1000, ).toISOString(); // 30 days await client.query( `INSERT INTO sessions (session_hash, user_id, created_at, expires_at, last_active_at) VALUES ($1, $2, now(), $3, now()) ON CONFLICT (session_hash) DO NOTHING`, [adminSessionHash, adminId, expiresAt], ); await client.query( `INSERT INTO sessions (session_hash, user_id, created_at, expires_at, last_active_at) VALUES ($1, $2, now(), $3, now()) ON CONFLICT (session_hash) DO NOTHING`, [userSessionHash, userId, expiresAt], ); // ----------------------------------------------------------------------- // 4. Ensure Gemini provider exists and is enabled // (The migration seeds it, but make sure is_enabled = true) // ----------------------------------------------------------------------- await client.query( `UPDATE admin_providers SET is_enabled = true WHERE provider_name = 'gemini'`, ); console.log('Seed completed successfully.'); console.log(` Admin: admin@test.local (id=${adminId})`); console.log(` User: user@test.local (id=${userId})`); console.log(` Admin session hash: ${adminSessionHash.slice(0, 16)}...`); console.log(` User session hash: ${userSessionHash.slice(0, 16)}...`); } finally { await client.end(); } } seed().catch((err) => { console.error('Seed failed:', err); process.exit(1); });