Fix: Teams RLS 403 and insertion violation (Phase 8 Governance)
Browse files
database/fix_teams_rls_governance.sql
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- Fix for 403 Forbidden on Teams access (Phase 8 Governance)
|
| 2 |
+
-- This migration resolves potential RLS recursion and ensures proper grants.
|
| 3 |
+
|
| 4 |
+
-- 1. Ensure table permissions are granted to authenticated users
|
| 5 |
+
GRANT SELECT, INSERT, UPDATE, DELETE ON public.teams TO authenticated;
|
| 6 |
+
GRANT SELECT, INSERT, UPDATE, DELETE ON public.team_members TO authenticated;
|
| 7 |
+
GRANT USAGE ON SCHEMA public TO authenticated;
|
| 8 |
+
|
| 9 |
+
-- 2. Drop existing problematic policies
|
| 10 |
+
DROP POLICY IF EXISTS "Teams are readable by members" ON public.teams;
|
| 11 |
+
DROP POLICY IF EXISTS "Team members are readable by team" ON public.team_members;
|
| 12 |
+
|
| 13 |
+
-- 3. Re-implement Teams Select Policy using a non-recursive direct check
|
| 14 |
+
-- Users can see teams they belong to or teams they created.
|
| 15 |
+
CREATE POLICY "Teams are readable by members" ON public.teams
|
| 16 |
+
FOR SELECT TO authenticated
|
| 17 |
+
USING (
|
| 18 |
+
created_by = auth.uid()
|
| 19 |
+
OR EXISTS (
|
| 20 |
+
SELECT 1 FROM public.team_members
|
| 21 |
+
WHERE team_members.team_id = id
|
| 22 |
+
AND team_members.user_id = auth.uid()
|
| 23 |
+
)
|
| 24 |
+
);
|
| 25 |
+
|
| 26 |
+
-- 4. Re-implement Team Members Select Policy
|
| 27 |
+
-- Users can see membership details of teams they are part of.
|
| 28 |
+
CREATE POLICY "Team members are readable by team" ON public.team_members
|
| 29 |
+
FOR SELECT TO authenticated
|
| 30 |
+
USING (
|
| 31 |
+
EXISTS (
|
| 32 |
+
SELECT 1 FROM public.team_members AS m
|
| 33 |
+
WHERE m.team_id = team_members.team_id
|
| 34 |
+
AND m.user_id = auth.uid()
|
| 35 |
+
)
|
| 36 |
+
);
|
| 37 |
+
|
| 38 |
+
-- 5. Ensure the is_team_member function is robust and uses search_path
|
| 39 |
+
CREATE OR REPLACE FUNCTION public.is_team_member(target_team_id UUID)
|
| 40 |
+
RETURNS BOOLEAN AS $$
|
| 41 |
+
BEGIN
|
| 42 |
+
RETURN EXISTS (
|
| 43 |
+
SELECT 1
|
| 44 |
+
FROM public.team_members
|
| 45 |
+
WHERE team_id = target_team_id
|
| 46 |
+
AND user_id = auth.uid()
|
| 47 |
+
);
|
| 48 |
+
END;
|
| 49 |
+
$$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = public;
|
| 50 |
+
|
| 51 |
+
-- 6. Reload schema for PostgREST
|
| 52 |
+
NOTIFY pgrst, 'reload schema';
|