-- ============================================================ -- Announcements + Comments tables -- ============================================================ -- 1. announcements table CREATE TABLE IF NOT EXISTS public.announcements ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), author_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE, title text NOT NULL, body text NOT NULL, visible_roles text[] NOT NULL DEFAULT ARRAY['admin','dispatcher','programmer','it_staff']::text[], is_template boolean NOT NULL DEFAULT false, template_id uuid REFERENCES public.announcements(id) ON DELETE SET NULL, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); ALTER TABLE public.announcements ENABLE ROW LEVEL SECURITY; ALTER TABLE public.announcements REPLICA IDENTITY FULL; -- RLS: SELECT — user can see if their role is in visible_roles OR they are the author CREATE POLICY "Announcements: select" ON public.announcements FOR SELECT USING ( author_id = auth.uid() OR EXISTS ( SELECT 1 FROM public.profiles p WHERE p.id = auth.uid() AND p.role::text = ANY(visible_roles) ) ); -- RLS: INSERT — admin, dispatcher, programmer, it_staff only CREATE POLICY "Announcements: insert" ON public.announcements FOR INSERT WITH CHECK ( EXISTS ( SELECT 1 FROM public.profiles p WHERE p.id = auth.uid() AND p.role IN ('admin', 'dispatcher', 'programmer', 'it_staff') ) ); -- RLS: UPDATE — only the author or admin CREATE POLICY "Announcements: update" ON public.announcements FOR UPDATE USING ( author_id = auth.uid() OR EXISTS ( SELECT 1 FROM public.profiles p WHERE p.id = auth.uid() AND p.role = 'admin' ) ); -- RLS: DELETE — only the author or admin CREATE POLICY "Announcements: delete" ON public.announcements FOR DELETE USING ( author_id = auth.uid() OR EXISTS ( SELECT 1 FROM public.profiles p WHERE p.id = auth.uid() AND p.role = 'admin' ) ); -- Index for efficient queries CREATE INDEX IF NOT EXISTS idx_announcements_created_at ON public.announcements (created_at DESC); CREATE INDEX IF NOT EXISTS idx_announcements_visible_roles ON public.announcements USING GIN (visible_roles); -- 2. announcement_comments table CREATE TABLE IF NOT EXISTS public.announcement_comments ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), announcement_id uuid NOT NULL REFERENCES public.announcements(id) ON DELETE CASCADE, author_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE, body text NOT NULL, created_at timestamptz NOT NULL DEFAULT now() ); ALTER TABLE public.announcement_comments ENABLE ROW LEVEL SECURITY; ALTER TABLE public.announcement_comments REPLICA IDENTITY FULL; -- RLS: SELECT — can read comments if user can see the parent announcement CREATE POLICY "Announcement comments: select" ON public.announcement_comments FOR SELECT USING ( EXISTS ( SELECT 1 FROM public.announcements a WHERE a.id = announcement_id AND ( a.author_id = auth.uid() OR EXISTS ( SELECT 1 FROM public.profiles p WHERE p.id = auth.uid() AND p.role::text = ANY(a.visible_roles) ) ) ) ); -- RLS: INSERT — any authenticated user who can see the announcement CREATE POLICY "Announcement comments: insert" ON public.announcement_comments FOR INSERT WITH CHECK ( author_id = auth.uid() AND EXISTS ( SELECT 1 FROM public.announcements a WHERE a.id = announcement_id AND ( a.author_id = auth.uid() OR EXISTS ( SELECT 1 FROM public.profiles p WHERE p.id = auth.uid() AND p.role::text = ANY(a.visible_roles) ) ) ) ); -- RLS: DELETE — only the comment author or admin CREATE POLICY "Announcement comments: delete" ON public.announcement_comments FOR DELETE USING ( author_id = auth.uid() OR EXISTS ( SELECT 1 FROM public.profiles p WHERE p.id = auth.uid() AND p.role = 'admin' ) ); -- Index for efficient comment lookups CREATE INDEX IF NOT EXISTS idx_announcement_comments_announcement_id ON public.announcement_comments (announcement_id, created_at); -- 3. Extend notifications table with announcement_id FK ALTER TABLE public.notifications ADD COLUMN IF NOT EXISTS announcement_id uuid REFERENCES public.announcements(id) ON DELETE CASCADE; -- 4. Enable realtime for both tables ALTER PUBLICATION supabase_realtime ADD TABLE public.announcements; ALTER PUBLICATION supabase_realtime ADD TABLE public.announcement_comments;