Compare commits
4
Commits
75f9727710
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3538d77217 | ||
|
|
b7551073f5 | ||
|
|
e8b4a604e9 | ||
|
|
caa0b126b1 |
@@ -150,6 +150,9 @@ activemq-data/
|
|||||||
# Environments
|
# Environments
|
||||||
.env
|
.env
|
||||||
.envrc
|
.envrc
|
||||||
|
# Configuration de déploiement : contient la chaîne de connexion et
|
||||||
|
# la clé JWT. Seul api.env.example (sans valeurs) est versionné.
|
||||||
|
api.env
|
||||||
.venv
|
.venv
|
||||||
env/
|
env/
|
||||||
venv/
|
venv/
|
||||||
|
|||||||
@@ -132,8 +132,8 @@ pip install pytest httpx && pytest -q
|
|||||||
|
|
||||||
**82 tests**, curseur SQL simulé (aucune vraie base requise) :
|
**82 tests**, curseur SQL simulé (aucune vraie base requise) :
|
||||||
|
|
||||||
| Fichier | Couverture |
|
| Fichier | Domaine testé |
|
||||||
|---------|------------|
|
|---------|---------------|
|
||||||
| `test_endpoints.py` | santé, référentiels, authentification, filtres du dashboard, rôles par enum |
|
| `test_endpoints.py` | santé, référentiels, authentification, filtres du dashboard, rôles par enum |
|
||||||
| `test_historique.py` | bornes de dates, validation du format, agrégation des courbes par monitoring et par service |
|
| `test_historique.py` | bornes de dates, validation du format, agrégation des courbes par monitoring et par service |
|
||||||
| `test_securite.py` | protection 401 de chaque route, RBAC 403, jeton forgé rejeté, en-têtes de sécurité, rate-limit 429, compte désactivé, droits RGPD |
|
| `test_securite.py` | protection 401 de chaque route, RBAC 403, jeton forgé rejeté, en-têtes de sécurité, rate-limit 429, compte désactivé, droits RGPD |
|
||||||
|
|||||||
+1
-1
@@ -77,4 +77,4 @@ docker compose up -d datasentinel-api
|
|||||||
## Contacts
|
## Contacts
|
||||||
|
|
||||||
- Hébergement / infra : administrateur homelab (neckfire).
|
- Hébergement / infra : administrateur homelab (neckfire).
|
||||||
- Application / code : A. Coyaud (auteur, dépôts GitHub).
|
- Application / code : A. Coyaud (auteur, dépôts Gitea — git.nfteam.ovh).
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# ============================================================
|
||||||
|
# Data Sentinel — modèle de configuration de l'API
|
||||||
|
#
|
||||||
|
# Copier ce fichier en api.env (à côté du docker-compose.yml)
|
||||||
|
# et renseigner les valeurs. api.env n'est JAMAIS versionné :
|
||||||
|
# il est exclu par .gitignore.
|
||||||
|
#
|
||||||
|
# cp Api-DataSentinel/api.env.example api.env
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# ---- Base de données ---------------------------------------
|
||||||
|
# Hôte SQL Server. En conteneur, le nom du service Docker
|
||||||
|
# (ex. dev-mssql) ; en local, localhost ou HOTE\INSTANCE.
|
||||||
|
DB_SERVER=dev-mssql
|
||||||
|
|
||||||
|
# Port. Laisser VIDE pour une instance nommée (HOTE\INSTANCE).
|
||||||
|
DB_PORT=1433
|
||||||
|
|
||||||
|
DB_NAME=DataSentinel
|
||||||
|
|
||||||
|
# Compte applicatif dédié — surtout pas « sa ».
|
||||||
|
# Création : voir README.md §3.3 (db_datareader + db_datawriter
|
||||||
|
# sur la seule base DataSentinel).
|
||||||
|
DB_USER=datasentinel_app
|
||||||
|
DB_PASSWORD=
|
||||||
|
|
||||||
|
# Pilote ODBC embarqué dans l'image.
|
||||||
|
DB_DRIVER=ODBC Driver 18 for SQL Server
|
||||||
|
|
||||||
|
# Mettre à yes pour forcer l'authentification Windows
|
||||||
|
# (poste de développement uniquement, sans DB_USER).
|
||||||
|
DB_TRUSTED_CONNECTION=
|
||||||
|
|
||||||
|
# ---- Sécurité ----------------------------------------------
|
||||||
|
# OBLIGATOIRE en déploiement. Sans cette variable, l'API démarre
|
||||||
|
# mais tire une clé aléatoire à chaque redémarrage : toutes les
|
||||||
|
# sessions sont alors invalidées au moindre restart.
|
||||||
|
# Générer : python -c "import secrets; print(secrets.token_urlsafe(64))"
|
||||||
|
JWT_SECRET=
|
||||||
|
|
||||||
|
JWT_ALGORITHM=HS256
|
||||||
|
JWT_EXPIRE_MINUTES=60
|
||||||
|
|
||||||
|
# ---- CORS ---------------------------------------------------
|
||||||
|
# Origines autorisées, séparées par des virgules. Doit contenir
|
||||||
|
# l'URL exacte du front (schéma + hôte, sans slash final).
|
||||||
|
CORS_ORIGINS=https://datasentinel.nfteam.ovh
|
||||||
|
|
||||||
|
# ---- Build --------------------------------------------------
|
||||||
|
# Injecté par la CI (SHA court du commit) et exposé par GET /health.
|
||||||
|
APP_BUILD=local
|
||||||
@@ -81,7 +81,7 @@ class Config:
|
|||||||
|
|
||||||
# Paramètres API
|
# Paramètres API
|
||||||
API_TITLE = "Data Sentinel API"
|
API_TITLE = "Data Sentinel API"
|
||||||
API_VERSION = "1.0.0"
|
API_VERSION = "1.1.0"
|
||||||
API_DESCRIPTION = "API de monitoring de la qualité des données — XEFI"
|
API_DESCRIPTION = "API de monitoring de la qualité des données — XEFI"
|
||||||
|
|
||||||
# Identifiant de build injecté par la CI : permet de vérifier quelle
|
# Identifiant de build injecté par la CI : permet de vérifier quelle
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
-47
@@ -1,47 +0,0 @@
|
|||||||
import requests
|
|
||||||
import json
|
|
||||||
|
|
||||||
# Configuration
|
|
||||||
BASE_URL = "http://127.0.0.1:8000"
|
|
||||||
|
|
||||||
def test_get_dashboard():
|
|
||||||
print(f"--- Test de l'endpoint: {BASE_URL}/dashboard ---")
|
|
||||||
|
|
||||||
try:
|
|
||||||
# 1. Envoi de la requête
|
|
||||||
response = requests.get(f"{BASE_URL}/dashboard")
|
|
||||||
|
|
||||||
# 2. Vérification du code statut
|
|
||||||
if response.status_code == 200:
|
|
||||||
data = response.json()
|
|
||||||
|
|
||||||
if not data:
|
|
||||||
print("L'API a répondu avec succès, mais le tableau est vide (VUE_CONSO ne contient rien).")
|
|
||||||
return
|
|
||||||
|
|
||||||
# 3. Affichage formaté du tableau
|
|
||||||
print(f"{'ID':<5} | {'NOM DU MONITORING':<40} | {'ERREURS':<8} | {'SERVICE':<15}")
|
|
||||||
print("-" * 75)
|
|
||||||
|
|
||||||
for item in data:
|
|
||||||
print(f"{item['id_monito']:<5} | {item['nom_monito'][:38]:<40} | {item['nb_erreurs']:<8} | {item['service']:<15}")
|
|
||||||
|
|
||||||
print(f"\nTotal de lignes récupérées : {len(data)}")
|
|
||||||
|
|
||||||
else:
|
|
||||||
print(f"Erreur lors de la requête : {response.status_code}")
|
|
||||||
print(response.text)
|
|
||||||
|
|
||||||
except requests.exceptions.ConnectionError:
|
|
||||||
print("Erreur : Impossible de se connecter à l'API. Est-ce qu'uvicorn est lancé ?")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# Petit check de santé avant de tester les données
|
|
||||||
print("Vérification de l'état de l'API...")
|
|
||||||
health = requests.get(f"{BASE_URL}/health").json()
|
|
||||||
print(f"Statut API : {health['api']} | Statut DB : {health['database']}\n")
|
|
||||||
|
|
||||||
if health['database'] == "ok":
|
|
||||||
test_get_dashboard()
|
|
||||||
else:
|
|
||||||
print("Abandon du test : La base de données n'est pas accessible.")
|
|
||||||
Reference in New Issue
Block a user