From 08e56a22d841221a4ea9d5fcb3fddb0e3bc76e45 Mon Sep 17 00:00:00 2001 From: dwindown Date: Fri, 2 Jan 2026 15:07:41 +0700 Subject: [PATCH] Fix send-auth-otp: Remove notification_logs references - Remove notification_logs table references (table doesn't exist) - This was causing the function to crash after sending email - Now the function should complete successfully - Added better email payload logging - Keep .env file for local development --- .env | 8 + check-template.sql | 17 ++ check_email_logs.sql | 14 ++ cleanup-user.sql | 30 ++++ debug-email.sh | 91 +++++++++++ supabase/functions/send-auth-otp/index.ts | 43 ++---- ...20250102000004_fix_auth_email_template.sql | 145 ++++++++++++++++++ test-otp-flow.sh | 104 +++++++++++++ 8 files changed, 421 insertions(+), 31 deletions(-) create mode 100644 .env create mode 100644 check-template.sql create mode 100644 check_email_logs.sql create mode 100644 cleanup-user.sql create mode 100755 debug-email.sh create mode 100644 supabase/migrations/20250102000004_fix_auth_email_template.sql create mode 100755 test-otp-flow.sh diff --git a/.env b/.env new file mode 100644 index 0000000..45bd0ab --- /dev/null +++ b/.env @@ -0,0 +1,8 @@ +SITE_URL=https://with.dwindi.com/ +VITE_APP_ENV=production +VITE_GOOGLE_CLIENT_ID=650232746742-nup9nrp27001n0c6a3vqlc156g4tqfqa.apps.googleusercontent.com +VITE_PAKASIR_API_KEY=iP13osgh7lAzWWIPsj7TbW5M3iGEAQMo +VITE_PAKASIR_PROJECT_SLUG=withdwindi +VITE_SUPABASE_ANON_KEY=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzdXBhYmFzZSIsImlhdCI6MTc2NjAzNzEyMCwiZXhwIjo0OTIxNzEwNzIwLCJyb2xlIjoiYW5vbiJ9.Sa-eECy9dgBUQy3O4X5X-3tDPmF01J5zeT-Qtb-koYc +VITE_SUPABASE_EDGE_URL=https://lovable.backoffice.biz.id/functions/v1 +VITE_SUPABASE_URL=https://lovable.backoffice.biz.id/ \ No newline at end of file diff --git a/check-template.sql b/check-template.sql new file mode 100644 index 0000000..48c7ed3 --- /dev/null +++ b/check-template.sql @@ -0,0 +1,17 @@ +-- Check if the email template exists and has content +SELECT + key, + name, + is_active, + email_subject, + LENGTH(email_body_html) as html_length, + SUBSTRING(email_body_html, 1, 500) as html_preview, + CASE + WHEN email_body_html IS NULL THEN 'NULL - empty template' + WHEN LENGTH(email_body_html) < 100 THEN 'TOO SHORT - template incomplete' + WHEN email_body_html LIKE '%%' THEN 'Has HTML tag' + WHEN email_body_html LIKE '%---%' THEN 'Has YAML delimiters' + ELSE 'Unknown format' + END as template_status +FROM notification_templates +WHERE key = 'auth_email_verification'; diff --git a/check_email_logs.sql b/check_email_logs.sql new file mode 100644 index 0000000..808ca23 --- /dev/null +++ b/check_email_logs.sql @@ -0,0 +1,14 @@ +-- Check recent notification logs for auth_email_verification +SELECT + id, + user_id, + email, + notification_type, + status, + provider, + error_message, + created_at +FROM notification_logs +WHERE notification_type = 'auth_email_verification' +ORDER BY created_at DESC +LIMIT 5; diff --git a/cleanup-user.sql b/cleanup-user.sql new file mode 100644 index 0000000..3568bda --- /dev/null +++ b/cleanup-user.sql @@ -0,0 +1,30 @@ +-- ============================================================================ +-- Clean Up User from Supabase Auth Completely +-- ============================================================================ + +-- NOTE: You CANNOT just DELETE from auth.users +-- Supabase keeps deleted users in a recycle bin + +-- To completely remove a user, you need to use Supabase Auth Admin API +-- OR use a cascade delete from a linked table + +-- Option 1: Delete via cascade (if you have foreign keys) +-- This works because auth_otps has ON DELETE CASCADE +DELETE FROM auth.users WHERE email = 'your@email.com'; + +-- Option 2: Check if user still exists in recycle bin +SELECT id, email, deleted_at +FROM auth.users +WHERE email = 'your@email.com'; + +-- If you see deleted_at IS NOT NULL, the user is in recycle bin + +-- To permanently delete from recycle bin, you need to: +-- 1. Go to Supabase Dashboard → Authentication → Users +-- 2. Find the user +-- 3. Click "Permanently delete" + +-- OR use the Auth Admin API from an edge function: +/* +const { data, error } = await supabase.auth.admin.deleteUser(userId); +*/ diff --git a/debug-email.sh b/debug-email.sh new file mode 100755 index 0000000..16cecc0 --- /dev/null +++ b/debug-email.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +# Test script to debug email sending issue +# Run this after registering a user + +echo "🔍 OTP Email Debug Script" +echo "===========================" +echo "" + +SUPABASE_URL="https://lovable.backoffice.biz.id" +SERVICE_KEY="YOUR_SERVICE_ROLE_KEY_HERE" # Replace with actual service role key + +echo "1. Checking recent OTP records..." +echo "Run this in Supabase SQL Editor:" +echo "" +echo "SELECT" +echo " id," +echo " user_id," +echo " email," +echo " otp_code," +echo " expires_at," +echo " used_at," +echo " created_at" +echo "FROM auth_otps" +echo "ORDER BY created_at DESC" +echo "LIMIT 1;" +echo "" + +echo "2. Checking notification logs..." +echo "Run this in Supabase SQL Editor:" +echo "" +echo "SELECT" +echo " id," +echo " user_id," +echo " email," +echo " notification_type," +echo " status," +echo " provider," +echo " error_message," +echo " created_at" +echo "FROM notification_logs" +echo "WHERE notification_type = 'auth_email_verification'" +echo "ORDER BY created_at DESC" +echo "LIMIT 5;" +echo "" + +echo "3. Checking notification settings..." +echo "Run this in Supabase SQL Editor:" +echo "" +echo "SELECT" +echo " platform_name," +echo " from_name," +echo " from_email," +echo " api_token," +echo " mailketing_api_token" +echo "FROM notification_settings" +echo "LIMIT 1;" +echo "" + +echo "4. Checking email template..." +echo "Run this in Supabase SQL Editor:" +echo "" +echo "SELECT" +echo " key," +echo " name," +echo " is_active," +echo " email_subject," +echo " LEFT(email_body_html, 200) as email_preview" +echo "FROM notification_templates" +echo "WHERE key = 'auth_email_verification';" +echo "" + +echo "5. Testing email sending manually..." +echo "Replace USER_ID and EMAIL with actual values from step 1, then run:" +echo "" +echo "curl -X POST ${SUPABASE_URL}/functions/v1/send-auth-otp \\" +echo " -H \"Authorization: Bearer ${SERVICE_KEY}\" \\" +echo " -H \"Content-Type: application/json\" \\" +echo " -d '{" +echo " \"user_id\": \"USER_UUID\"," +echo " \"email\": \"your@email.com\"" +echo " }'" +echo "" + +echo "6. Common issues to check:" +echo " ✓ from_email is not 'noreply@example.com' (set real domain)" +echo " ✓ api_token or mailketing_api_token is set" +echo " ✓ Email template is_active = true" +echo " ✓ Mailketing API is accessible from Supabase server" +echo " ✓ Check notification_logs.error_message for specific error" +echo "" diff --git a/supabase/functions/send-auth-otp/index.ts b/supabase/functions/send-auth-otp/index.ts index 11b60c8..0d43510 100644 --- a/supabase/functions/send-auth-otp/index.ts +++ b/supabase/functions/send-auth-otp/index.ts @@ -138,7 +138,6 @@ serve(async (req: Request) => { hasFromName: !!settings.from_name, hasFromEmail: !!settings.from_email, platformName: settings.platform_name, - allSettings: JSON.stringify(settings) }); // Use api_token (not mailketing_api_token) @@ -148,6 +147,16 @@ serve(async (req: Request) => { throw new Error('API token not found in notification_settings'); } + // Log email details (truncate HTML body for readability) + console.log('Email payload:', { + to: email, + from_name: settings.from_name || settings.platform_name || 'Admin', + from_email: settings.from_email || 'noreply@example.com', + subject: subject, + html_body_length: htmlBody.length, + html_body_preview: htmlBody.substring(0, 200), + }); + const emailResponse = await fetch(`${supabaseUrl}/functions/v1/send-email-v2`, { method: 'POST', headers: { @@ -173,17 +182,7 @@ serve(async (req: Request) => { const emailResult = await emailResponse.json(); console.log('Email sent successfully:', emailResult); - // Log notification - await supabase - .from('notification_logs') - .insert({ - user_id, - email: email, - notification_type: 'auth_email_verification', - status: 'sent', - provider: 'mailketing', - error_message: null, - }); + // Note: notification_logs table doesn't exist, skipping logging return new Response( JSON.stringify({ @@ -196,25 +195,7 @@ serve(async (req: Request) => { } catch (error: any) { console.error("Error sending OTP:", error); - // Try to log error notification - try { - const supabaseUrl = Deno.env.get('SUPABASE_URL')!; - const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!; - const supabase = createClient(supabaseUrl, supabaseServiceKey); - - await supabase - .from('notification_logs') - .insert({ - user_id: null, - email: null, - notification_type: 'auth_email_verification', - status: 'failed', - provider: 'mailketing', - error_message: error.message || 'Unknown error', - }); - } catch (logError) { - console.error('Failed to log error:', logError); - } + // Note: notification_logs table doesn't exist, skipping error logging return new Response( JSON.stringify({ diff --git a/supabase/migrations/20250102000004_fix_auth_email_template.sql b/supabase/migrations/20250102000004_fix_auth_email_template.sql new file mode 100644 index 0000000..133861a --- /dev/null +++ b/supabase/migrations/20250102000004_fix_auth_email_template.sql @@ -0,0 +1,145 @@ +-- ============================================================================ +-- Fix Auth Email Verification Template - Remove YAML delimiters +-- ============================================================================ + +-- Update the auth_email_verification template with proper HTML +UPDATE notification_templates +SET + email_subject = 'Kode Verifikasi Email Anda - {platform_name}', + email_body_html = ' + + + + + Verifikasi Email + + + +
+
+

🔐 Verifikasi Email

+
+ +
+

Halo {nama},

+ +

+ Terima kasih telah mendaftar di {platform_name}! + Gunakan kode OTP berikut untuk memverifikasi alamat email Anda: +

+ +
+
{otp_code}
+
⏰ Berlaku selama {expiry_minutes} menit
+
+ +
+ Cara menggunakan:
+ 1. Salin kode 6 digit di atas
+ 2. Kembali ke halaman pendaftaran
+ 3. Masukkan kode tersebut pada form verifikasi +
+ +

+ Jika Anda tidak merasa mendaftar di {platform_name}, + abaikan email ini dengan aman. +

+
+ + +
+ +' +WHERE key = 'auth_email_verification'; + +-- Verify the update +SELECT + key, + name, + is_active, + email_subject, + LENGTH(email_body_html) as html_length, + SUBSTRING(email_body_html, 1, 100) as html_start, + CASE + WHEN email_body_html LIKE '%%' THEN '✓ Has HTML tag' + WHEN email_body_html LIKE '%---%' THEN '✗ Still has YAML delimiters' + ELSE 'Unknown format' + END as template_status +FROM notification_templates +WHERE key = 'auth_email_verification'; diff --git a/test-otp-flow.sh b/test-otp-flow.sh new file mode 100755 index 0000000..7180bbf --- /dev/null +++ b/test-otp-flow.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Test OTP Email Flow +# This script tests the complete OTP email verification flow + +echo "🔐 Testing OTP Email Verification Flow" +echo "========================================" +echo "" + +# Configuration +SUPABASE_URL="https://lovable.backoffice.biz.id" +# You need to get your service role key from Coolify/Docker +SERVICE_KEY="YOUR_SERVICE_ROLE_KEY_HERE" + +echo "⚠️ IMPORTANT: Replace YOUR_SERVICE_ROLE_KEY_HERE with your actual service role key" +echo " You can find it in Coolify → Supabase service → Environment variables" +echo "" + +# Step 1: Register a test user (using curl) +echo "Step 1: Creating test user..." +echo "Run this in Supabase SQL Editor first:" +echo "" +echo "-- Clean up any existing test user" +echo "DELETE FROM auth_otps WHERE email = 'test@example.com';" +echo "DELETE FROM auth.users WHERE email = 'test@example.com';" +echo "" + +# Step 2: Test the send-auth-otp edge function +echo "Step 2: Testing send-auth-otp edge function..." +echo "" +echo "Replace USER_ID with the actual UUID from step 1, then run:" +echo "" +echo "curl -X POST ${SUPABASE_URL}/functions/v1/send-auth-otp \\" +echo " -H \"Authorization: Bearer \${SERVICE_KEY}\" \\" +echo " -H \"Content-Type: application/json\" \\" +echo " -d '{" +echo " \"user_id\": \"USER_UUID_HERE\"," +echo " \"email\": \"test@example.com\"" +echo " }'" +echo "" + +# Step 3: Check if OTP was created +echo "Step 3: Check if OTP was created in database..." +echo "Run this in Supabase SQL Editor:" +echo "" +echo "SELECT" +echo " id," +echo " user_id," +echo " email," +echo " otp_code," +echo " expires_at," +echo " used_at," +echo " created_at" +echo "FROM auth_otps" +echo "WHERE email = 'test@example.com'" +echo "ORDER BY created_at DESC" +echo "LIMIT 1;" +echo "" + +# Step 4: Check notification settings +echo "Step 4: Check notification settings..." +echo "Run this in Supabase SQL Editor:" +echo "" +echo "SELECT" +echo " id," +echo " platform_name," +echo " from_name," +echo " from_email," +echo " api_token," +echo " mailketing_api_token" +echo "FROM notification_settings" +echo "LIMIT 1;" +echo "" + +# Step 5: Check email template +echo "Step 5: Check email template..." +echo "Run this in Supabase SQL Editor:" +echo "" +echo "SELECT" +echo " key," +echo " name," +echo " is_active," +echo " email_subject," +echo " LENGTH(email_body_html) as html_length" +echo "FROM notification_templates" +echo "WHERE key = 'auth_email_verification';" +echo "" + +echo "========================================" +echo "Common Issues:" +echo "========================================" +echo "" +echo "1. If curl returns 404: Edge function not deployed" +echo " Solution: Deploy the function from your server" +echo "" +echo "2. If curl returns 401: Invalid service role key" +echo " Solution: Check SERVICE_KEY is correct" +echo "" +echo "3. If curl returns 500: Check edge function logs" +echo " Solution: SSH into server and check Docker logs" +echo "" +echo "4. If OTP created but no email: Mailketing API issue" +echo " Solution: Check api_token in notification_settings" +echo ""