feat(routes): thread userId through routes + visibility/fork/curated endpoints

This commit is contained in:
2026-05-21 00:26:49 +02:00
parent 181a757323
commit fb95ccd772
7 changed files with 98 additions and 48 deletions

View File

@@ -3,6 +3,8 @@ import * as XLSX from 'xlsx';
import type { Db } from '../db/client.js';
import { cardProgress, cards, lessons } from '../db/schema.js';
import { getDescendantLessonIds } from './lessons.js';
import { canEditLesson, canReadLesson } from './permissions.js';
import { ApiError } from '../lib/errors.js';
export interface ImportRow {
question: string;
@@ -55,8 +57,11 @@ async function resolveLesson(
}
export async function importCardsFromBuffer(
db: Db, defaultLessonId: number, buffer: Buffer, opts: ImportOptions
db: Db, userId: number, defaultLessonId: number, buffer: Buffer, opts: ImportOptions
): Promise<ImportResult> {
if (!(await canEditLesson(db, userId, defaultLessonId))) {
throw new ApiError(403, 'FORBIDDEN_LESSON', 'Not your lesson');
}
const rows = parseSheet(buffer);
const result: ImportResult = { inserted: 0, updated: 0, skipped: 0, errors: [] };
for (let i = 0; i < rows.length; i++) {
@@ -94,7 +99,12 @@ export async function importCardsFromBuffer(
return result;
}
export async function exportCardsToBuffer(db: Db, lessonId: number, includeDescendants: boolean): Promise<Buffer> {
export async function exportCardsToBuffer(
db: Db, userId: number, lessonId: number, includeDescendants: boolean
): Promise<Buffer> {
if (!(await canReadLesson(db, userId, lessonId))) {
throw new ApiError(403, 'FORBIDDEN_LESSON', 'Cannot read this lesson');
}
const ids = includeDescendants ? await getDescendantLessonIds(db, lessonId) : [lessonId];
const lessonRows = db.select().from(lessons).where(inArray(lessons.id, ids)).all();
const pathById = buildPathMap(lessonRows);