Demo, all content is generated
Question

My admin page is just hidden from the menu, is that protection?

Solved · 1159 views · asked by mina_j · edited

In my Lovable app the Admin link only shows if my email is logged in. But if I log in as a test user and type /admin in the address bar, the admin page opens and shows all orders. Lovable says 'the admin link is only visible to admins' like that's the solution.

What I’ve tried

Asked Lovable to add a redirect in the admin page if not admin. Now it flashes the page and then redirects, and I think the data still loads.

Comment
Does the admin page read from Supabase directly in the browser? Then check the Network tab as a test user. amir_h · edited

3 answers

Marked as helpful by the asker
amir_h · edited

Hiding a link is decoration, not security. And a redirect in the page component runs after the data is already fetched, in the user's own browser. Your instinct is correct: the data still loads, check the Network tab.

In a Lovable app (React + Supabase, no server of its own) the real lock is RLS on the tables. The page can do whatever it wants; the database must refuse to return other people's orders.

-- admins table only you can write to
create table admins (user_id uuid primary key references auth.users);
alter table admins enable row level security;

create policy "admins read all orders" on orders for select
using (exists (select 1 from admins where user_id = auth.uid()));

create policy "users read own orders" on orders for select
using (user_id = auth.uid());

Then the /admin page for a normal user shows only their own orders or nothing. Keep the redirect for nicer UX.

Comment
Network tab showed ALL orders for the test user. Added the policies (Lovable did it when I pasted this). Now test user sees only their own. Scary. mina_j · edited
Checked mine after reading this. Same problem. Fixed. Thanks both. sipho_m · edited
chidi_eze · edited

And for admin actions (refund, delete user, change plan): those must go through server code (Edge Function) that checks the admin table again. Never let the browser call something with the service role directly because 'only admins see the button'.

Comment
pixelpaulo · edited

Don't forget the other tables the admin page touches (customers, messages, etc). RLS per table, every table.

Comment