import { NextResponse } from 'next/server'; import { createClient } from '@supabase/supabase-js'; import { apiError } from '@kit/next/route-helpers'; import { getLogger } from '@kit/shared/logger'; export async function POST(request: Request) { const logger = await getLogger(); try { const formData = await request.formData(); const token = formData.get('token') as string; const slug = formData.get('slug') as string; const password = formData.get('password') as string; if (!token || !password || password.length < 8) { return NextResponse.json({ error: 'Ungültige Eingabe' }, { status: 400 }); } // Use service role to create user + link member const supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.SUPABASE_SECRET_KEY!, ); // 1. Get invitation const { data: invitation, error: invError } = await supabase .from('member_portal_invitations') .select('id, email, member_id, account_id, status, expires_at') .eq('invite_token', token) .single(); if (invError || !invitation || invitation.status !== 'pending') { return NextResponse.redirect( new URL( `/club/${slug}/portal/invite?token=${token}&error=invalid`, request.url, ), ); } if (new Date(invitation.expires_at) < new Date()) { return NextResponse.redirect( new URL( `/club/${slug}/portal/invite?token=${token}&error=expired`, request.url, ), ); } // 2. Create auth user const { data: authData, error: authError } = await supabase.auth.admin.createUser({ email: invitation.email, password, email_confirm: true, user_metadata: { invited_via: 'member_portal' }, }); if (authError) { // User might already exist — try to find them const { data: existingUsers } = await supabase.auth.admin.listUsers(); const existing = existingUsers?.users?.find( (u) => u.email === invitation.email, ); if (existing) { // Link existing user to member await supabase .from('members') .update({ user_id: existing.id }) .eq('id', invitation.member_id); await supabase .from('member_portal_invitations') .update({ status: 'accepted', accepted_at: new Date().toISOString() }) .eq('id', invitation.id); return NextResponse.redirect( new URL(`/club/${slug}/portal`, request.url), ); } logger.error( { error: authError, context: 'accept-invite-auth' }, '[accept-invite] Auth error', ); return NextResponse.redirect( new URL( `/club/${slug}/portal/invite?token=${token}&error=auth`, request.url, ), ); } // 3. Link member to user await supabase .from('members') .update({ user_id: authData.user.id }) .eq('id', invitation.member_id); // 4. Mark invitation as accepted await supabase .from('member_portal_invitations') .update({ status: 'accepted', accepted_at: new Date().toISOString(), }) .eq('id', invitation.id); // 5. Redirect to portal login return NextResponse.redirect(new URL(`/club/${slug}/portal`, request.url)); } catch (err) { logger.error( { error: err, context: 'accept-invite' }, '[accept-invite] Error', ); return apiError('Serverfehler', 500); } }