Files
ObsiGate/docs/features/settings-order-avatar-113.md
T
bruno 33fe1a3439
CI / lint (push) Successful in 1m59s
CI / security (push) Successful in 1m28s
CI / test (push) Successful in 4m14s
CI / build (push) Successful in 1m20s
CI / e2e (push) Successful in 13m43s
feat: ordre naturel des sections Configurations et avatar utilisateur #113
2026-09-23 22:18:29 -04:00

4.7 KiB

#113 — Ordre naturel des sections Configurations & avatar utilisateur

Version livrée : 2.22.0 · Statut : 🟢 · Impact : 🟡 Zone : frontend (index.html, frontend/js/config.js, frontend/js/auth.js, frontend/style.css, i18n FR/EN) + backend (backend/auth/router.py, backend/auth/user_store.py) + CI (.gitea/workflows/ci.yml).

Contexte

Deux irritants sur la page Configurations :

  • l'ordre des sections était historique et peu naturel (Recherche en tête, Profil noyé en position 11, À propos au milieu) ;
  • la section Profil ne permettait pas de personnaliser l'image affichée dans le cercle du compte en bas de la sidebar (initiales uniquement).

Ce qui a été livré

A. Ordre naturel des sections (TOC = page)

Nouvel ordre, appliqué à la liste <ul class="help-nav-list"> (TOC) et aux <section> de la page, dans le même ordre :

  1. Profil (#cfg-profile) — en premier
  2. Sécurité du compte (#cfg-security)
  3. Thèmes (#cfg-themes)
  4. Paramètres de recherche (#cfg-search)
  5. Historique récent (#cfg-recent)
  6. Filtrage de tags (#cfg-tags)
  7. Fichiers cachés (#cfg-hidden-files)
  8. Synchronisation (#cfg-sync)
  9. Paramètres backend (#cfg-backend-settings)
  10. Diagnostics (#cfg-diags)
  11. Clés API IA (#cfg-ai)
  12. Sources connectées (#cfg-sources)
  13. Clés API & MCP (#cfg-tokens)
  14. Notifications push (#cfg-push)
  15. Webhooks (#cfg-webhooks)
  16. Partages publics (#cfg-partages-publics)
  17. Plugins (#cfg-plugins)
  18. À propos (#cfg-about) — en dernier

Regroupement retenu : Compte & apparence → Navigation & contenu → Système → Intégrations & notifications → À propos.

Les ancres cfg-tags et cfg-partages-publics étaient posées sur un <h2> à l'intérieur d'une <section> sans id : elles sont désormais portées par la <section> elle-même, pour que le scroll vise le haut de la section (comme toutes les autres).

B. Avatar utilisateur ( Profil )

  • Import d'image : bouton « Choisir une image » + overlay caméra au survol de l'aperçu circulaire (88 px) → <input type="file" accept="image/png,image/jpeg,image/webp">.
  • Traitement client (config.js) : garde type (PNG/JPEG/WEBP) et taille brute (8 Mo), recadrage carré central et redimensionnement à 256 px via canvas, export JPEG qualitée 0,85 (fond blanc pour les PNG transparents).
  • Persistance serveur : PATCH /api/auth/me avec {"avatar": "<data-url>"} ; "" supprime. Validation stricte dans backend/auth/router.py (_validate_avatar) : data-URL PNG/JPEG/WebP uniquement (SVG refusé — surface XSS), plafond 400 000 caractères, base64 valide et octets magiques contrôlés. Champ avatar ajouté à data/users.json (create_user), renvoyé par GET/PATCH /api/auth/me et par le payload user de login.
  • Affichage sidebar (auth.js) : renderUserSection() insère un <img class="sidebar-user-avatar-img"> dans #sidebar-user-avatar quand user.avatar est défini, sinon les initiales (repli inchangé). Helpers AuthManager.updateCachedUser() et AuthManager.isAuthEnabled().
  • Suppression : bouton « Supprimer la photo » (stylisté danger), revenu aux initiales.
  • Auth désactivée : le bloc avatar est masqué (pas de compte, sidebar masquée).
  • Feedback : toasts config.avatar_updated / config.avatar_removed, erreurs en ligne (config.avatar_invalid_type, config.avatar_too_large, config.avatar_upload_failed).

Tests

  • tests/test_auth_api.py — classe TestAvatar (+8) : GET/PATCH exposent l'avatar, data-URL PNG acceptée, "" efface, SVG refusé, payload non-image refusé, trop grand refusé, base64 invalide refusé, avatar présent dans le payload de login.
  • tests/frontend/settings-order-avatar.test.mjs (nouveau, ajouté au job lint) — 9 tests : ordre TOC (Profil 1er, À propos dernier), ordre de page strictement identique à la TOC, aucune ancre morte / section orpheline, présence de l'UI avatar dans #cfg-profile, flux config.js (types, taille, resize, PATCH, rafraîchissement sidebar), rendu auth.js, règles CSS, clés i18n FR/EN, validation backend.
  • Vérifications locales : pytest 1302 passed, ruff/mypy 0 erreur, tests frontend statiques + JSDOM verts.

Limitations connues

  • L'avatar est stocké en data-URL dans data/users.json (adéquat pour un usage personnel ; un stockage fichier dédié restera possible si les comptes se multiplient).
  • La conversion GIF/animé n'est pas prise en charge (types PNG/JPEG/WEBP uniquement).
  • Le nom d'affichage du profil reste local (localStorage) et n'est pas poussé au serveur (comportement antérieur conservé).