fix: force mailu sync before vaultwarden

This commit is contained in:
Brad Stein 2026-01-19 23:27:10 -03:00
parent e8007fcb63
commit 1dabd78921
4 changed files with 52 additions and 5 deletions

View File

@ -313,7 +313,7 @@ class ProvisioningManager:
self._upsert_task(conn, request_code, "mailu_sync", "ok", detail) self._upsert_task(conn, request_code, "mailu_sync", "ok", detail)
self._record_task(request_code, "mailu_sync", "ok", detail, start) self._record_task(request_code, "mailu_sync", "ok", detail, start)
else: else:
mailu.sync(reason="ariadne_access_approve") mailu.sync(reason="ariadne_access_approve", force=True)
self._upsert_task(conn, request_code, "mailu_sync", "ok", None) self._upsert_task(conn, request_code, "mailu_sync", "ok", None)
self._record_task(request_code, "mailu_sync", "ok", None, start) self._record_task(request_code, "mailu_sync", "ok", None, start)
except Exception as exc: except Exception as exc:
@ -401,7 +401,12 @@ class ProvisioningManager:
start = datetime.now(timezone.utc) start = datetime.now(timezone.utc)
try: try:
if not mailu.wait_for_mailbox(mailu_email, settings.mailu_mailbox_wait_timeout_sec): if not mailu.wait_for_mailbox(mailu_email, settings.mailu_mailbox_wait_timeout_sec):
raise RuntimeError("mailbox not ready") try:
mailu.sync(reason="ariadne_vaultwarden_retry", force=True)
except Exception:
pass
if not mailu.wait_for_mailbox(mailu_email, settings.mailu_mailbox_wait_timeout_sec):
raise RuntimeError("mailbox not ready")
result = vaultwarden.invite_user(mailu_email) result = vaultwarden.invite_user(mailu_email)
if result.ok: if result.ok:

View File

@ -39,13 +39,13 @@ class MailuService:
time.sleep(2) time.sleep(2)
return False return False
def sync(self, reason: str) -> None: def sync(self, reason: str, force: bool = False) -> None:
if not settings.mailu_sync_url: if not settings.mailu_sync_url:
return return
with httpx.Client(timeout=settings.mailu_sync_wait_timeout_sec) as client: with httpx.Client(timeout=settings.mailu_sync_wait_timeout_sec) as client:
resp = client.post( resp = client.post(
settings.mailu_sync_url, settings.mailu_sync_url,
json={"ts": int(time.time()), "wait": True, "reason": reason}, json={"ts": int(time.time()), "wait": True, "reason": reason, "force": force},
) )
if resp.status_code != 200: if resp.status_code != 200:
raise RuntimeError(f"mailu sync failed status={resp.status_code}") raise RuntimeError(f"mailu sync failed status={resp.status_code}")

View File

@ -107,7 +107,7 @@ def test_provisioning_filters_flag_groups(monkeypatch) -> None:
admin = DummyAdmin() admin = DummyAdmin()
monkeypatch.setattr(prov, "keycloak_admin", admin) monkeypatch.setattr(prov, "keycloak_admin", admin)
monkeypatch.setattr(prov.mailu, "sync", lambda reason: None) monkeypatch.setattr(prov.mailu, "sync", lambda reason, force=False: None)
monkeypatch.setattr(prov.mailu, "wait_for_mailbox", lambda email, timeout: True) monkeypatch.setattr(prov.mailu, "wait_for_mailbox", lambda email, timeout: True)
monkeypatch.setattr(prov.nextcloud, "sync_mail", lambda username, wait=True: {"status": "ok"}) monkeypatch.setattr(prov.nextcloud, "sync_mail", lambda username, wait=True: {"status": "ok"})
monkeypatch.setattr(prov.wger, "sync_user", lambda username, email, password, wait=True: {"status": "ok"}) monkeypatch.setattr(prov.wger, "sync_user", lambda username, email, password, wait=True: {"status": "ok"})

View File

@ -5,6 +5,7 @@ import types
import pytest import pytest
from ariadne.services.firefly import FireflyService from ariadne.services.firefly import FireflyService
from ariadne.services.mailu import MailuService
from ariadne.services.nextcloud import NextcloudService from ariadne.services.nextcloud import NextcloudService
from ariadne.services.wger import WgerService from ariadne.services.wger import WgerService
@ -24,6 +25,24 @@ class DummySpawner:
return {"job": "test", "status": "queued"} return {"job": "test", "status": "queued"}
class DummyClient:
def __init__(self):
self.url = ""
self.payload = None
self.status_code = 200
def __enter__(self):
return self
def __exit__(self, exc_type, exc, tb):
return False
def post(self, url, json=None):
self.url = url
self.payload = json
return types.SimpleNamespace(status_code=self.status_code)
def test_nextcloud_sync_mail_builds_env(monkeypatch) -> None: def test_nextcloud_sync_mail_builds_env(monkeypatch) -> None:
dummy = types.SimpleNamespace( dummy = types.SimpleNamespace(
nextcloud_namespace="nextcloud", nextcloud_namespace="nextcloud",
@ -88,6 +107,29 @@ def test_firefly_sync_user_env(monkeypatch) -> None:
assert env_map["FIREFLY_USER_EMAIL"] == "alice@bstein.dev" assert env_map["FIREFLY_USER_EMAIL"] == "alice@bstein.dev"
def test_mailu_sync_includes_force(monkeypatch) -> None:
dummy_settings = types.SimpleNamespace(
mailu_sync_url="http://mailu",
mailu_sync_wait_timeout_sec=10.0,
mailu_db_host="localhost",
mailu_db_port=5432,
mailu_db_name="mailu",
mailu_db_user="mailu",
mailu_db_password="secret",
)
client = DummyClient()
monkeypatch.setattr("ariadne.services.mailu.settings", dummy_settings)
monkeypatch.setattr("ariadne.services.mailu.httpx.Client", lambda *args, **kwargs: client)
svc = MailuService()
svc.sync("provision", force=True)
assert client.url == "http://mailu"
assert client.payload["wait"] is True
assert client.payload["force"] is True
def test_nextcloud_missing_config(monkeypatch) -> None: def test_nextcloud_missing_config(monkeypatch) -> None:
dummy = types.SimpleNamespace( dummy = types.SimpleNamespace(
nextcloud_namespace="", nextcloud_namespace="",