from __future__ import annotations from types import SimpleNamespace from unittest.mock import AsyncMock import pytest from langbot.pkg.workspace.invitation_delivery import ( InvitationDeliveryResult, InvitationDeliveryService, ) pytestmark = pytest.mark.asyncio def _app(config: dict) -> SimpleNamespace: return SimpleNamespace( instance_config=SimpleNamespace(data=config), logger=SimpleNamespace(warning=lambda *args, **kwargs: None), ) async def test_link_only_delivery_builds_public_web_link_without_secret_capability(): service = InvitationDeliveryService( _app( { 'api': { 'webui_url': 'https://public.langbot.example/', 'webhook_prefix': 'http://internal:5300', } } ) ) assert service.build_invitation_link('lbi_secret') == ( 'https://public.langbot.example/invitations/accept#token=lbi_secret' ) assert service.capability() == {'enabled': False, 'provider': None} result = await service.deliver_invitation( recipient_email='member@example.com', workspace_name='Workspace', invitation_link='https://public.langbot.example/invitations/accept#token=lbi_secret', ) assert result == InvitationDeliveryResult(status='link_only', provider=None) async def test_configured_provider_failure_returns_failed_without_raising(): service = InvitationDeliveryService( _app( { 'workspace': { 'invitations': { 'email': { 'provider': 'resend', 'from': 'LangBot ', 'resend': {'api_key': 'resend-secret'}, } } } } ) ) service._send_resend = AsyncMock(return_value=False) assert service.capability() == {'enabled': True, 'provider': 'resend'} result = await service.deliver_invitation( recipient_email='member@example.com', workspace_name='Workspace', invitation_link='https://public.langbot.example/invitations/accept#token=lbi_secret', ) assert result == InvitationDeliveryResult(status='failed', provider='resend') service._send_resend.assert_awaited_once() async def test_environment_mapping_enables_provider_without_leaking_secret(monkeypatch): monkeypatch.setenv('WORKSPACE__INVITATIONS__PUBLIC_WEB_URL', 'https://env.langbot.example/') monkeypatch.setenv('WORKSPACE__INVITATIONS__EMAIL__PROVIDER', 'smtp') monkeypatch.setenv('WORKSPACE__INVITATIONS__EMAIL__FROM', 'LangBot ') monkeypatch.setenv('WORKSPACE__INVITATIONS__EMAIL__SMTP__HOST', 'smtp.example.com') monkeypatch.setenv('WORKSPACE__INVITATIONS__EMAIL__SMTP__PASSWORD', 'smtp-secret') service = InvitationDeliveryService(_app({'api': {'webui_url': 'https://config.example'}})) assert service.build_invitation_link('lbi_secret') == ( 'https://env.langbot.example/invitations/accept#token=lbi_secret' ) assert service.capability() == {'enabled': True, 'provider': 'smtp'}