vaultwarden: make cred sync idempotent
This commit is contained in:
parent
12348258fa
commit
51a733096f
@ -27,7 +27,9 @@ def _iter_keycloak_users(page_size: int = 200) -> Iterable[dict[str, Any]]:
|
||||
first = 0
|
||||
while True:
|
||||
headers = client.headers()
|
||||
params = {"first": str(first), "max": str(page_size)}
|
||||
# We need attributes for idempotency (vaultwarden_status/vaultwarden_email). Keycloak defaults to a
|
||||
# brief representation which may omit these.
|
||||
params = {"first": str(first), "max": str(page_size), "briefRepresentation": "false"}
|
||||
with httpx.Client(timeout=settings.HTTP_CHECK_TIMEOUT_SEC) as http:
|
||||
resp = http.get(url, params=params, headers=headers)
|
||||
resp.raise_for_status()
|
||||
@ -79,7 +81,9 @@ def _vaultwarden_email_for_user(user: dict[str, Any]) -> str:
|
||||
if email and email.lower().endswith(f"@{settings.MAILU_DOMAIN.lower()}"):
|
||||
return email
|
||||
|
||||
return f"{username}@{settings.MAILU_DOMAIN}"
|
||||
# Don't guess an internal mailbox address until Mailu sync has run and stored mailu_email.
|
||||
# This avoids spamming Vaultwarden invites that can never be delivered (unknown recipient).
|
||||
return ""
|
||||
|
||||
|
||||
def _set_user_attribute_if_missing(username: str, user: dict[str, Any], key: str, value: str) -> None:
|
||||
@ -121,6 +125,7 @@ def main() -> int:
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
current_status = _extract_attr(user.get("attributes"), VAULTWARDEN_STATUS_ATTR)
|
||||
email = _vaultwarden_email_for_user(user)
|
||||
if not email:
|
||||
print(f"skip {username}: missing email", file=sys.stderr)
|
||||
@ -132,6 +137,12 @@ def main() -> int:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# If we've already successfully invited or confirmed presence, do not re-invite on every cron run.
|
||||
# Vaultwarden returns 409 for "already exists", which is idempotent but noisy and can trigger rate limits.
|
||||
if current_status in {"invited", "already_present"}:
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
processed += 1
|
||||
result = invite_user(email)
|
||||
if result.ok:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user