import { getUserFromToken, hasAnyRole, readUsers, writeUsers, normalizeUserEmail } from '../utils/auth.js' import { readMembers, saveMember } from '../utils/members.js' function requestedBirthdayVisibility(body) { return body?.visibility?.showBirthday ?? body?.showBirthday } function birthdayVisibilityIsTrue(value) { return value === true || value === 'true' } function resolveAdminBirthdayVisibility({ requested, existingManualMember, existingUser }) { if (requested === false || requested === 'false') return false const existingValue = existingUser?.visibility?.showBirthday ?? existingManualMember?.visibility?.showBirthday if (existingValue === true) return true return false } export default defineEventHandler(async (event) => { try { // Support both Cookie and Authorization Header let token = getCookie(event, 'auth_token') // If no cookie token, try Authorization header (Bearer token) if (!token) { const authHeader = getHeader(event, 'authorization') if (authHeader && authHeader.startsWith('Bearer ')) { token = authHeader.substring(7) } } if (!token) { throw createError({ statusCode: 401, message: 'Nicht authentifiziert. Bitte Token im Cookie oder Authorization-Header bereitstellen.' }) } const user = await getUserFromToken(token) if (!user) { throw createError({ statusCode: 401, message: 'Nicht authentifiziert oder Benutzer nicht gefunden.' }) } // Only admin and vorstand can add/edit members if (!hasAnyRole(user, 'admin', 'vorstand')) { throw createError({ statusCode: 403, message: 'Keine Berechtigung zum Hinzufügen/Bearbeiten von Mitgliedern. Erforderlich: admin oder vorstand Rolle.' }) } const body = await readBody(event) const { id, firstName, lastName, geburtsdatum, email, phone, address, notes, isMannschaftsspieler, hasHallKey, hasHallenschluessel, active, visibility } = body if (!firstName || !lastName) { throw createError({ statusCode: 400, message: 'Vorname und Nachname sind erforderlich.' }) } if (!geburtsdatum && !id) { throw createError({ statusCode: 400, message: 'Geburtsdatum ist für neue Mitglieder erforderlich, um Duplikate zu vermeiden.' }) } try { const [members, users] = await Promise.all([readMembers(), readUsers()]) const normalizedEmail = normalizeUserEmail(email) const existingManualMember = members.find(member => { if (id && member.id === id) return true return normalizedEmail && normalizeUserEmail(member.email) === normalizedEmail }) const userIndex = users.findIndex(user => { if (id && user.id === id) return true return normalizedEmail && normalizeUserEmail(user.email) === normalizedEmail }) const existingUser = userIndex !== -1 ? users[userIndex] : null const nextShowBirthday = resolveAdminBirthdayVisibility({ requested: requestedBirthdayVisibility(body), existingManualMember, existingUser }) await saveMember({ id: id || undefined, firstName, lastName, geburtsdatum: geburtsdatum || '', email: email || '', phone: phone || '', address: address || '', notes: notes || '', isMannschaftsspieler: isMannschaftsspieler === true || isMannschaftsspieler === 'true', hasHallKey: hasHallKey === true || hasHallKey === 'true' || hasHallenschluessel === true || hasHallenschluessel === 'true', visibility: { ...(visibility && typeof visibility === 'object' ? visibility : {}), showBirthday: nextShowBirthday }, active: typeof active === 'boolean' ? active : true }) if (userIndex !== -1 && (!birthdayVisibilityIsTrue(requestedBirthdayVisibility(body)) || existingUser?.visibility?.showBirthday === true)) { users[userIndex].visibility = { ...(users[userIndex].visibility || {}), showBirthday: nextShowBirthday } await writeUsers(users) } return { success: true, message: 'Mitglied erfolgreich gespeichert.' } } catch (memberError) { // Check if it's a duplicate error if (memberError.message && memberError.message.includes('existiert bereits')) { throw createError({ statusCode: 409, message: memberError.message }) } // Re-throw other errors throw memberError } } catch (error) { console.error('Fehler beim Speichern des Mitglieds:', error) // If it's already a createError, re-throw it if (error.statusCode) { throw error } // Otherwise wrap it throw createError({ statusCode: error.statusCode || 500, message: error.message || 'Fehler beim Speichern des Mitglieds.' }) } })