-- ============================================================================= -- Freemium F3b — /saas/usuarios (donos por tenant) + notificação aos devs -- -- ⚠️ APLICAR COMO supabase_admin (lê auth.users.email + cria trigger em -- public.subscriptions; notify_user_sistema é chamada por SECURITY DEFINER). -- -- • saas_list_account_owners(): 1 linha por tenant com o DONO (master), -- nome/slug/e-mail/plano + selo "novo" (24h). Dev-only (is_saas_admin). -- • notify_all_devs(): insere em notifications_sistema p/ cada saas_admin. -- • trigger em subscriptions: avisa os devs quando nasce/muda uma assinatura, -- com deeplink pra /saas/usuarios. -- ============================================================================= BEGIN; -- 1) Donos por tenant (dev-only) --------------------------------------------- CREATE OR REPLACE FUNCTION public.saas_list_account_owners() RETURNS TABLE ( tenant_id uuid, slug text, tenant_name text, kind text, owner_id uuid, owner_name text, owner_email text, plan_key text, created_at timestamptz, is_new boolean ) LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public','pg_temp' AS $$ BEGIN IF NOT public.is_saas_admin() THEN RAISE EXCEPTION 'forbidden' USING ERRCODE = '42501'; END IF; RETURN QUERY SELECT t.id, t.slug::text, t.name::text, t.kind::text, owner.user_id, pr.full_name::text, au.email::text, COALESCE(vas.plan_key, ps.plan_key)::text, t.created_at, (t.created_at > now() - interval '24 hours') FROM public.tenants t LEFT JOIN LATERAL ( SELECT tm.user_id FROM public.tenant_members tm WHERE tm.tenant_id = t.id AND tm.role = 'tenant_admin' AND tm.status = 'active' ORDER BY tm.created_at ASC LIMIT 1 ) owner ON true LEFT JOIN public.profiles pr ON pr.id = owner.user_id LEFT JOIN auth.users au ON au.id = owner.user_id LEFT JOIN public.v_tenant_active_subscription vas ON vas.tenant_id = t.id LEFT JOIN LATERAL ( SELECT s.plan_key FROM public.subscriptions s WHERE s.user_id = owner.user_id AND s.status = 'active' AND s.tenant_id IS NULL ORDER BY s.created_at DESC LIMIT 1 ) ps ON true ORDER BY t.created_at DESC; END $$; ALTER FUNCTION public.saas_list_account_owners() OWNER TO supabase_admin; REVOKE ALL ON FUNCTION public.saas_list_account_owners() FROM PUBLIC; GRANT EXECUTE ON FUNCTION public.saas_list_account_owners() TO authenticated, service_role; -- 2) notify_all_devs ---------------------------------------------------------- CREATE OR REPLACE FUNCTION public.notify_all_devs( p_type text, p_payload jsonb, p_ref_id uuid DEFAULT NULL, p_ref_table text DEFAULT NULL ) RETURNS int LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public','pg_temp' AS $$ DECLARE r record; n int := 0; BEGIN FOR r IN SELECT user_id FROM public.saas_admins LOOP PERFORM public.notify_user_sistema(r.user_id, p_type, p_payload, NULL, p_ref_id, p_ref_table); n := n + 1; END LOOP; RETURN n; END $$; ALTER FUNCTION public.notify_all_devs(text, jsonb, uuid, text) OWNER TO supabase_admin; -- 3) trigger em subscriptions ------------------------------------------------- CREATE OR REPLACE FUNCTION public.trg_notify_devs_subscription() RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public','pg_temp' AS $$ DECLARE v_slug text; v_title text; BEGIN -- só em INSERT ou quando o status muda IF TG_OP = 'UPDATE' AND NEW.status IS NOT DISTINCT FROM OLD.status THEN RETURN NEW; END IF; SELECT t.slug INTO v_slug FROM public.tenants t WHERE t.id = NEW.tenant_id; v_title := CASE WHEN TG_OP = 'INSERT' THEN 'Nova assinatura' ELSE 'Assinatura atualizada' END; PERFORM public.notify_all_devs( 'subscription_' || lower(TG_OP), jsonb_build_object( 'title', v_title, 'detail', NEW.plan_key || ' · ' || NEW.status || COALESCE(' · ' || v_slug, ''), 'deeplink', '/saas/usuarios', 'plan_key', NEW.plan_key, 'status', NEW.status ), NEW.id, 'subscriptions' ); RETURN NEW; END $$; ALTER FUNCTION public.trg_notify_devs_subscription() OWNER TO supabase_admin; DROP TRIGGER IF EXISTS trg_subscriptions_notify_devs ON public.subscriptions; CREATE TRIGGER trg_subscriptions_notify_devs AFTER INSERT OR UPDATE OF status ON public.subscriptions FOR EACH ROW EXECUTE FUNCTION public.trg_notify_devs_subscription(); COMMIT;