feat(app): mount sharing routes + post-migration backfill
This commit is contained in:
@@ -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');
|
||||||
|
|||||||
@@ -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.');
|
||||||
|
|||||||
Reference in New Issue
Block a user