main.py comptait 829 lignes et regroupait 9 domaines fonctionnels. Il ne fait plus que l'assemblage de l'application (configuration, middlewares, montage des routeurs), soit 115 lignes. - routers/ : un module par domaine, chacun déclarant sa propre dépendance d'authentification - domain.py : enums UserRole et AuditAction, mapping MONITO_TABLES ; les rôles étaient jusqu'ici répétés en dur à deux endroits - helpers.py : conversion des lignes pyodbc, écriture du journal - rate_limit.py : limiteur partagé, isolé pour éviter un import circulaire entre main.py et le routeur d'authentification Les codes HTTP littéraux (404, 401, 400, 201) passent aux constantes fastapi.status, comme le faisait déjà auth.py. Les actions du journal d'audit passent en paramètre SQL au lieu d'être concaténées. Aucune route modifiée : la comparaison des specs OpenAPI avant/après confirme que les 26 URL existantes sont identiques. conftest patchait main.get_cursor ; chaque routeur important désormais get_cursor dans son propre espace de noms, la fixture remplace le nom dans tous les modules concernés.
Api-DataSentinel
API FastAPI de monitoring de la qualité des données — Data Sentinel (XEFI). Backend en lecture seule sur SQL Server, sécurisé par authentification JWT.
Stack
- Python 3.12 · FastAPI 0.136 · uvicorn
- SQL Server 2022 via
pyodbc(ODBC Driver 18) - Auth : JWT (
python-jose) + bcrypt (passlib), rate-limit (slowapi)
Lancement en local (dev)
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python -m uvicorn main:app --reload --port 8000
- Swagger :
http://127.0.0.1:8000/docs· Santé :http://127.0.0.1:8000/health
Sans variables d'environnement, l'API se connecte en authentification Windows
(LaptopCA\SQLEXPRESS) — comportement de dev d'origine, inchangé.
Configuration (variables d'environnement)
| Variable | Rôle | Défaut |
|---|---|---|
DB_SERVER |
hôte SQL Server (active l'auth SQL si défini) | — (sinon Windows local) |
DB_PORT / DB_NAME |
port / base | 1433 / DataSentinel |
DB_USER / DB_PASSWORD |
compte applicatif | — |
DB_DRIVER |
pilote ODBC | ODBC Driver 18 for SQL Server |
CORS_ORIGINS |
origines autorisées (séparées par ,) |
localhost:5173,localhost:3000 |
JWT_SECRET |
clé de signature JWT | placeholder (à définir en prod) |
JWT_ALGORITHM / JWT_EXPIRE_MINUTES |
algo / durée du token | HS256 / 60 |
Authentification & rôles
POST /auth/login(formusername/password) →{access_token, token_type, user}. Rate-limité 5/min.GET /auth/me→ profil courant.- Tous les endpoints de données exigent
Authorization: Bearer <token>(401 sinon). Seul/healthest public. - Rôles :
Admin,Superviseur,Consultant. Les routes/admin/*exigentAdmin(403 sinon).
Comptes de démo
| Identifiant | Mot de passe | Rôle | Usage |
|---|---|---|---|
Juré (JURE@NEXA.com) |
123456 |
Admin | Compte de visite / évaluation — à communiquer aux personnes qui consultent le site |
admin |
Admin2026! |
Admin | Compte d'administration technique |
superviseur |
Super2026! |
Superviseur | Illustration du RBAC (pas d'accès /admin/*) |
consultant |
Conseil2026! |
Consultant | Illustration du RBAC (lecture seule) |
Ces comptes sont créés par sql/data_sentinel_auth.sql. Pour (re)créer le seul
compte Juré sur une base déjà déployée, sans rejouer tout le script d'auth :
sqlcmd -S <serveur> -d DataSentinel -U <user> -P <mdp> -i sql/create_admin_jure.sql
Les mots de passe ci-dessus sont des identifiants de démonstration : ils sont
stockés hachés (bcrypt, coût 12) et doivent être régénérés avant toute mise en
production réelle (POST /admin/users/{id}/reset-password).
Endpoints (résumé)
- Données (protégés) :
/categories,/services,/contacts,/monitorings[...],/dashboard[...],/historique[...],/evolution/*. - Admin (
Admin) :GET/POST /admin/users,PUT/DELETE /admin/users/{id},POST /admin/users/{id}/reset-password,GET /admin/journal. - RGPD :
GET /me/data-export(portabilité),DELETE /me(droit à l'oubli + anonymisation).
Spécification complète : GET /openapi.json (export dans docs/openapi.json).
Sécurité
- En-têtes :
X-Content-Type-Options,X-Frame-Options,Referrer-Policy,Strict-Transport-Security. - CORS restreint aux origines
CORS_ORIGINS, tous verbes + credentials. - Requêtes SQL paramétrées (noms de tables/colonnes whitelistés) ; le compte applicatif
n'est pas
sa. Tables d'auth :[USER]+JOURNAL_AUDIT(sql/data_sentinel_auth.sql, identique au dump livré dansRENDU/02_Dump_SQL/). - Journal d'audit alimenté à chaque login + action admin.
Tests
pip install pytest httpx && pytest -q
Curseur SQL simulé (aucune vraie BDD) : santé, auth (succès/échec), protection 401, RBAC 403, 404.
Docker & CI/CD
Dockerfile: image Python 3.12 +msodbcsql18.- CI Gitea Actions (
.gitea/workflows/build.yml) : build → pytest (dans l'image) → push versgit.nfteam.ovh/neckfire/datasentinel-api+ notification ntfy. Déclenché sur pushmain. - Déploiement, exploitation, sauvegarde : voir
RUNBOOK.mdet le stack d'hébergement (homelab/dev/datasentinel/). La base tourne sur un SQL Server partagé (dev-mssql), pas dédiée à l'app.