Le nom affiché dans la barre de navigation (base.html) devient un lien vers /profile : informations du compte (email en lecture seule, nom/ prénom modifiables), changement de mot de passe (mot de passe actuel requis + mêmes règles de force qu'à l'inscription/la réinitialisation), et une section "danger" pour demander la suppression du compte. La suppression exige le mot de passe actuel ET la saisie exacte de "SUPPRIMER" (deux confirmations distinctes pour une action irréversible) — routes/auth/profile.py. Pour un compte "user" (limité à un seul projet, créé automatiquement et impossible à supprimer autrement, voir core/auth_guard.py), supprimer le compte supprime aussi son unique projet sur le disque, faute de quoi il resterait orphelin sans plus aucun propriétaire. Un compte "admin" peut posséder plusieurs jeux qui ne lui sont pas dédiés de la même façon : ses projets ne sont jamais touchés. L'unique compte administrateur ne peut pas être supprimé (auth/ count_admins.py) — le supprimer bloquerait la création d'un nouveau compte admin (réservée au tout premier compte jamais créé, base vide). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
48 lines
2.3 KiB
Python
48 lines
2.3 KiB
Python
"""auth — comptes utilisateurs, connexion, 2FA (TOTP) et isolation par
|
|
utilisateur d'un SEUL projet (sauf le rôle "admin", illimité) — voir
|
|
create_user.py pour le détail des règles. Base SQLite entièrement séparée
|
|
de db/ (une base par JEU) : ces comptes n'appartiennent à aucun jeu, ils
|
|
en POSSÈDENT un (project_slug)."""
|
|
|
|
from .connection import users_db_path
|
|
from .ensure_schema import ensure_users_schema
|
|
from .is_first_user import is_first_user
|
|
from .create_user import create_user, UserCreationError
|
|
from .get_user_by_email import get_user_by_email
|
|
from .get_user_by_id import get_user_by_id
|
|
from .verify_password import verify_password
|
|
from .confirm_totp import confirm_totp
|
|
from .verify_totp import verify_totp
|
|
from .set_project_slug import set_project_slug
|
|
from .password_strength import password_strength, MIN_SCORE_REQUIRED
|
|
from .totp_qrcode_svg import totp_provisioning_uri, totp_qrcode_svg
|
|
from .rate_limit import lockout_minutes_for, seconds_locked_remaining, lockout_message
|
|
from .record_failed_attempt import record_failed_attempt
|
|
from .reset_failed_attempts import reset_failed_attempts
|
|
from .recovery_codes import generate_recovery_codes, verify_recovery_code
|
|
from .set_password import set_password
|
|
from .password_reset import (
|
|
create_password_reset_token, get_user_id_for_valid_token, consume_password_reset_token,
|
|
TOKEN_TTL_MINUTES,
|
|
)
|
|
from .send_email import send_password_reset_email, EmailNotConfiguredError
|
|
from .update_profile import update_profile
|
|
from .count_admins import count_admins
|
|
from .delete_user import delete_user
|
|
|
|
__all__ = [
|
|
"users_db_path", "ensure_users_schema", "is_first_user",
|
|
"create_user", "UserCreationError",
|
|
"get_user_by_email", "get_user_by_id",
|
|
"verify_password", "confirm_totp", "verify_totp", "set_project_slug",
|
|
"password_strength", "MIN_SCORE_REQUIRED",
|
|
"totp_provisioning_uri", "totp_qrcode_svg",
|
|
"lockout_minutes_for", "seconds_locked_remaining", "lockout_message",
|
|
"record_failed_attempt", "reset_failed_attempts",
|
|
"generate_recovery_codes", "verify_recovery_code",
|
|
"set_password", "create_password_reset_token", "get_user_id_for_valid_token",
|
|
"consume_password_reset_token", "TOKEN_TTL_MINUTES",
|
|
"send_password_reset_email", "EmailNotConfiguredError",
|
|
"update_profile", "count_admins", "delete_user",
|
|
]
|