Logs de diagnostic et rapprochement SumUp ↔ bénévole
- Une ligne de log par requête (route modèle, statut, durée, code d'erreur, compte), identifiant X-Request-ID repris dans chaque log et affiché à l'utilisateur sous une erreur, exceptions non gérées tracées (500 JSON) - Journal d'accès d'uvicorn coupé : il exposait le jeton du formulaire public - Logs métier : paiement SumUp, connexion, import, plannings, solveur - Nom du bénévole dans la description du checkout SumUp - Code et identifiant de transaction SumUp enregistrés au paiement (migration 0023), affichés sur la fiche et dans l'export Excel Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
d722a81a87
commit
d0fa1e109c
@@ -84,7 +84,17 @@ def login(
|
||||
or account.password_hash is None
|
||||
or not verify_password(payload.password, account.password_hash)
|
||||
):
|
||||
# Cause réelle dans les logs seulement — la réponse reste la même
|
||||
# (pas de divulgation). Jamais l'email saisi.
|
||||
if account is None:
|
||||
reason = "aucun compte pour cet email"
|
||||
elif account.password_hash is None:
|
||||
reason = f"compte {account.id} sans mot de passe (lien magique)"
|
||||
else:
|
||||
reason = f"mot de passe incorrect pour le compte {account.id}"
|
||||
logger.info("Connexion refusée (édition %s) : %s", edition_id, reason)
|
||||
raise _invalid_credentials()
|
||||
logger.info("Connexion par mot de passe : compte %s (édition %s)", account.id, edition_id)
|
||||
return _issue(account)
|
||||
|
||||
|
||||
@@ -135,7 +145,19 @@ def request_magic_link(
|
||||
tâche de fond (une erreur SMTP est journalisée, pas remontée)."""
|
||||
magic_link_limiter.hit(f"{edition_id}:{payload.email.strip().lower()}")
|
||||
account = _account_by_email(session, edition_id, payload.email)
|
||||
if account is None:
|
||||
logger.info(
|
||||
"Lien magique demandé sans compte correspondant (édition %s) — rien envoyé "
|
||||
"(un email sur une fiche bénévole ne crée pas d'accès)",
|
||||
edition_id,
|
||||
)
|
||||
elif account.password_hash is not None:
|
||||
logger.info(
|
||||
"Lien magique demandé pour le compte %s, qui a un mot de passe — rien envoyé",
|
||||
account.id,
|
||||
)
|
||||
if account is not None and account.password_hash is None:
|
||||
logger.info("Lien magique émis pour le compte %s (édition %s)", account.id, edition_id)
|
||||
settings = get_settings()
|
||||
raw = issue_magic_link_token(session, account)
|
||||
session.commit()
|
||||
@@ -172,13 +194,26 @@ def verify_magic_link(
|
||||
or token.used_at is not None
|
||||
or token.expires_at < local_now()
|
||||
):
|
||||
if token is None:
|
||||
reason = "jeton inconnu"
|
||||
elif token.used_at is not None:
|
||||
reason = f"jeton déjà utilisé (compte {token.account_id})"
|
||||
else:
|
||||
reason = f"jeton expiré (compte {token.account_id})"
|
||||
logger.info("Lien magique refusé (édition %s) : %s", edition_id, reason)
|
||||
raise _invalid_token()
|
||||
account = session.get(Account, token.account_id)
|
||||
if account is None or account.edition_id != edition_id:
|
||||
logger.info(
|
||||
"Lien magique refusé (édition %s) : compte %s absent ou d'une autre édition",
|
||||
edition_id,
|
||||
token.account_id,
|
||||
)
|
||||
raise _invalid_token()
|
||||
token.used_at = local_now()
|
||||
session.commit()
|
||||
session.refresh(account)
|
||||
logger.info("Connexion par lien magique : compte %s (édition %s)", account.id, edition_id)
|
||||
return _issue(account)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user