Changes
Co-authored-by: wolfoftyreso-debug <250630591+wolfoftyreso-debug@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.45.0";
|
||||
|
||||
/**
|
||||
* Verifies the caller is an authenticated admin.
|
||||
* Returns { ok: true } on success or { ok: false, response } with a
|
||||
* ready-to-return Response on failure.
|
||||
*/
|
||||
export async function requireAdmin(
|
||||
req: Request,
|
||||
corsHeaders: Record<string, string>,
|
||||
): Promise<{ ok: true; userId: string } | { ok: false; response: Response }> {
|
||||
const authHeader = req.headers.get("Authorization");
|
||||
if (!authHeader?.startsWith("Bearer ")) {
|
||||
return {
|
||||
ok: false,
|
||||
response: new Response(JSON.stringify({ error: "Unauthorized" }), {
|
||||
status: 401,
|
||||
headers: { ...corsHeaders, "Content-Type": "application/json" },
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
const supabaseUrl = Deno.env.get("SUPABASE_URL");
|
||||
const anonKey = Deno.env.get("SUPABASE_ANON_KEY");
|
||||
const serviceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY");
|
||||
if (!supabaseUrl || !anonKey || !serviceKey) {
|
||||
return {
|
||||
ok: false,
|
||||
response: new Response(JSON.stringify({ error: "Server misconfigured" }), {
|
||||
status: 500,
|
||||
headers: { ...corsHeaders, "Content-Type": "application/json" },
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
const supabase = createClient(supabaseUrl, anonKey, {
|
||||
global: { headers: { Authorization: authHeader } },
|
||||
});
|
||||
|
||||
const token = authHeader.replace("Bearer ", "");
|
||||
const { data, error } = await supabase.auth.getClaims(token);
|
||||
if (error || !data?.claims?.sub) {
|
||||
return {
|
||||
ok: false,
|
||||
response: new Response(JSON.stringify({ error: "Unauthorized" }), {
|
||||
status: 401,
|
||||
headers: { ...corsHeaders, "Content-Type": "application/json" },
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
const userId = data.claims.sub as string;
|
||||
|
||||
// Verify admin role via service-role client (bypasses RLS deterministically)
|
||||
const admin = createClient(supabaseUrl, serviceKey);
|
||||
const { data: role, error: roleErr } = await admin
|
||||
.from("user_roles")
|
||||
.select("role")
|
||||
.eq("user_id", userId)
|
||||
.eq("role", "admin")
|
||||
.maybeSingle();
|
||||
|
||||
if (roleErr || !role) {
|
||||
return {
|
||||
ok: false,
|
||||
response: new Response(JSON.stringify({ error: "Forbidden" }), {
|
||||
status: 403,
|
||||
headers: { ...corsHeaders, "Content-Type": "application/json" },
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
return { ok: true, userId };
|
||||
}
|
||||
Reference in New Issue
Block a user