i've implemented an insert policy checking auth_role with a function, this worked with other projects that i've made but since yesterday if i do a request inserting another row into the table question_types
, returns 403 error
.
Fun facts:
user_roles table
-> table columns: user_id, role_id
403 error
even if the user_role is correct.user_id
: SELECT 1
FROM user_roles ur
JOIN roles r ON ur.role_id = r.id
WHERE ur.user_id = <USER_ID> AND r.name = 'advisor'
create table public.question_types (
id integer primary key generated always as identity,
question_id integer references public.questions(id) on delete cascade,
evaluation_type_id integer references public.evaluation_types(id) on delete cascade,
created_at timestamp with time zone default now(),
updated_at timestamp with time zone default now()
);
CREATE OR REPLACE FUNCTION auth_role(role_name text)
RETURNS boolean LANGUAGE plpgsql AS $$
BEGIN
RETURN EXISTS(
SELECT 1
FROM user_roles ur
JOIN roles r ON ur.role_id = r.id
WHERE ur.user_id = auth.uid() AND r.name = role_name
);
END;
$$;
alter table public.question_types
enable row level security;
CREATE POLICY "Insert can be done by authenticated users." ON public.question_types
FOR INSERT TO authenticated
WITH CHECK (auth_role('superadmin'));
CREATE POLICY "Insert can be done by authenticated users advisor." ON public.question_types
FOR INSERT TO authenticated
WITH CHECK (auth_role('advisor'));
i have missed to put a select policy to authenticated users on roles table.
CREATE POLICY "Only authenticated can view the roles."
ON public.roles
FOR SELECT TO authenticated
USING(true);
The bug was related to the last RLS policy created:
CREATE POLICY "Only authenticated can view the roles."
ON public.roles
FOR SELECT TO authenticated
USING(auth_role('superadmin'));
So i guess that when the user was trying to insert a new row question_types
the last flow checked the auth_role before insert, checking roles table
but, the RLS from that table did not allow to select any row from roles table
if the user wasn't superadmin
SELECT 1
FROM user_roles ur
JOIN roles r ON ur.role_id = r.id
WHERE ur.user_id = auth.uid() AND r.name = role_name