feat: per-user visibility (own/shared), anonymous generations, private sessions (generate+forget), NSFW model gating
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNQ8ghPfzAfsyVYd6HgFb6
This commit is contained in:
@@ -7,8 +7,15 @@ const json = (b: unknown, s = 200) =>
|
||||
|
||||
export const GET: APIRoute = async ({ params, locals }) => {
|
||||
if (!locals.user) return new Response('Unauthorized', { status: 401 });
|
||||
const job = await one('SELECT * FROM jobs WHERE id=$1', [params.id]);
|
||||
const job = await one<any>('SELECT * FROM jobs WHERE id=$1', [params.id]);
|
||||
if (!job) return json({ error: 'Nicht gefunden.' }, 404);
|
||||
// Zugriff: eigener Auftrag, Admin, oder shared (nicht privat).
|
||||
const isAdmin = locals.user.role === 'admin';
|
||||
const own = job.created_by === locals.user.uid;
|
||||
if (!isAdmin && !own) {
|
||||
const s = await one<{ library_visibility: string }>('SELECT library_visibility FROM settings WHERE id=1');
|
||||
if (job.private || s?.library_visibility !== 'shared') return new Response('Forbidden', { status: 403 });
|
||||
}
|
||||
const items = await query(
|
||||
`SELECT id, position, status, filename, output_px, has_alpha, error_message,
|
||||
result_path, delivery_status, cost FROM items WHERE job_id=$1 ORDER BY position`,
|
||||
|
||||
@@ -8,9 +8,16 @@ const json = (b: unknown, s = 200) =>
|
||||
|
||||
export const GET: APIRoute = async ({ locals }) => {
|
||||
if (!locals.user) return new Response('Unauthorized', { status: 401 });
|
||||
const s = await one<any>('SELECT library_visibility, anonymous_generations FROM settings WHERE id=1');
|
||||
const isAdmin = locals.user.role === 'admin';
|
||||
const shared = s?.library_visibility === 'shared';
|
||||
const where: string[] = ['j.private=false']; const args: any[] = [];
|
||||
if (!isAdmin && !shared) { args.push(locals.user.uid); where.push(`j.created_by=$${args.length}`); }
|
||||
const nameCol = (s?.anonymous_generations && !isAdmin) ? 'NULL' : 'u.display_name';
|
||||
const rows = await query(
|
||||
`SELECT j.*, u.display_name AS by_name FROM jobs j
|
||||
LEFT JOIN users u ON u.id=j.created_by ORDER BY j.created_at DESC LIMIT 50`);
|
||||
`SELECT j.*, ${nameCol} AS by_name FROM jobs j
|
||||
LEFT JOIN users u ON u.id=j.created_by
|
||||
WHERE ${where.join(' AND ')} ORDER BY j.created_at DESC LIMIT 50`, args);
|
||||
return json({ jobs: rows });
|
||||
};
|
||||
|
||||
@@ -52,11 +59,17 @@ export const POST: APIRoute = async ({ request, locals }) => {
|
||||
delivery_target_id: snapshot.delivery_target_id ?? null,
|
||||
};
|
||||
|
||||
// Private Session: nur wenn global erlaubt oder für den Nutzer erzwungen.
|
||||
const acc = await one<any>(`SELECT s.private_allowed, u.private_forced
|
||||
FROM settings s, users u WHERE s.id=1 AND u.id=$1`, [locals.user.uid]);
|
||||
const isPrivate = !!(acc?.private_forced || (acc?.private_allowed && b.private));
|
||||
if (isPrivate) snap.delivery = 'library'; // kein externes Delivery bei privaten Aufträgen
|
||||
|
||||
const total = (mode === 'each') ? sources.length : 1;
|
||||
const job = await one<{ id: string }>(
|
||||
`INSERT INTO jobs (created_by, origin, mode, recipe_snapshot, status, total)
|
||||
VALUES ($1,$2,$3,$4,'queued',$5) RETURNING id`,
|
||||
[locals.user.uid, b.origin || 'web', mode, JSON.stringify(snap), total]);
|
||||
`INSERT INTO jobs (created_by, origin, mode, recipe_snapshot, status, total, private)
|
||||
VALUES ($1,$2,$3,$4,'queued',$5,$6) RETURNING id`,
|
||||
[locals.user.uid, b.origin || 'web', mode, JSON.stringify(snap), total, isPrivate]);
|
||||
|
||||
if (mode === 'each') {
|
||||
for (let i = 0; i < sources.length; i++) {
|
||||
|
||||
Reference in New Issue
Block a user