// Follow this setup guide to integrate the Deno language server with your editor: // https://deno.land/manual/getting_started/setup_your_environment // This enables autocomplete, go to definition, etc. // Setup type definitions for built-in Supabase Runtime APIs //import "jsr:@supabase/functions-js/edge-runtime.d.ts" //console.log("Hello from Functions!") //Deno.serve(async (req) => { // const { name } = await req.json() // const data = { // message: `Hello ${name}!`, // } // return new Response( // JSON.stringify(data), // { headers: { "Content-Type": "application/json" } }, // ) //}) /* To invoke locally: 1. Run `supabase start` (see: https://supabase.com/docs/reference/cli/supabase-start) 2. Make an HTTP request: curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/delete-user' \ --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \ --header 'Content-Type: application/json' \ --data '{"name":"Functions"}' */ import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'; import { corsHeaders } from '../_shared/.temp/functions/_shared/cors.ts'; Deno.serve(async (req) => { // Handle preflight OPTIONS request for CORS if (req.method === 'OPTIONS') { return new Response('ok', { headers: corsHeaders }); } try { const { password } = await req.json(); if (!password) { throw new Error('Password is required.'); } // Create a Supabase client with the user's authentication token const authHeader = req.headers.get('Authorization'); if (!authHeader) { throw new Error('Missing authorization header.'); } const userSupabaseClient = createClient( Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_ANON_KEY')!, { global: { headers: { Authorization: authHeader } } } ); // Get the user from the token const { data: { user }, error: userError } = await userSupabaseClient.auth.getUser(); if (userError || !user) { return new Response(JSON.stringify({ error: userError?.message || 'User not authenticated.' }), { status: 401, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } // Verify the user's password by attempting to sign in const { error: signInError } = await userSupabaseClient.auth.signInWithPassword({ email: user.email!, password: password, }); if (signInError) { return new Response(JSON.stringify({ error: 'Invalid password.' }), { status: 403, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } // If password is correct, create an admin client with the service_role key const adminSupabaseClient = createClient( Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!, { auth: { autoRefreshToken: false, persistSession: false } } ); // Delete the user const { error: deleteError } = await adminSupabaseClient.auth.admin.deleteUser(user.id); if (deleteError) { throw deleteError; } return new Response(JSON.stringify({ message: 'User deleted successfully.' }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 200, }); } catch (error) { // Return a detailed error with a stack trace for better debugging. return new Response(JSON.stringify({ error: error.message, stack: error.stack }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 500, }); } });