Aller au contenu principal

Piste d'audit

Le problème​

Conformité, débogage, savoir qui-a-fait-quoi : chaque écriture doit enregistrer qui l'a faite et quand. Le faire dans le code client est mauvais (l'utilisateur peut falsifier) ; le faire dans chaque INSERT / UPDATE est fragile (une requête manquante et le trou d'audit apparaît).

Le modèle​

Les valeurs par défaut de la couche formulaire du framework peuplent les colonnes d'audit côté serveur au moment de l'enregistrement. Le client ne les voit jamais ; l'opérateur ne les saisit jamais ; chaque connecteur qui écrit dans la table obtient les mêmes données d'audit par construction.

Deux couches :

CoucheCe qu'elle fait
SchémaQuatre colonnes sur la table — created_by, created_at, updated_by, updated_at.
DictionnaireDeux entrées dictionnaire avec Valeurs par défaut couche formulaire LOGIN + SYSDATE.

Les requêtes d'écriture du connecteur référencent ces colonnes et le framework substitue les valeurs côté serveur.

La recette​

1. Ajouter les colonnes à la table​

ALTER TABLE customers
ADD COLUMN created_by VARCHAR(64),
ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
ADD COLUMN updated_by VARCHAR(64),
ADD COLUMN updated_at TIMESTAMP;

2. Entrées dictionnaire​

Paramètres → Dictionnaire → Colonnes → + Nouvelle colonne :

Champaudit_created_byaudit_updated_by
Typestringstring
RègleLOOKUP sur users (optionnel, pour l'affichage en puce)LOOKUP sur users
Valeur par défaut couche formulaire — CréationLOGIN—
Valeur par défaut couche formulaire — Mise à jour—LOGIN
Lecture seule sur les formulaires✓✓
Masquer à la création✓✓

Même forme pour audit_created_at / audit_updated_at :

Champaudit_created_ataudit_updated_at
Typedatetimedatetime
Formatdd/MM/yyyy HH:mmdd/MM/yyyy HH:mm
Valeur par défaut couche formulaire — CréationSYSDATE—
Valeur par défaut couche formulaire — Mise à jour—SYSDATE
Lecture seule✓✓

3. Câbler les indices de colonnes sur la requête de lecture​

Sur la requête list du connecteur, ajoutez les indices de colonnes :

ColonneDictionnaire
created_byaudit_created_by
created_ataudit_created_at
updated_byaudit_updated_by
updated_ataudit_updated_at

4. Référencer les colonnes dans les requêtes d'écriture​

-- create
INSERT INTO customers (name, status, created_by, created_at)
VALUES (:name, :status, :session_user, CURRENT_TIMESTAMP);

-- update
UPDATE customers SET
name = :name, status = :status,
updated_by = :session_user, updated_at = CURRENT_TIMESTAMP
WHERE id = :id;

Le placeholder :session_user est ce qui rend cela sûr — il est lié côté serveur depuis le JWT, pas depuis le payload du dialogue.

5. Terminé​

Le dialogue affiche maintenant les quatre colonnes d'audit comme champs en lecture seule sur l'onglet Historique (ou là où vous choisissez de les placer dans l'éditeur de dialogue). La grille affiche optionnellement Dernière modification avec la valeur updated_at comme puce alignée à droite.

Où cela apparaît​

SurfaceCe qui s'affiche
GrilleColonnes optionnelles Dernière modification / Créé par (vous décidez).
DialogueChamps en lecture seule, typiquement sur un onglet Audit ou Historique.
API RESTLes colonnes passent sans modification.
Export ExcelInclus si vous activez Inclure dans l'export.
Assistant IAVisible pour les requêtes que l'assistant peut exécuter.

Pourquoi c'est sûr​

Ce qu'un utilisateur malveillant pourrait essayerCe que fait le framework
Modifier le HTML du formulaire pour envoyer created_by = "victime" à l'enregistrement.Le serveur ignore la valeur du formulaire pour ce champ — la valeur par défaut LOGIN du dictionnaire l'emporte.
POSTer directement sur l'endpoint REST avec un corps created_by falsifié.Idem — la valeur par défaut de la couche formulaire est appliquée côté serveur au moment de l'enregistrement, après l'analyse du corps de la requête.
Utiliser liberty-connectors run (CLI) pour contourner l'auth.La CLI s'exécute comme l'utilisateur local ; la même valeur par défaut LOGIN substitue l'utilisateur OS. Piste d'audit intacte.

Variantes​

Vous voulez…Faites ceci
Une colonne versionAjoutez une colonne version, incrémentez-la dans la requête update (SET version = version + 1). Combinée avec les verrous d'enregistrement du framework, vous obtenez un contrôle de concurrence optimiste.
Un journal d'audit immuable (chaque modification, pas seulement la dernière)Ajoutez une table enfant audit_log ; écrivez une ligne depuis une étape Python à chaque enregistrement. Voir Plugins.
Suivre qui a consulté une ligneProblème différent. Le framework enregistre chaque appel API dans le journal des requêtes ; pour l'audit de lecture au niveau ligne, écrivez un hook Python sur screen.before_read.

Pour aller plus loin​