Journal d'audit
Traçabilité complète des actions utilisateur, persistée en base et exposée via l'API REST.
Vue d'ensemble
Le journal d'audit enregistre chaque action significative dans la table audit_logs.
Chaque entrée capture l'acteur (l'utilisateur), l'action, la cible
(type + UUID), des métadonnées contextuelles et l'adresse IP.
Le système est piloté par le pattern Event Subscriber — les subscribers d'audit écoutent les événements métier existants sans modifier la logique applicative.
| Fichier | Rôle |
|---|---|
src/Entity/Audit/AuditLog.php | Entité (UUID, actor, action enum, target_type, target_id, metadata JSON, ip_address) |
src/Enum/AuditAction.php | 11 actions prédéfinies (auth, profil, organisation) |
src/Service/Audit/AuditService.php | Service central — méthode log() injectable partout |
src/EventSubscriber/Audit/AuditAuthSubscriber.php | Écoute les événements Auth + LoginSuccessEvent |
src/EventSubscriber/Audit/AuditOrganizationSubscriber.php | Écoute les événements Organisation |
src/ApiResource/AuditLogResource.php | DTO API Platform |
src/State/Api/AuditLogProvider.php | Provider — filtré sur l'org, Owner/Admin uniquement |
Actions tracées
| Action | Déclencheur | Métadonnées |
|---|---|---|
user_registered | UserRegisteredEvent | |
user_login | LoginSuccessEvent | firewall |
user_email_verified | UserEmailVerifiedEvent | — |
password_reset_requested | PasswordResetRequestedEvent | |
email_change_requested | EmailChangeRequestedEvent | new_email |
twofa_enabled | À déclencher manuellement | — |
twofa_disabled | À déclencher manuellement | — |
organization_created | OrganizationCreatedEvent | name, slug |
member_invited | MemberInvitedEvent | email, role, organization |
member_joined | MemberJoinedEvent | organization, role |
profile_updated | À déclencher manuellement | — |
Endpoint API
| Méthode | URI | Accès |
|---|---|---|
| GET | /api/organizations/{id}/audit |
Owner ou Admin de l'organisation |
Exemple de réponse
[
{
"id": "019e...",
"actorId": "018f...",
"actorName": "Benjamin Manguet",
"action": "member_joined",
"targetType": "organization",
"targetId": "018e...",
"metadata": { "organization": "Acme", "role": "member" },
"ipAddress": "127.0.0.1",
"createdAt": "2026-04-19T11:00:00+00:00"
}
]
Les membres simples (member) reçoivent une 403 s'ils tentent
d'accéder au journal — seuls les Owner et Admin peuvent lire l'audit de leur organisation.
Ajouter une action
1 — Ajouter un case dans AuditAction :
case ProfileUpdated = 'profile_updated';
2 — Appeler AuditService::log() depuis un subscriber ou un service :
$this->auditService->log(
action: AuditAction::ProfileUpdated,
actor: $user,
targetType: 'user',
targetId: (string) $user->getId(),
metadata: ['fields' => 'firstName, lastName'],
ipAddress: $request->getClientIp(),
);
3 — Ajouter la traduction dans translations/boilerplate.*.yaml sous la clé
audit.action.profile_updated.