-- ============================================================ -- Migration: role_permissions + role activity log extensions -- Timestamp: 20260322190000 -- ============================================================ -- 1. role_permissions table: stores per-role permission flags CREATE TABLE IF NOT EXISTS public.role_permissions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), role TEXT NOT NULL UNIQUE, can_publish_articles BOOLEAN NOT NULL DEFAULT false, can_edit_articles BOOLEAN NOT NULL DEFAULT false, can_delete_articles BOOLEAN NOT NULL DEFAULT false, can_manage_comments BOOLEAN NOT NULL DEFAULT false, can_moderate_forum BOOLEAN NOT NULL DEFAULT false, can_pin_threads BOOLEAN NOT NULL DEFAULT false, can_lock_threads BOOLEAN NOT NULL DEFAULT false, can_flag_content BOOLEAN NOT NULL DEFAULT false, can_view_analytics BOOLEAN NOT NULL DEFAULT false, can_manage_newsletter BOOLEAN NOT NULL DEFAULT false, can_invite_users BOOLEAN NOT NULL DEFAULT false, can_manage_users BOOLEAN NOT NULL DEFAULT false, updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_role_permissions_role ON public.role_permissions(role); -- 2. Enable RLS ALTER TABLE public.role_permissions ENABLE ROW LEVEL SECURITY; -- 3. RLS Policies DROP POLICY IF EXISTS "admin_manage_role_permissions" ON public.role_permissions; CREATE POLICY "admin_manage_role_permissions" ON public.role_permissions FOR ALL TO authenticated USING (public.is_admin_user()) WITH CHECK (public.is_admin_user()); DROP POLICY IF EXISTS "authenticated_read_role_permissions" ON public.role_permissions; CREATE POLICY "authenticated_read_role_permissions" ON public.role_permissions FOR SELECT TO authenticated USING (true); -- 4. Trigger for updated_at DROP TRIGGER IF EXISTS update_role_permissions_updated_at ON public.role_permissions; CREATE TRIGGER update_role_permissions_updated_at BEFORE UPDATE ON public.role_permissions FOR EACH ROW EXECUTE FUNCTION public.update_updated_at(); -- 5. Extend audit_action_type enum with role-related actions -- We add new values to the existing enum safely DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_enum WHERE enumlabel = 'role_permission_updated' AND enumtypid = (SELECT oid FROM pg_type WHERE typname = 'audit_action_type') ) THEN ALTER TYPE public.audit_action_type ADD VALUE 'role_permission_updated'; END IF; IF NOT EXISTS ( SELECT 1 FROM pg_enum WHERE enumlabel = 'role_assigned' AND enumtypid = (SELECT oid FROM pg_type WHERE typname = 'audit_action_type') ) THEN ALTER TYPE public.audit_action_type ADD VALUE 'role_assigned'; END IF; END $$; -- 6. Seed default role permissions INSERT INTO public.role_permissions (role, can_publish_articles, can_edit_articles, can_delete_articles, can_manage_comments, can_moderate_forum, can_pin_threads, can_lock_threads, can_flag_content, can_view_analytics, can_manage_newsletter, can_invite_users, can_manage_users) VALUES ('admin', true, true, true, true, true, true, true, true, true, true, true, true), ('editor', true, true, false, true, false, false, false, true, true, false, false, false), ('moderator', false, false, false, true, true, true, true, true, false, false, false, false), ('contributor', false, true, false, false, false, false, false, false, false, false, false, false), ('reader', false, false, false, false, false, false, false, false, false, false, false, false) ON CONFLICT (role) DO NOTHING;