Files
ServerKit/backend/tests/test_email_provider_usage_flags.py
Juan DenisandClaude Opus 4.8 45e01f8731 refactor(unify): §6 Phase C6a — email provider usage flags
Foundation for folding the single-row email_relay_config into the multi-row
EmailProviderConnection so one table drives notifications and the Postfix relay.

- EmailProviderConnection gains uses_notifications (default true), uses_relay
  (default false), relay_priority (default 0); surfaced in to_dict.
- Notification selection (default_provider) now restricted to uses_notifications
  rows, so relay-only connections are never used to send notifications.
- New relay_provider() selects the active SMTP connection by relay_priority.
- add_provider() accepts the flags; uses_relay honored only for provider=smtp
  (API providers can't be a Postfix smarthost).
- Migration 038 (idempotent additive columns).

Additive — existing providers default to uses_notifications=true / no relay.
Verified: 4 new tests + notification-bus suite pass (24 passed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 14:32:41 -04:00

62 lines
2.5 KiB
Python

"""§6 Phase C6a — email provider usage flags.
One EmailProviderConnection can drive the Notification Bus and/or the Postfix
relay. Notification selection ignores relay-only rows; a relay selector picks
the flagged SMTP connection by priority.
"""
from app.models.email_provider import EmailProviderConnection
from app.notifications.providers import EmailProviderService
def test_usage_flags_default_and_serialize(app):
with app.app_context():
p = EmailProviderService.add_provider({
'provider': 'smtp', 'name': 'Main SMTP',
'host': 'smtp.example.com', 'port': 587, 'username': 'u', 'password': 'pw',
})
d = p.to_dict()
assert d['uses_notifications'] is True
assert d['uses_relay'] is False
assert d['relay_priority'] == 0
def test_default_provider_ignores_relay_only(app):
with app.app_context():
# A relay-only row must never be chosen for notifications.
EmailProviderService.add_provider({
'provider': 'smtp', 'name': 'Relay only',
'host': 'relay.example.com', 'port': 587, 'username': 'u', 'password': 'pw',
'uses_notifications': False, 'uses_relay': True, 'is_default': True,
})
assert EmailProviderService.default_provider() is None
notif = EmailProviderService.add_provider({
'provider': 'sendgrid', 'name': 'SG', 'api_key': 'sg-key',
})
chosen = EmailProviderService.default_provider()
assert chosen is not None and chosen.id == notif.id
def test_relay_provider_selection_by_priority(app):
with app.app_context():
low = EmailProviderService.add_provider({
'provider': 'smtp', 'name': 'low', 'host': 'a', 'username': 'u', 'password': 'p',
'uses_relay': True, 'relay_priority': 1, 'uses_notifications': False,
})
high = EmailProviderService.add_provider({
'provider': 'smtp', 'name': 'high', 'host': 'b', 'username': 'u', 'password': 'p',
'uses_relay': True, 'relay_priority': 5, 'uses_notifications': False,
})
chosen = EmailProviderService.relay_provider()
assert chosen.id == high.id
assert low.id != high.id
def test_api_provider_cannot_be_relay(app):
with app.app_context():
# uses_relay requested on a non-SMTP provider is ignored.
p = EmailProviderService.add_provider({
'provider': 'sendgrid', 'name': 'SG', 'api_key': 'k', 'uses_relay': True,
})
assert p.uses_relay is False