Files
Dragonbank/DragonBank/backend/database.py
T
2026-03-27 17:52:41 +01:00

143 lines
3.8 KiB
Python

"""
DragonBank - Utilitaires Base de Donnees
=========================================
Gere la connexion a PostgreSQL et la serialisation
des resultats de requetes en types JSON-compatibles.
Version : 3.0
"""
import uuid
import decimal
import logging
from datetime import datetime
import psycopg2
import psycopg2.extras
from config import URL_BASE_DE_DONNEES
journaliseur = logging.getLogger('dragonbank.database')
# ============================================================
# CONNEXION
# ============================================================
def creer_connexion():
"""
Cree et retourne une connexion active a la base de donnees PostgreSQL.
Utilise RealDictCursor pour que les resultats soient des
dictionnaires (acces par nom de colonne) plutot que des tuples.
L'autocommit est desactive : chaque route doit appeler
commit() ou rollback() explicitement.
Returns:
psycopg2.connection: Connexion avec autocommit desactive.
Raises:
psycopg2.OperationalError: Si la connexion echoue.
"""
connexion = psycopg2.connect(
URL_BASE_DE_DONNEES,
cursor_factory=psycopg2.extras.RealDictCursor
)
connexion.autocommit = False
return connexion
# ============================================================
# SERIALISATION JSON
# ============================================================
def serialiser_valeur(valeur):
"""
Convertit une valeur PostgreSQL en type serialisable JSON.
Certains types retournes par psycopg2 (Decimal, datetime, UUID)
ne sont pas nativement serialisables par json.dumps().
Args:
valeur: La valeur a convertir.
Returns:
float : si la valeur est un Decimal.
str : si la valeur est un datetime ou un UUID.
valeur : inchangee pour tous les autres types.
"""
if isinstance(valeur, decimal.Decimal):
return float(valeur)
if isinstance(valeur, datetime):
return valeur.isoformat()
if isinstance(valeur, uuid.UUID):
return str(valeur)
return valeur
def serialiser_ligne(ligne):
"""
Serialise une ligne de resultat PostgreSQL en dictionnaire Python.
Args:
ligne: Une RealDictRow psycopg2, ou None.
Returns:
dict : Toutes les colonnes avec leurs valeurs converties.
None : Si la ligne est None.
"""
if ligne is None:
return None
resultat = {}
for cle, valeur in dict(ligne).items():
resultat[cle] = serialiser_valeur(valeur)
return resultat
def serialiser_lignes(lignes):
"""
Serialise une liste de lignes de resultat PostgreSQL.
Args:
lignes: Liste de RealDictRow psycopg2.
Returns:
list[dict]: Liste de dictionnaires serialises.
"""
resultat = []
for ligne in lignes:
resultat.append(serialiser_ligne(ligne))
return resultat
# ============================================================
# AUDIT
# ============================================================
def enregistrer_audit(curseur, id_utilisateur, action, details, adresse_ip):
"""
Insere une entree dans la table des journaux d'audit.
Trace toutes les actions sensibles (connexion, virement, ouverture
de compte) pour la conformite reglementaire (RGPD, DSP2).
Args:
curseur : Curseur de base de donnees actif.
id_utilisateur : UUID de l'utilisateur.
action (str) : Code de l'action (ex: 'LOGIN', 'TRANSFER_INTERNAL').
details (dict) : Informations complementaires en JSONB.
adresse_ip (str): IP du client.
Note:
Ne commit pas. La validation est a la charge de l'appelant.
"""
curseur.execute(
"""
INSERT INTO audit_logs (user_id, action, details, ip_address)
VALUES (%s, %s, %s::jsonb, %s)
""",
(id_utilisateur, action, psycopg2.extras.Json(details), adresse_ip)
)