107 lines
3.6 KiB
TypeScript
107 lines
3.6 KiB
TypeScript
// 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,
|
|
});
|
|
}
|
|
}); |