Email System Fixes: - Fix email sending after payment: handle-order-paid now calls send-notification instead of send-email-v2 directly, properly processing template variables - Fix order_created email timing: sent immediately after order creation, before payment QR code generation - Update email templates to use short order ID (8 chars) instead of full UUID - Add working "Akses Sekarang" buttons to payment_success and access_granted emails - Add platform_url column to platform_settings for email links OTP Verification Flow: - Create dedicated /confirm-otp page for users who close registration modal - Add link in checkout modal and email to dedicated OTP page - Update OTP email template with better copywriting and dedicated page link - Fix send-auth-otp to fetch platform settings for dynamic brand_name and platform_url - Auto-login users after OTP verification in checkout flow Admin Features: - Add delete user functionality with cascade deletion of all related data - Update IntegrasiTab to read/write email settings from platform_settings only - Add test email template for email configuration testing Cleanup: - Remove obsolete send-consultation-reminder and send-test-email functions - Update send-email-v2 to read email config from platform_settings - Remove footer links (Ubah Preferensi/Unsubscribe) from email templates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
62 lines
1.9 KiB
TypeScript
62 lines
1.9 KiB
TypeScript
import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
|
|
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
|
|
|
|
const corsHeaders = {
|
|
"Access-Control-Allow-Origin": "*",
|
|
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
|
|
};
|
|
|
|
interface DeleteUserRequest {
|
|
user_id: string;
|
|
}
|
|
|
|
serve(async (req: Request) => {
|
|
if (req.method === "OPTIONS") {
|
|
return new Response(null, { headers: corsHeaders });
|
|
}
|
|
|
|
try {
|
|
const body: DeleteUserRequest = await req.json();
|
|
const { user_id } = body;
|
|
|
|
if (!user_id) {
|
|
return new Response(
|
|
JSON.stringify({ success: false, message: "user_id is required" }),
|
|
{ status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
|
|
);
|
|
}
|
|
|
|
const supabaseUrl = Deno.env.get("SUPABASE_URL")!;
|
|
const supabaseServiceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!;
|
|
const supabase = createClient(supabaseUrl, supabaseServiceKey, {
|
|
auth: {
|
|
autoRefreshToken: false,
|
|
persistSession: false
|
|
}
|
|
});
|
|
|
|
console.log(`Deleting user from auth.users: ${user_id}`);
|
|
|
|
// Delete user from auth.users using admin API
|
|
const { error: deleteError } = await supabase.auth.admin.deleteUser(user_id);
|
|
|
|
if (deleteError) {
|
|
console.error('Error deleting user from auth.users:', deleteError);
|
|
throw new Error(`Failed to delete user from auth: ${deleteError.message}`);
|
|
}
|
|
|
|
console.log(`Successfully deleted user: ${user_id}`);
|
|
|
|
return new Response(
|
|
JSON.stringify({ success: true, message: "User deleted successfully" }),
|
|
{ status: 200, headers: { ...corsHeaders, "Content-Type": "application/json" } }
|
|
);
|
|
} catch (error: any) {
|
|
console.error("Error deleting user:", error);
|
|
return new Response(
|
|
JSON.stringify({ success: false, message: error.message }),
|
|
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
|
|
);
|
|
}
|
|
});
|