Spaces:
Sleeping
Sleeping
fix(rls): infinite recursion in profiles policy — use SECURITY DEFINER is_admin() function
Browse files- web/lib/supabase/schema.sql +18 -7
web/lib/supabase/schema.sql
CHANGED
|
@@ -128,24 +128,35 @@ ALTER TABLE public.api_keys ENABLE ROW LEVEL SECURITY;
|
|
| 128 |
ALTER TABLE public.custom_rules ENABLE ROW LEVEL SECURITY;
|
| 129 |
ALTER TABLE public.admin_logs ENABLE ROW LEVEL SECURITY;
|
| 130 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 131 |
-- Profiles
|
| 132 |
CREATE POLICY "Users see own profile" ON public.profiles FOR SELECT USING (auth.uid() = id);
|
| 133 |
CREATE POLICY "Users update own profile" ON public.profiles FOR UPDATE USING (auth.uid() = id);
|
| 134 |
-
CREATE POLICY "Admins read all profiles" ON public.profiles FOR SELECT USING (
|
| 135 |
-
CREATE POLICY "Admins update all profiles" ON public.profiles FOR UPDATE USING (
|
| 136 |
|
| 137 |
-- Analyses
|
| 138 |
CREATE POLICY "Users see own analyses" ON public.analyses FOR SELECT
|
| 139 |
USING (auth.uid() = user_id OR team_id IN (SELECT team_id FROM public.profiles WHERE id = auth.uid()));
|
| 140 |
CREATE POLICY "Users insert analyses" ON public.analyses FOR INSERT WITH CHECK (auth.uid() = user_id);
|
| 141 |
CREATE POLICY "Users delete own analyses" ON public.analyses FOR DELETE USING (auth.uid() = user_id);
|
| 142 |
-
CREATE POLICY "Admins read all analyses" ON public.analyses FOR SELECT USING (
|
| 143 |
|
| 144 |
-- Teams
|
| 145 |
CREATE POLICY "Team members can view" ON public.teams FOR SELECT
|
| 146 |
USING (id IN (SELECT team_id FROM public.profiles WHERE id = auth.uid()) OR owner_id = auth.uid());
|
| 147 |
CREATE POLICY "Owner can update team" ON public.teams FOR UPDATE USING (owner_id = auth.uid());
|
| 148 |
-
CREATE POLICY "Admins read all teams" ON public.teams FOR SELECT USING (
|
| 149 |
|
| 150 |
-- Team invites
|
| 151 |
CREATE POLICY "Members see team invites" ON public.team_invites FOR SELECT
|
|
@@ -156,17 +167,17 @@ CREATE POLICY "Users can invite" ON public.team_invites FOR INSERT WITH CHECK (i
|
|
| 156 |
CREATE POLICY "Users see own API keys" ON public.api_keys FOR SELECT
|
| 157 |
USING (user_id = auth.uid() OR team_id IN (SELECT team_id FROM public.profiles WHERE id = auth.uid()));
|
| 158 |
CREATE POLICY "Users manage own API keys" ON public.api_keys FOR ALL USING (user_id = auth.uid());
|
| 159 |
-
CREATE POLICY "Admins read all api_keys" ON public.api_keys FOR SELECT USING (
|
| 160 |
|
| 161 |
-- Custom Rules
|
| 162 |
CREATE POLICY "Users see own rules" ON public.custom_rules FOR SELECT
|
| 163 |
USING (user_id = auth.uid() OR team_id IN (SELECT team_id FROM public.profiles WHERE id = auth.uid()));
|
| 164 |
CREATE POLICY "Users manage own rules" ON public.custom_rules FOR ALL USING (user_id = auth.uid());
|
| 165 |
-
CREATE POLICY "Admins read all rules" ON public.custom_rules FOR SELECT USING (
|
| 166 |
|
| 167 |
-- Admin Logs
|
| 168 |
CREATE POLICY "Admins manage logs" ON public.admin_logs FOR ALL
|
| 169 |
-
USING (
|
| 170 |
|
| 171 |
-- ─── Auto-create profile on signup ───
|
| 172 |
CREATE OR REPLACE FUNCTION public.handle_new_user()
|
|
|
|
| 128 |
ALTER TABLE public.custom_rules ENABLE ROW LEVEL SECURITY;
|
| 129 |
ALTER TABLE public.admin_logs ENABLE ROW LEVEL SECURITY;
|
| 130 |
|
| 131 |
+
-- ─── FIX v4.3: SECURITY DEFINER function to check admin role ───
|
| 132 |
+
-- Querying profiles FROM a profiles policy causes infinite recursion (42P17).
|
| 133 |
+
-- SECURITY DEFINER bypasses RLS, breaking the cycle.
|
| 134 |
+
CREATE OR REPLACE FUNCTION public.is_admin()
|
| 135 |
+
RETURNS boolean AS $$
|
| 136 |
+
SELECT EXISTS (
|
| 137 |
+
SELECT 1 FROM public.profiles
|
| 138 |
+
WHERE id = auth.uid() AND role = 'admin'
|
| 139 |
+
);
|
| 140 |
+
$$ LANGUAGE sql SECURITY DEFINER STABLE;
|
| 141 |
+
|
| 142 |
-- Profiles
|
| 143 |
CREATE POLICY "Users see own profile" ON public.profiles FOR SELECT USING (auth.uid() = id);
|
| 144 |
CREATE POLICY "Users update own profile" ON public.profiles FOR UPDATE USING (auth.uid() = id);
|
| 145 |
+
CREATE POLICY "Admins read all profiles" ON public.profiles FOR SELECT USING (public.is_admin());
|
| 146 |
+
CREATE POLICY "Admins update all profiles" ON public.profiles FOR UPDATE USING (public.is_admin());
|
| 147 |
|
| 148 |
-- Analyses
|
| 149 |
CREATE POLICY "Users see own analyses" ON public.analyses FOR SELECT
|
| 150 |
USING (auth.uid() = user_id OR team_id IN (SELECT team_id FROM public.profiles WHERE id = auth.uid()));
|
| 151 |
CREATE POLICY "Users insert analyses" ON public.analyses FOR INSERT WITH CHECK (auth.uid() = user_id);
|
| 152 |
CREATE POLICY "Users delete own analyses" ON public.analyses FOR DELETE USING (auth.uid() = user_id);
|
| 153 |
+
CREATE POLICY "Admins read all analyses" ON public.analyses FOR SELECT USING (public.is_admin());
|
| 154 |
|
| 155 |
-- Teams
|
| 156 |
CREATE POLICY "Team members can view" ON public.teams FOR SELECT
|
| 157 |
USING (id IN (SELECT team_id FROM public.profiles WHERE id = auth.uid()) OR owner_id = auth.uid());
|
| 158 |
CREATE POLICY "Owner can update team" ON public.teams FOR UPDATE USING (owner_id = auth.uid());
|
| 159 |
+
CREATE POLICY "Admins read all teams" ON public.teams FOR SELECT USING (public.is_admin());
|
| 160 |
|
| 161 |
-- Team invites
|
| 162 |
CREATE POLICY "Members see team invites" ON public.team_invites FOR SELECT
|
|
|
|
| 167 |
CREATE POLICY "Users see own API keys" ON public.api_keys FOR SELECT
|
| 168 |
USING (user_id = auth.uid() OR team_id IN (SELECT team_id FROM public.profiles WHERE id = auth.uid()));
|
| 169 |
CREATE POLICY "Users manage own API keys" ON public.api_keys FOR ALL USING (user_id = auth.uid());
|
| 170 |
+
CREATE POLICY "Admins read all api_keys" ON public.api_keys FOR SELECT USING (public.is_admin());
|
| 171 |
|
| 172 |
-- Custom Rules
|
| 173 |
CREATE POLICY "Users see own rules" ON public.custom_rules FOR SELECT
|
| 174 |
USING (user_id = auth.uid() OR team_id IN (SELECT team_id FROM public.profiles WHERE id = auth.uid()));
|
| 175 |
CREATE POLICY "Users manage own rules" ON public.custom_rules FOR ALL USING (user_id = auth.uid());
|
| 176 |
+
CREATE POLICY "Admins read all rules" ON public.custom_rules FOR SELECT USING (public.is_admin());
|
| 177 |
|
| 178 |
-- Admin Logs
|
| 179 |
CREATE POLICY "Admins manage logs" ON public.admin_logs FOR ALL
|
| 180 |
+
USING (public.is_admin());
|
| 181 |
|
| 182 |
-- ─── Auto-create profile on signup ───
|
| 183 |
CREATE OR REPLACE FUNCTION public.handle_new_user()
|