import { eq, SQL, type Operators } from 'drizzle-orm'; import useDatabase from '~/composables/useDatabase'; import { characterTable, userPermissionsTable } from '~/db/schema'; import { hasPermissions } from '~/shared/auth.util'; import { group } from '~/shared/general.util'; import type { Character, MainStat, TrainingLevel } from '~/types/character'; export default defineEventHandler(async (e) => { let { visibility } = getQuery(e) as { visibility?: "public" | "own" | "admin" }; if(!visibility) { visibility = "own"; } let where: ((character: typeof characterTable._.config.columns, sql: Operators) => SQL | undefined) | undefined = undefined; const db = useDatabase(); const session = await getUserSession(e); if(visibility === "own") { if(!session.user) { setResponseStatus(e, 401); return; } where = (character, { eq, and }) => and(eq(character.owner, session.user!.id)); } else if(visibility === 'public') { where = (character, { eq, and }) => eq(character.visibility, "public"); } else if(visibility === 'admin') { if(!session.user) { setResponseStatus(e, 401); return; } const db = useDatabase(); const rights = db.select({ right: userPermissionsTable.permission }).from(userPermissionsTable).where(eq(userPermissionsTable.id, session.user.id)).all(); if(rights.length === 0 || !hasPermissions(rights.map(e => e.right), ['admin'])) { setResponseStatus(e, 403); return; } where = undefined; } const characters = db.query.characterTable.findMany({ with: { abilities: true, levels: true, training: true, choices: true, user: { columns: { username: true } } }, where: where, }).sync(); if(characters !== undefined) { return characters.map(character => ({ id: character.id, name: character.name, people: character.people, level: character.level, aspect: character.aspect, notes: { public: character.public_notes, private: session.user?.id === character.owner ? character.private_notes : undefined }, variables: character.variables, training: character.training.reduce((p, v) => { p[v.stat] ??= {}; p[v.stat][v.level as TrainingLevel] = v.choice; return p; }, {} as Record>>), leveling: group(character.levels, "level", "choice"), abilities: group(character.abilities, "ability", "value"), choices: character.choices.reduce((p, v) => { p[v.id] ??= []; p[v.id]?.push(v.choice); return p; }, {} as Record), owner: character.owner, username: character.user.username, visibility: character.visibility, } as Character)); } setResponseStatus(e, 404); return; });