import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'; import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'; import { edgeLogger, startRequest, endRequest } from '../_shared/logger.ts'; const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', }; serve(async (req) => { const tracking = startRequest(); if (req.method === 'OPTIONS') { return new Response(null, { headers: { ...corsHeaders, 'X-Request-ID': tracking.requestId } }); } try { const supabaseClient = createClient( Deno.env.get('SUPABASE_URL') ?? '', Deno.env.get('SUPABASE_ANON_KEY') ?? '', { global: { headers: { Authorization: req.headers.get('Authorization')! }, }, } ); // Get authenticated user const { data: { user }, error: userError, } = await supabaseClient.auth.getUser(); if (userError || !user) { const duration = endRequest(tracking); edgeLogger.error('Authentication failed', { action: 'request_deletion', requestId: tracking.requestId, duration }); throw new Error('Unauthorized'); } edgeLogger.info('Processing deletion request', { action: 'request_deletion', requestId: tracking.requestId, userId: user.id }); // Check for existing active deletion request (pending or confirmed) const { data: existingRequest } = await supabaseClient .from('account_deletion_requests') .select('*') .eq('user_id', user.id) .in('status', ['pending', 'confirmed']) .maybeSingle(); if (existingRequest) { const errorMsg = existingRequest.status === 'confirmed' ? 'Your account is already scheduled for deletion. You can cancel it from your account settings.' : 'You already have a pending deletion request. Check your email for the confirmation code.'; return new Response( JSON.stringify({ error: errorMsg, request: existingRequest, }), { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json', 'X-Request-ID': tracking.requestId }, } ); } // Generate confirmation code const { data: codeData, error: codeError } = await supabaseClient .rpc('generate_deletion_confirmation_code'); if (codeError) { throw codeError; } const confirmationCode = codeData as string; const scheduledDeletionAt = new Date(); scheduledDeletionAt.setDate(scheduledDeletionAt.getDate() + 14); // Create deletion request const { data: deletionRequest, error: requestError } = await supabaseClient .from('account_deletion_requests') .insert({ user_id: user.id, confirmation_code: confirmationCode, confirmation_code_sent_at: new Date().toISOString(), scheduled_deletion_at: scheduledDeletionAt.toISOString(), status: 'pending', }) .select() .single(); if (requestError) { throw requestError; } // Send confirmation email const emailPayload = { to: user.email, subject: 'Account Deletion Requested - Confirmation Code Inside', html: `
Hello,
We received a request to delete your account on ${new Date().toLocaleDateString()}.
You must enter the confirmation code within 24 hours. Once confirmed, your account will be deactivated and permanently deleted on ${scheduledDeletionAt.toLocaleDateString()} (14 days from confirmation).
IMPORTANT: You have 24 hours to enter this code to confirm the deletion. After entering the code, your account will be deactivated and you'll have 14 days to cancel before permanent deletion.
Need to cancel? You can cancel at any time - before OR after confirming - during the 14-day period.
Changed your mind? Simply log in to your account settings and click "Cancel Deletion".
`, }; // Send via ForwardEmail API const forwardEmailKey = Deno.env.get('FORWARDEMAIL_API_KEY'); const fromEmail = Deno.env.get('FROM_EMAIL_ADDRESS') || 'noreply@thrillwiki.com'; if (forwardEmailKey) { try { await fetch('https://api.forwardemail.net/v1/emails', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Basic ${btoa(forwardEmailKey + ':')}`, }, body: JSON.stringify({ from: fromEmail, to: emailPayload.to, subject: emailPayload.subject, html: emailPayload.html, }), }); console.log('Deletion confirmation email sent'); } catch (emailError) { console.error('Failed to send email:', emailError); } } const duration = endRequest(tracking); edgeLogger.info('Deletion request created successfully', { action: 'request_deletion', requestId: tracking.requestId, userId: user.id, duration, requestId: deletionRequest.id }); return new Response( JSON.stringify({ success: true, message: 'Account deletion request created successfully', scheduled_deletion_at: scheduledDeletionAt.toISOString(), request_id: deletionRequest.id, requestId: tracking.requestId, }), { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json', 'X-Request-ID': tracking.requestId }, } ); } catch (error) { const duration = endRequest(tracking); edgeLogger.error('Error processing deletion request', { action: 'request_deletion', requestId: tracking.requestId, duration, error: error.message }); return new Response( JSON.stringify({ error: error.message, requestId: tracking.requestId }), { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json', 'X-Request-ID': tracking.requestId }, } ); } });