From 5822dbc8ae47a7c77d53e04b4e7bbcbeed865103 Mon Sep 17 00:00:00 2001 From: Bert Hausmans Date: Thu, 21 May 2026 00:28:29 +0200 Subject: [PATCH] feat(app): mount sharing routes + post-migration backfill --- packages/backend/src/app.ts | 6 ++++++ packages/backend/src/db/migrate.ts | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/packages/backend/src/app.ts b/packages/backend/src/app.ts index 9e59c42..f7f2799 100644 --- a/packages/backend/src/app.ts +++ b/packages/backend/src/app.ts @@ -13,6 +13,9 @@ import { lessonsRouter } from './routes/lessons.js'; import { cardsRouter } from './routes/cards.js'; import { sessionsRouter } from './routes/sessions.js'; import { statsRouter } from './routes/stats.js'; +import { subscriptionsRouter } from './routes/subscriptions.js'; +import { marketplaceRouter } from './routes/marketplace.js'; +import { adminLessonsRouter } from './routes/admin-lessons.js'; export function createApp(db: Db): Express { const app = express(); @@ -34,6 +37,9 @@ export function createApp(db: Db): Express { app.use('/api/sessions', requireAuth, verifyCsrf, sessionsRouter(db)); app.use('/api/stats', requireAuth, verifyCsrf, statsRouter(db)); app.use('/api/admin/users', requireAuth, requireRole('sysadmin'), verifyCsrf, adminUsersRouter(db)); + app.use('/api/admin/lessons', requireAuth, requireRole('sysadmin'), verifyCsrf, adminLessonsRouter(db)); + app.use('/api', requireAuth, verifyCsrf, subscriptionsRouter(db)); + app.use('/api/marketplace', requireAuth, marketplaceRouter(db)); // Static frontend in production const frontendDist = resolve(import.meta.dirname, '../../frontend/dist'); diff --git a/packages/backend/src/db/migrate.ts b/packages/backend/src/db/migrate.ts index 327b92e..6876b88 100644 --- a/packages/backend/src/db/migrate.ts +++ b/packages/backend/src/db/migrate.ts @@ -4,5 +4,28 @@ import { createDb } from './client.js'; const { db, sqlite } = createDb(); migrate(db, { migrationsFolder: resolve(import.meta.dirname, '../../drizzle') }); + +// Post-migration backfill: assign orphan rows to the oldest active sysadmin. +// Idempotent and safe on fresh DBs (no-op if no users yet). +function backfill() { + const sysadmin = sqlite.prepare(` + SELECT id FROM users + WHERE role='sysadmin' AND is_active=1 + ORDER BY id ASC LIMIT 1 + `).get() as { id: number } | undefined; + if (!sysadmin) { + console.log('Backfill: no active sysadmin yet; skipping (this is normal on a fresh DB).'); + return; + } + const uid = sysadmin.id; + const r1 = sqlite.prepare(`UPDATE lessons SET owner_id = ? WHERE owner_id IS NULL`).run(uid); + const r2 = sqlite.prepare(`UPDATE sessions SET user_id = ? WHERE user_id IS NULL`).run(uid); + const r3 = sqlite.prepare(`UPDATE card_progress SET user_id = ? WHERE user_id IS NULL`).run(uid); + if (r1.changes || r2.changes || r3.changes) { + console.log(`Backfill: assigned ${r1.changes} lessons, ${r2.changes} sessions, ${r3.changes} card_progress rows to sysadmin id=${uid}.`); + } +} +backfill(); + sqlite.close(); console.log('Migrations applied.');