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 à jourLOGIN
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 à jourSYSDATE
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.
Tracer 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