1920495d9b
Co-authored-by: wolfoftyreso-debug <250630591+wolfoftyreso-debug@users.noreply.github.com>
29 lines
1.1 KiB
PL/PgSQL
29 lines
1.1 KiB
PL/PgSQL
-- Restrict direct execution of SECURITY DEFINER function has_role.
|
|
-- Switching to SECURITY INVOKER: when called as auth.uid() the user_roles
|
|
-- RLS policy already lets a user see (only) their own role rows, so
|
|
-- has_role(auth.uid(), 'admin') still returns correctly.
|
|
-- We also revoke EXECUTE from anon/public so the function cannot be
|
|
-- invoked directly from the Data API.
|
|
|
|
CREATE OR REPLACE FUNCTION public.has_role(_user_id uuid, _role app_role)
|
|
RETURNS boolean
|
|
LANGUAGE sql
|
|
STABLE
|
|
SECURITY INVOKER
|
|
SET search_path = public
|
|
AS $$
|
|
SELECT EXISTS (
|
|
SELECT 1
|
|
FROM public.user_roles
|
|
WHERE user_id = _user_id
|
|
AND role = _role
|
|
)
|
|
$$;
|
|
|
|
REVOKE EXECUTE ON FUNCTION public.has_role(uuid, app_role) FROM PUBLIC;
|
|
REVOKE EXECUTE ON FUNCTION public.has_role(uuid, app_role) FROM anon;
|
|
-- authenticated retains EXECUTE so RLS policies referencing has_role
|
|
-- continue to work; the function itself is now SECURITY INVOKER so it
|
|
-- cannot be used to bypass RLS.
|
|
GRANT EXECUTE ON FUNCTION public.has_role(uuid, app_role) TO authenticated;
|
|
GRANT EXECUTE ON FUNCTION public.has_role(uuid, app_role) TO service_role; |