Release 0.2.0

This commit is contained in:
hnzio committed 2026-10-21 17:25:28 +02:00
1 parent 7a49e66c37
commit 08e8875cb5
38 files changed
+2645 -93

No files matched your search

+94 -2
View File
@@ -1,5 +1,97 @@
import { fail } from '@sveltejs/kit';
import type { Actions, PageServerLoad } from './$types';
import { getTaxonomy } from '#lib/server/previews.js';
import { getMailConfig } from '#lib/server/config.js';
import {
inviteUser,
isRole,
listOpenInvitations,
listUsers,
requireBarkeeper,
revokeInvitation,
setUserLocked,
setUserRole,
validEmail
} from '#lib/server/auth.js';
export function load() {
return { taxonomy: getTaxonomy() };
export const load: PageServerLoad = ({ locals }) => {
requireBarkeeper(locals.user);
return {
taxonomy: getTaxonomy(),
users: listUsers(),
invitations: listOpenInvitations(),
mailTransport: getMailConfig().transport
};
};
function actionError(cause: unknown): string {
const code = cause instanceof Error ? cause.message : '';
if (code === 'USER_EXISTS') return 'Für diese E-Mail existiert bereits ein Konto.';
if (code === 'SELF_LOCK') return 'Das eigene Konto kann nicht gesperrt werden.';
if (code === 'LAST_BARKEEPER') return 'Mindestens ein aktiver Barkeeper muss erhalten bleiben.';
if (code === 'NOT_FOUND') return 'Das Konto wurde nicht gefunden.';
return 'Die Aktion konnte nicht ausgeführt werden.';
}
export const actions = {
invite: async ({ locals, request }) => {
const actor = requireBarkeeper(locals.user);
const data = await request.formData();
const email = String(data.get('email') || '').trim();
const role = String(data.get('role') || '');
if (!validEmail(email) || !isRole(role)) {
return fail(400, { intent: 'invite', email, error: 'E-Mail und Rolle bitte prüfen.' });
}
try {
const transport = await inviteUser(actor, email, role);
return {
intent: 'invite',
success:
transport === 'local'
? 'Einladung wurde in der lokalen Mail-Outbox abgelegt.'
: 'Einladung wurde versandt.'
};
} catch (cause) {
return fail(400, { intent: 'invite', email, error: actionError(cause) });
}
},
role: async ({ locals, request }) => {
const actor = requireBarkeeper(locals.user);
const data = await request.formData();
const userId = String(data.get('userId') || '');
const role = String(data.get('role') || '');
if (!userId || !isRole(role)) return fail(400, { intent: 'role', error: 'Ungültige Rolle.' });
try {
setUserRole(actor, userId, role);
return { intent: 'role', success: 'Rolle aktualisiert.' };
} catch (cause) {
return fail(400, { intent: 'role', error: actionError(cause) });
}
},
lock: async ({ locals, request }) => {
const actor = requireBarkeeper(locals.user);
const data = await request.formData();
try {
setUserLocked(actor, String(data.get('userId') || ''), true);
return { intent: 'lock', success: 'Konto gesperrt und bestehende Sitzungen beendet.' };
} catch (cause) {
return fail(400, { intent: 'lock', error: actionError(cause) });
}
},
unlock: async ({ locals, request }) => {
const actor = requireBarkeeper(locals.user);
const data = await request.formData();
try {
setUserLocked(actor, String(data.get('userId') || ''), false);
return { intent: 'unlock', success: 'Konto entsperrt.' };
} catch (cause) {
return fail(400, { intent: 'unlock', error: actionError(cause) });
}
},
revokeInvitation: async ({ locals, request }) => {
const actor = requireBarkeeper(locals.user);
const data = await request.formData();
revokeInvitation(actor, String(data.get('invitationId') || ''));
return { intent: 'revokeInvitation', success: 'Einladung widerrufen.' };
}
} satisfies Actions;