feat: Optimisations UX/UI et amélioration import/export CSV
Optimisations majeures de l'interface utilisateur et amélioration du système d'import/export CSV avec rapport d'erreurs détaillé. ## Optimisations UX/UI - Suppression des blocs Actions Rapides redondants dans les pages list/view - Consolidation des actions dans les en-têtes de page - Conversion des filtres en panneau collapsible avec badge Filtres actifs - Suppression du sous-menu Attribution Rôles (redondant avec /users/edit) - Amélioration de la navigation et de l'ergonomie générale - Correction des attributs iconLeft non supportés par fr:fieldInput ## Import/Export CSV - Ajout de ImportResultDTO avec rapport détaillé des erreurs - Création de CsvValidationHelper pour validation robuste des données - Amélioration des messages d'erreur avec numéros de ligne - Support de colonnes flexibles (username,prenom,nom,email) - Validation stricte des formats email ## Corrections techniques - Fix DashboardBeanTest: getRecentActions() → getActionsLast24h() - Fix UserServiceImplTest: retour ImportResultDTO au lieu de int - Amélioration de la gestion d'erreurs dans AuditServiceImpl - Migration Flyway V1.0.0 pour la table audit_logs ## Infrastructure - Mise à jour .gitignore professionnel (exclusion docs de session) - Configuration production sécurisée (variables d'environnement) - Pas de secrets hardcodés dans les fichiers de configuration Testé et validé en environnement de développement.
This commit is contained in:
@@ -22,6 +22,7 @@ import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
|
||||
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
|
||||
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -407,6 +408,86 @@ public class UserResource {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exporter les utilisateurs en CSV
|
||||
*/
|
||||
@GET
|
||||
@Path("/export/csv")
|
||||
@Operation(summary = "Exporter les utilisateurs en CSV")
|
||||
@APIResponses({
|
||||
@APIResponse(responseCode = "200", description = "Fichier CSV généré avec succès"),
|
||||
@APIResponse(responseCode = "400", description = "Realm manquant ou invalide"),
|
||||
@APIResponse(responseCode = "500", description = "Erreur serveur")
|
||||
})
|
||||
@RolesAllowed({"admin", "user_manager", "user_viewer"})
|
||||
@Produces(MediaType.TEXT_PLAIN)
|
||||
public Response exportUsersToCSV(@QueryParam("realm") @NotBlank String realmName) {
|
||||
log.info("GET /api/users/export/csv - realm: {}", realmName);
|
||||
|
||||
try {
|
||||
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
|
||||
.realmName(realmName)
|
||||
.pageSize(10000) // Export complet sans pagination
|
||||
.page(0)
|
||||
.build();
|
||||
|
||||
String csvContent = userService.exportUsersToCSV(criteria);
|
||||
|
||||
String filename = "users_export_" +
|
||||
LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd_HHmmss")) +
|
||||
".csv";
|
||||
|
||||
return Response.ok(csvContent)
|
||||
.header("Content-Disposition", "attachment; filename=\"" + filename + "\"")
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
log.error("Erreur lors de l'export CSV des utilisateurs", e);
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(new ErrorResponse(e.getMessage()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Importer des utilisateurs depuis CSV avec rapport détaillé
|
||||
*/
|
||||
@POST
|
||||
@Path("/import/csv")
|
||||
@Operation(summary = "Importer des utilisateurs depuis un fichier CSV")
|
||||
@APIResponses({
|
||||
@APIResponse(responseCode = "200", description = "Import terminé avec rapport détaillé"),
|
||||
@APIResponse(responseCode = "400", description = "Fichier CSV vide ou invalide"),
|
||||
@APIResponse(responseCode = "500", description = "Erreur serveur")
|
||||
})
|
||||
@RolesAllowed({"admin", "user_manager"})
|
||||
@Consumes(MediaType.TEXT_PLAIN)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response importUsersFromCSV(
|
||||
@QueryParam("realm") @NotBlank String realmName,
|
||||
String csvContent) {
|
||||
log.info("POST /api/users/import/csv - realm: {}", realmName);
|
||||
|
||||
try {
|
||||
if (csvContent == null || csvContent.trim().isEmpty()) {
|
||||
return Response.status(Response.Status.BAD_REQUEST)
|
||||
.entity(new ErrorResponse("Le contenu CSV est vide"))
|
||||
.build();
|
||||
}
|
||||
|
||||
dev.lions.user.manager.dto.importexport.ImportResultDTO result = userService.importUsersFromCSV(csvContent, realmName);
|
||||
|
||||
log.info("{} utilisateur(s) importé(s) dans le realm {} ({} erreur(s))",
|
||||
result.getSuccessCount(), realmName, result.getErrorCount());
|
||||
|
||||
return Response.ok(result).build();
|
||||
} catch (Exception e) {
|
||||
log.error("Erreur lors de l'import CSV des utilisateurs", e);
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(new ErrorResponse(e.getMessage()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== DTOs internes ====================
|
||||
|
||||
@Schema(description = "Requête de réinitialisation de mot de passe")
|
||||
|
||||
Reference in New Issue
Block a user