-- ============================================================================ -- Compliance CFP #7 — RPC list_my_signatures (portal do paciente) -- ---------------------------------------------------------------------------- -- Retorna as solicitações de assinatura do paciente logado (auth.uid() -- associado a patients.user_id). SECURITY DEFINER pra bypassar a RLS de -- document_signatures (que hoje só libera pra tenant_members). -- -- Cada item já vem com o share_link.token associado, pra que o portal -- aponte direto pra /shared/document/:token onde o usuário vai assinar. -- O link público é gerado quando o terapeuta solicita a assinatura. -- ============================================================================ BEGIN; CREATE OR REPLACE FUNCTION public.list_my_signatures( p_status text[] DEFAULT NULL ) RETURNS TABLE ( signature_id uuid, documento_id uuid, tenant_id uuid, signatario_tipo text, status text, ordem smallint, assinado_em timestamptz, criado_em timestamptz, -- Documento nome_original text, tipo_documento text, mime_type text, -- Share link (primeiro válido encontrado pro doc) share_token text, share_expira_em timestamptz ) LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$ DECLARE v_uid uuid; BEGIN v_uid := auth.uid(); IF v_uid IS NULL THEN RAISE EXCEPTION 'Sessão inválida' USING ERRCODE = '28000'; END IF; RETURN QUERY SELECT s.id AS signature_id, s.documento_id AS documento_id, s.tenant_id AS tenant_id, s.signatario_tipo AS signatario_tipo, s.status AS status, s.ordem AS ordem, s.assinado_em AS assinado_em, s.criado_em AS criado_em, d.nome_original AS nome_original, d.tipo_documento AS tipo_documento, d.mime_type AS mime_type, sl.token AS share_token, sl.expira_em AS share_expira_em FROM public.document_signatures s JOIN public.documents d ON d.id = s.documento_id AND d.deleted_at IS NULL LEFT JOIN LATERAL ( SELECT token, expira_em FROM public.document_share_links WHERE documento_id = d.id AND ativo = true AND expira_em > now() AND usos < usos_max ORDER BY criado_em DESC LIMIT 1 ) sl ON true WHERE ( -- signatario_id direto (quando registrado) s.signatario_id = v_uid OR -- Fallback: paciente pelo email (quando signatario_id veio NULL) s.signatario_email = (SELECT email FROM auth.users WHERE id = v_uid) OR -- Fallback: paciente pelo patient_id (documents.patient_id -> patients.user_id) d.patient_id IN (SELECT p.id FROM public.patients p WHERE p.user_id = v_uid) ) AND (p_status IS NULL OR s.status = ANY (p_status)) ORDER BY CASE s.status WHEN 'pendente' THEN 0 WHEN 'enviado' THEN 1 WHEN 'assinado' THEN 2 WHEN 'recusado' THEN 3 WHEN 'expirado' THEN 4 ELSE 99 END, s.criado_em DESC; END; $$; COMMENT ON FUNCTION public.list_my_signatures(text[]) IS 'Lista signatures do paciente logado (auth.uid()) cruzando por signatario_id, email ou patient.user_id. Inclui share_token pra link de assinatura.'; GRANT EXECUTE ON FUNCTION public.list_my_signatures(text[]) TO authenticated; COMMIT;