136 lines
4.9 KiB
TypeScript
136 lines
4.9 KiB
TypeScript
import { fail } from '@sveltejs/kit';
|
|
import type { Actions, PageServerLoad } from './$types';
|
|
import {
|
|
createTaxonomy,
|
|
deleteTaxonomy,
|
|
getTaxonomy,
|
|
type TaxonomyKind
|
|
} from '#lib/server/content.js';
|
|
import { getMailConfig } from '#lib/server/config.js';
|
|
import {
|
|
inviteUser,
|
|
isRole,
|
|
listOpenInvitations,
|
|
listUsers,
|
|
requireBarkeeper,
|
|
revokeInvitation,
|
|
setUserLocked,
|
|
setUserRole,
|
|
validEmail
|
|
} from '#lib/server/auth.js';
|
|
|
|
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 'Der Eintrag wurde nicht gefunden.';
|
|
if (code === 'TAXONOMY_EXISTS') return 'Dieser Name ist bereits vorhanden.';
|
|
if (code === 'TAXONOMY_IN_USE')
|
|
return 'Verwendete oder für Vorlagen benötigte Einträge können nicht entfernt werden.';
|
|
if (code === 'INVALID_COLOR') return 'Bitte eine gültige Farbe wählen.';
|
|
if (code === 'INVALID_TAXONOMY') return 'Bitte einen gültigen Namen eingeben.';
|
|
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.' };
|
|
},
|
|
createTaxonomy: async ({ locals, request }) => {
|
|
requireBarkeeper(locals.user);
|
|
const data = await request.formData();
|
|
const kind = String(data.get('kind') || '') as TaxonomyKind;
|
|
if (!['category', 'format', 'topic'].includes(kind)) {
|
|
return fail(400, { intent: 'taxonomy', error: 'Ungültige Taxonomieart.' });
|
|
}
|
|
try {
|
|
createTaxonomy(kind, String(data.get('name') || ''), String(data.get('color') || ''));
|
|
return { intent: 'taxonomy', success: 'Eintrag angelegt.' };
|
|
} catch (cause) {
|
|
return fail(400, { intent: 'taxonomy', error: actionError(cause) });
|
|
}
|
|
},
|
|
deleteTaxonomy: async ({ locals, request }) => {
|
|
requireBarkeeper(locals.user);
|
|
const data = await request.formData();
|
|
const kind = String(data.get('kind') || '') as TaxonomyKind;
|
|
if (!['category', 'format', 'topic'].includes(kind)) {
|
|
return fail(400, { intent: 'taxonomy', error: 'Ungültige Taxonomieart.' });
|
|
}
|
|
try {
|
|
deleteTaxonomy(kind, String(data.get('taxonomyId') || ''));
|
|
return { intent: 'taxonomy', success: 'Eintrag entfernt.' };
|
|
} catch (cause) {
|
|
return fail(400, { intent: 'taxonomy', error: actionError(cause) });
|
|
}
|
|
}
|
|
} satisfies Actions;
|