Files
gesthub/docs/08_partie5_retrodocumentation.md
2026-08-21 09:12:02 +02:00

76 lines
4.4 KiB
Markdown

# Partie 5 — Rétro-documentation
Cette rétro-documentation a été produite par analyse du code source réel de
`gesthub-v2` (et non rédigée en amont du code), selon la démarche
décrite au Bloc 4 — C1 : 1) analyse de l'arborescence, 2) lecture du code
pour comprendre le rôle de chaque fonction, 3) reconstruction des flux à
partir des appels de fonctions, 4) production du dictionnaire de données.
## RD-1 — Architecture en 5 couches
| Couche | Répertoire | Responsabilité |
|---|---|---|
| Présentation | `templates/`, `static/` | Rendu HTML (Jinja2), CSS, JS (SortableJS pour le drag & drop) |
| Contrôleur | `routes/` | Orchestration HTTP : authentifie, délègue, répond en JSON/HTML |
| Service | `services/` | Logique métier, validation, journalisation dans `audit_log` |
| Accès données | `models/` | Repository Pattern, seules requêtes SQL de tout le projet |
| Infrastructure | `db.py`, `config.py`, `docker-compose.yml` | Connexion MariaDB, configuration par variables d'environnement, orchestration des conteneurs |
## RD-2 — Flux de données détaillés
**Consultation des annonces :**
`Navigateur → GET /api/annonces → routes/annonces.py (vérifie la session)
→ services/annonce_service.list_annonces → models/annonce_model.fetch_all
→ MariaDB (SELECT paramétré) → JSON → Navigateur`
**Upload de fichier :**
`Navigateur (multipart/form-data) → routes/fichiers.py → services/
fichier_service.handle_upload (8 étapes : présence → taille → MIME →
extension → nom UUID → écriture disque → INSERT métadonnées → INSERT
audit_log) → réponse JSON {id}`
**Téléchargement de fichier :**
`Navigateur → GET /api/fichiers/{id}/download → vérification des droits
(propriétaire ou admin) → audit_log (SUCCESS ou REFUSED) → send_file (si
autorisé) ou 403`
## RD-3 — Flux d'authentification OIDC (annoté, 7 étapes)
| Étape | Description | Code |
|---|---|---|
| 1 | Détection de l'absence de session | `routes/dashboard.py::index` (`is_authenticated()`) |
| 2 | Génération de l'URL d'autorisation + nonce anti-rejeu | `routes/auth.py::login` |
| 3 | Redirection vers Keycloak | `keycloak.authorize_redirect(...)` |
| 4 | Retour sur `/auth` avec le code d'autorisation | Géré automatiquement par Authlib |
| 5 | Échange du code contre un token | `keycloak.authorize_access_token()` |
| 6 | Vérification du token (signature + nonce) | `keycloak.parse_id_token(token, nonce=nonce)` |
| 7 | Création de la session applicative | `session["user"] = userinfo` |
## RD-4 — Dictionnaire de données
| Champ | Table | Type SQL | Source | Description |
|---|---|---|---|---|
| `id` | toutes | `INT UNSIGNED AUTO_INCREMENT` | MariaDB | Clé primaire |
| `titre` | annonces, evenements | `VARCHAR(150)` | Saisie admin | Titre affiché |
| `epinglee` | annonces | `TINYINT(1)` | Saisie admin | Priorité d'affichage |
| `auteur_sub` / `uploader_sub` / `createur_sub` | annonces, fichiers, evenements | `VARCHAR(64)` | Claim `sub` du token OIDC | Référence utilisateur (pas de doublon des données Keycloak) |
| `nom_stocke` | fichiers | `VARCHAR(64)` | Généré (UUID4) | Nom réel sur disque, anti path-traversal |
| `taille_octets` | fichiers | `BIGINT UNSIGNED` | Calculé à l'upload | Taille du fichier |
| `action` / `statut` | audit_log | `VARCHAR(50)` / `VARCHAR(20)` | Généré par les services | Traçabilité (ex. `CREATE_ANNONCE` / `SUCCESS`) |
## RD-5 — Table de correspondance claims JWT ↔ champs applicatifs
| Claim JWT (Keycloak) | Champ applicatif | Utilisation |
|---|---|---|
| `sub` | `session["user"]["sub"]`, colonnes `*_sub` en base | Identifiant utilisateur unique et stable |
| `preferred_username` | `session["user"]["preferred_username"]` | Affichage du nom d'utilisateur (template `index.html`) |
| `email` | `session["user"]["email"]` | Non utilisé actuellement (disponible pour évolutions, ex. notifications) |
| `groups` | `session["user"]["groups"]` | Contrôle d'accès (`/admin``is_admin()`) |
| `iat`, `exp`, `iss` | Vérifiés automatiquement par Authlib | Validité temporelle et émetteur du token |
En spécialité Robotique & Systèmes Embarqués, cette même logique de table de
correspondance s'applique au mapping entre formats de données capteurs
(ex. trame UART) et structures Python applicatives — la compétence
transférée est la même : documenter précisément la correspondance entre un
format source externe et le modèle interne de l'application.