feat(sprint-15 backend 2026-04-25): Live Activity Feed — endpoint /api/audit-trail/recent + tests
Some checks failed
CI/CD Pipeline / pipeline (push) Failing after 3m50s

Transparency opérationnelle UnionFlow — opérations sensibles consultables en temps réel selon scope.

Repository
- findRecent(limit) : N opérations les plus récentes, toutes orgs
- findRecentByOrganisation(orgId, limit) : pour scope ORG
- findRecentByUser(userId, limit) : pour scope SELF
- Tous clamps limit à [1, 500] (sécurité DoS)

Service AuditTrailQueryService
- listerRecentes(scope, orgId, userId, limit) : dispatcher SELF/ORG/ALL avec fallback liste vide si UUID requis manquant ; insensible à la casse

Resource REST AuditTrailOperationResource
- GET /api/audit-trail/recent?scope=SELF&orgId=...&userId=...&limit=50
- Default scope=SELF, limit=50
- @RolesAllowed étendu (MEMBRE inclus pour scope SELF) — un membre peut voir SES propres opérations

Tests (7 nouveaux, 11/11 cumulé service)
- recentes_All / Null defaults to ALL / Org / OrgWithoutId / Self / SelfWithoutUser / CaseInsensitive
This commit is contained in:
dahoud
2026-04-25 16:08:33 +00:00
parent 7c3352ed48
commit e4d7c8e4b7
4 changed files with 128 additions and 0 deletions

View File

@@ -78,6 +78,30 @@ public class AuditTrailOperationResource {
return queryService.operationsFinancieres(orgId, fromDt, toDt);
}
/**
* Live Activity Feed (Sprint 15) — N opérations les plus récentes (transparency).
*
* <p>Scopes :
* <ul>
* <li>ALL — toutes orgs (restreint compliance/contrôleurs/super-admin)</li>
* <li>ORG — organisation indiquée (admin org / président / officers)</li>
* <li>SELF (défaut) — opérations de l'utilisateur indiqué (n'importe quel rôle peut voir les siennes)</li>
* </ul>
*
* <p>Limit clampé à [1, 500] côté repository (sécurité contre DoS).
*/
@GET
@Path("/recent")
@RolesAllowed({"COMPLIANCE_OFFICER", "CONTROLEUR_INTERNE", "ADMIN_ORGANISATION",
"PRESIDENT", "TRESORIER", "MEMBRE", "SUPER_ADMIN"})
public List<AuditTrailOperationResponse> recent(
@QueryParam("scope") @jakarta.ws.rs.DefaultValue("SELF") String scope,
@QueryParam("orgId") UUID orgId,
@QueryParam("userId") UUID userId,
@QueryParam("limit") @jakarta.ws.rs.DefaultValue("50") int limit) {
return queryService.listerRecentes(scope, orgId, userId, limit);
}
private LocalDateTime parseDateTime(String input, LocalDateTime fallback) {
if (input == null || input.isBlank()) return fallback;
try {