-- ============================================================================= -- Migration: 20260419000018_servicos_prontuarios_hardening -- Sessão 9 — Serviços/Prontuários scan. -- -- Resolve: -- • Serviços V#1+V#2 (CRÍTICOS): silos por owner em services/medicos/insurance_plans -- • Serviços V#3+V#4 (ALTOS): cascade silos em commitment_services/insurance_plan_services -- • Serviços V#5: WITH CHECK ausente em commitment_time_logs/determined_* -- -- Padrão validado em 5 áreas anteriores (Documentos/Financeiro/Comunicação/etc): -- SELECT tenant_member, INSERT/UPDATE/DELETE owner+saas, com WITH CHECK explícito. -- ============================================================================= -- ───────────────────────────────────────────────────────────────────────── -- V#1 services — split em 4 policies -- ----------------------------------------------------------------------------- DROP POLICY IF EXISTS "services: owner full access" ON public.services; DROP POLICY IF EXISTS "services: select" ON public.services; DROP POLICY IF EXISTS "services: insert" ON public.services; DROP POLICY IF EXISTS "services: update" ON public.services; DROP POLICY IF EXISTS "services: delete" ON public.services; CREATE POLICY "services: select" ON public.services FOR SELECT TO authenticated USING ( owner_id = auth.uid() OR public.is_saas_admin() OR tenant_id IN ( SELECT tm.tenant_id FROM public.tenant_members tm WHERE tm.user_id = auth.uid() AND tm.status = 'active' ) ); CREATE POLICY "services: insert" ON public.services FOR INSERT TO authenticated WITH CHECK ( owner_id = auth.uid() AND tenant_id IN ( SELECT tm.tenant_id FROM public.tenant_members tm WHERE tm.user_id = auth.uid() AND tm.status = 'active' ) ); CREATE POLICY "services: update" ON public.services FOR UPDATE TO authenticated USING (owner_id = auth.uid() OR public.is_saas_admin()) WITH CHECK (owner_id = auth.uid() OR public.is_saas_admin()); CREATE POLICY "services: delete" ON public.services FOR DELETE TO authenticated USING (owner_id = auth.uid() OR public.is_saas_admin()); -- ───────────────────────────────────────────────────────────────────────── -- V#2 medicos — mesmo padrão -- ----------------------------------------------------------------------------- DROP POLICY IF EXISTS "medicos: owner full access" ON public.medicos; DROP POLICY IF EXISTS "medicos: select" ON public.medicos; DROP POLICY IF EXISTS "medicos: insert" ON public.medicos; DROP POLICY IF EXISTS "medicos: update" ON public.medicos; DROP POLICY IF EXISTS "medicos: delete" ON public.medicos; CREATE POLICY "medicos: select" ON public.medicos FOR SELECT TO authenticated USING ( owner_id = auth.uid() OR public.is_saas_admin() OR tenant_id IN ( SELECT tm.tenant_id FROM public.tenant_members tm WHERE tm.user_id = auth.uid() AND tm.status = 'active' ) ); CREATE POLICY "medicos: insert" ON public.medicos FOR INSERT TO authenticated WITH CHECK ( owner_id = auth.uid() AND tenant_id IN ( SELECT tm.tenant_id FROM public.tenant_members tm WHERE tm.user_id = auth.uid() AND tm.status = 'active' ) ); CREATE POLICY "medicos: update" ON public.medicos FOR UPDATE TO authenticated USING (owner_id = auth.uid() OR public.is_saas_admin()) WITH CHECK (owner_id = auth.uid() OR public.is_saas_admin()); CREATE POLICY "medicos: delete" ON public.medicos FOR DELETE TO authenticated USING (owner_id = auth.uid() OR public.is_saas_admin()); -- ───────────────────────────────────────────────────────────────────────── -- V#1 (parte 2) insurance_plans — mesmo padrão -- ----------------------------------------------------------------------------- DROP POLICY IF EXISTS "insurance_plans: owner full access" ON public.insurance_plans; DROP POLICY IF EXISTS "insurance_plans: select" ON public.insurance_plans; DROP POLICY IF EXISTS "insurance_plans: insert" ON public.insurance_plans; DROP POLICY IF EXISTS "insurance_plans: update" ON public.insurance_plans; DROP POLICY IF EXISTS "insurance_plans: delete" ON public.insurance_plans; CREATE POLICY "insurance_plans: select" ON public.insurance_plans FOR SELECT TO authenticated USING ( owner_id = auth.uid() OR public.is_saas_admin() OR tenant_id IN ( SELECT tm.tenant_id FROM public.tenant_members tm WHERE tm.user_id = auth.uid() AND tm.status = 'active' ) ); CREATE POLICY "insurance_plans: insert" ON public.insurance_plans FOR INSERT TO authenticated WITH CHECK ( owner_id = auth.uid() AND tenant_id IN ( SELECT tm.tenant_id FROM public.tenant_members tm WHERE tm.user_id = auth.uid() AND tm.status = 'active' ) ); CREATE POLICY "insurance_plans: update" ON public.insurance_plans FOR UPDATE TO authenticated USING (owner_id = auth.uid() OR public.is_saas_admin()) WITH CHECK (owner_id = auth.uid() OR public.is_saas_admin()); CREATE POLICY "insurance_plans: delete" ON public.insurance_plans FOR DELETE TO authenticated USING (owner_id = auth.uid() OR public.is_saas_admin()); -- ───────────────────────────────────────────────────────────────────────── -- V#3 commitment_services — cascade via JOIN com services.tenant_id -- (tabela N:N sem tenant_id próprio; herda do services pai) -- ----------------------------------------------------------------------------- DROP POLICY IF EXISTS "commitment_services: owner full access" ON public.commitment_services; DROP POLICY IF EXISTS "commitment_services: tenant_member" ON public.commitment_services; CREATE POLICY "commitment_services: tenant_member" ON public.commitment_services FOR ALL TO authenticated USING ( EXISTS ( SELECT 1 FROM public.services s WHERE s.id = commitment_services.service_id AND ( s.owner_id = auth.uid() OR public.is_saas_admin() OR s.tenant_id IN ( SELECT tm.tenant_id FROM public.tenant_members tm WHERE tm.user_id = auth.uid() AND tm.status = 'active' ) ) ) ) WITH CHECK ( EXISTS ( SELECT 1 FROM public.services s WHERE s.id = commitment_services.service_id AND (s.owner_id = auth.uid() OR public.is_saas_admin()) ) ); -- ───────────────────────────────────────────────────────────────────────── -- V#4 insurance_plan_services — cascade via JOIN com insurance_plans -- ----------------------------------------------------------------------------- DROP POLICY IF EXISTS "insurance_plan_services_owner" ON public.insurance_plan_services; DROP POLICY IF EXISTS "insurance_plan_services: tenant_member" ON public.insurance_plan_services; CREATE POLICY "insurance_plan_services: tenant_member" ON public.insurance_plan_services FOR ALL TO authenticated USING ( EXISTS ( SELECT 1 FROM public.insurance_plans ip WHERE ip.id = insurance_plan_services.insurance_plan_id AND ( ip.owner_id = auth.uid() OR public.is_saas_admin() OR ip.tenant_id IN ( SELECT tm.tenant_id FROM public.tenant_members tm WHERE tm.user_id = auth.uid() AND tm.status = 'active' ) ) ) ) WITH CHECK ( EXISTS ( SELECT 1 FROM public.insurance_plans ip WHERE ip.id = insurance_plan_services.insurance_plan_id AND (ip.owner_id = auth.uid() OR public.is_saas_admin()) ) ); -- ───────────────────────────────────────────────────────────────────────── -- V#5 — adicionar WITH CHECK em INSERT das 3 tabelas que não tinham -- ----------------------------------------------------------------------------- DROP POLICY IF EXISTS ctl_insert_for_active_member ON public.commitment_time_logs; CREATE POLICY ctl_insert_for_active_member ON public.commitment_time_logs FOR INSERT TO authenticated WITH CHECK ( tenant_id IN ( SELECT tm.tenant_id FROM public.tenant_members tm WHERE tm.user_id = auth.uid() AND tm.status = 'active' ) ); DROP POLICY IF EXISTS dcf_insert_for_active_member ON public.determined_commitment_fields; CREATE POLICY dcf_insert_for_active_member ON public.determined_commitment_fields FOR INSERT TO authenticated WITH CHECK ( tenant_id IN ( SELECT tm.tenant_id FROM public.tenant_members tm WHERE tm.user_id = auth.uid() AND tm.status = 'active' ) ); DROP POLICY IF EXISTS dc_insert_for_active_member ON public.determined_commitments; CREATE POLICY dc_insert_for_active_member ON public.determined_commitments FOR INSERT TO authenticated WITH CHECK ( tenant_id IN ( SELECT tm.tenant_id FROM public.tenant_members tm WHERE tm.user_id = auth.uid() AND tm.status = 'active' ) );