feat(app): mount sharing routes + post-migration backfill

This commit is contained in:
2026-05-21 00:28:29 +02:00
parent fb95ccd772
commit 5822dbc8ae
2 changed files with 29 additions and 0 deletions

View File

@@ -13,6 +13,9 @@ import { lessonsRouter } from './routes/lessons.js';
import { cardsRouter } from './routes/cards.js'; import { cardsRouter } from './routes/cards.js';
import { sessionsRouter } from './routes/sessions.js'; import { sessionsRouter } from './routes/sessions.js';
import { statsRouter } from './routes/stats.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 { export function createApp(db: Db): Express {
const app = 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/sessions', requireAuth, verifyCsrf, sessionsRouter(db));
app.use('/api/stats', requireAuth, verifyCsrf, statsRouter(db)); app.use('/api/stats', requireAuth, verifyCsrf, statsRouter(db));
app.use('/api/admin/users', requireAuth, requireRole('sysadmin'), verifyCsrf, adminUsersRouter(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 // Static frontend in production
const frontendDist = resolve(import.meta.dirname, '../../frontend/dist'); const frontendDist = resolve(import.meta.dirname, '../../frontend/dist');

View File

@@ -4,5 +4,28 @@ import { createDb } from './client.js';
const { db, sqlite } = createDb(); const { db, sqlite } = createDb();
migrate(db, { migrationsFolder: resolve(import.meta.dirname, '../../drizzle') }); 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(); sqlite.close();
console.log('Migrations applied.'); console.log('Migrations applied.');