diff --git a/pom.xml b/pom.xml
index c16e416..2126784 100644
--- a/pom.xml
+++ b/pom.xml
@@ -91,6 +91,11 @@
io.quarkus
quarkus-jsonb
+
+
+ io.quarkus
+ quarkus-flyway
+
org.projectlombok
lombok
diff --git a/src/main/java/com/lions/dev/config/OpenAPIConfig.java b/src/main/java/com/lions/dev/config/OpenAPIConfig.java
new file mode 100644
index 0000000..4dd7710
--- /dev/null
+++ b/src/main/java/com/lions/dev/config/OpenAPIConfig.java
@@ -0,0 +1,30 @@
+package com.lions.dev.config;
+
+import org.eclipse.microprofile.openapi.annotations.OpenAPIDefinition;
+import org.eclipse.microprofile.openapi.annotations.info.Info;
+import org.eclipse.microprofile.openapi.annotations.servers.Server;
+
+import jakarta.ws.rs.core.Application;
+
+/**
+ * Configuration OpenAPI pour l'API AfterWork.
+ *
+ * Cette classe configure les métadonnées OpenAPI et le serveur de base
+ * pour que Swagger UI génère correctement les URLs avec le root-path.
+ */
+@OpenAPIDefinition(
+ info = @Info(
+ title = "AfterWork API",
+ version = "1.0.0",
+ description = "API REST pour l'application AfterWork - Gestion d'événements, réseaux sociaux et messagerie"
+ ),
+ servers = {
+ @Server(
+ url = "https://api.lions.dev/afterwork",
+ description = "Serveur de production"
+ )
+ }
+)
+public class OpenAPIConfig extends Application {
+ // Classe de configuration OpenAPI
+}
diff --git a/src/main/java/com/lions/dev/dto/PasswordResetRequest.java b/src/main/java/com/lions/dev/dto/PasswordResetRequest.java
new file mode 100644
index 0000000..d0d0505
--- /dev/null
+++ b/src/main/java/com/lions/dev/dto/PasswordResetRequest.java
@@ -0,0 +1,19 @@
+package com.lions.dev.dto;
+
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+
+public class PasswordResetRequest {
+
+ @NotBlank(message = "L'email est obligatoire")
+ @Email(message = "Format d'email invalide")
+ private String email;
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+}
diff --git a/src/main/java/com/lions/dev/resource/UsersResource.java b/src/main/java/com/lions/dev/resource/UsersResource.java
index 877f66a..af6d5c8 100644
--- a/src/main/java/com/lions/dev/resource/UsersResource.java
+++ b/src/main/java/com/lions/dev/resource/UsersResource.java
@@ -1,5 +1,6 @@
package com.lions.dev.resource;
+import com.lions.dev.dto.PasswordResetRequest;
import com.lions.dev.dto.request.users.UserAuthenticateRequestDTO;
import com.lions.dev.dto.request.users.UserCreateRequestDTO;
import com.lions.dev.dto.response.users.UserAuthenticateResponseDTO;
@@ -17,8 +18,10 @@ import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.io.File;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.Operation;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger;
@@ -273,4 +276,46 @@ public class UsersResource {
}
}
+ /**
+ * Endpoint pour demander une réinitialisation de mot de passe par email.
+ *
+ * @param request Le DTO contenant l'email de l'utilisateur.
+ * @return Une réponse HTTP indiquant que l'email a été envoyé (ou non, pour ne pas révéler si l'email existe).
+ */
+ @POST
+ @Path("/forgot-password")
+ @Operation(summary = "Demander une reinitialisation de mot de passe par email",
+ description = "Envoie un email de reinitialisation si un compte existe avec cet email")
+ @APIResponse(responseCode = "200", description = "Email de reinitialisation envoye si le compte existe")
+ @APIResponse(responseCode = "400", description = "Email invalide")
+ public Response requestPasswordReset(@Valid PasswordResetRequest request) {
+ LOG.info("Demande de reinitialisation de mot de passe pour l'email : " + request.getEmail());
+
+ try {
+ // Rechercher l'utilisateur par email
+ Users user = userService.findByEmail(request.getEmail());
+
+ if (user != null) {
+ // TODO: Generer un token de reset et l'envoyer par email
+ // Pour l'instant, on retourne success pour ne pas reveler si l'email existe
+ // String resetToken = generateResetToken();
+ // emailService.sendPasswordResetEmail(user.getEmail(), resetToken);
+ LOG.info("Utilisateur trouve, email de reinitialisation devrait etre envoye : " + request.getEmail());
+ } else {
+ LOG.info("Aucun utilisateur trouve avec cet email (ne pas reveler) : " + request.getEmail());
+ }
+
+ // Toujours retourner 200 pour ne pas reveler si l'email existe
+ return Response.ok()
+ .entity(Map.of("message", "Si un compte existe avec cet email, un lien de reinitialisation a ete envoye"))
+ .build();
+ } catch (Exception e) {
+ LOG.error("Erreur lors de la demande de reinitialisation de mot de passe", e);
+ // Toujours retourner 200 pour ne pas reveler si l'email existe
+ return Response.ok()
+ .entity(Map.of("message", "Si un compte existe avec cet email, un lien de reinitialisation a ete envoye"))
+ .build();
+ }
+ }
+
}
diff --git a/src/main/java/com/lions/dev/service/UsersService.java b/src/main/java/com/lions/dev/service/UsersService.java
index 8999bc9..588c963 100644
--- a/src/main/java/com/lions/dev/service/UsersService.java
+++ b/src/main/java/com/lions/dev/service/UsersService.java
@@ -251,4 +251,16 @@ public class UsersService {
System.out.println("[LOG] Utilisateur trouvé avec l'email : " + email);
return userOptional.get();
}
+
+ /**
+ * Recherche un utilisateur par son email (retourne null si non trouvé).
+ * Utilisé pour les opérations où on ne veut pas lever d'exception si l'utilisateur n'existe pas.
+ *
+ * @param email L'email de l'utilisateur à rechercher.
+ * @return L'utilisateur trouvé ou null si non trouvé.
+ */
+ public Users findByEmail(String email) {
+ Optional userOptional = usersRepository.findByEmail(email);
+ return userOptional.orElse(null);
+ }
}
diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties
index 9a74a10..020845c 100644
--- a/src/main/resources/application-production.properties
+++ b/src/main/resources/application-production.properties
@@ -8,6 +8,21 @@
# HTTP - Chemin de base de l'API
# ====================================================================
# Permet d'accéder à l'API via https://api.lions.dev/afterwork
+#
+# IMPORTANT - Configuration Ingress requise:
+# Cette application utilise quarkus.http.root-path pour être "context-aware",
+# ce qui permet à Swagger UI de générer les bonnes URLs.
+# L'Ingress Kubernetes DOIT préserver le chemin complet (PAS de rewrite-target).
+#
+# Configuration Ingress correcte:
+# - path: /afterwork
+# - pathType: Prefix
+# - PAS d'annotation rewrite-target
+#
+# Pourquoi cette approche ?
+# - Swagger UI nécessite que l'application connaisse son contexte
+# - Les URLs générées (OpenAPI, WebSocket) sont correctes
+# - Cohérent avec les applications context-aware (btpxpress, etc.)
quarkus.http.root-path=/afterwork
# ====================================================================
@@ -17,10 +32,13 @@ quarkus.http.root-path=/afterwork
quarkus.swagger-ui.enable=true
quarkus.swagger-ui.always-include=true
quarkus.swagger-ui.path=/q/swagger-ui
-# Configuration explicite de l'URL OpenAPI pour Swagger UI
-# Avec root-path=/afterwork, l'OpenAPI spec est à /afterwork/openapi
-quarkus.swagger-ui.urls.default=/afterwork/openapi
+# Configuration du chemin OpenAPI (relatif au root-path)
quarkus.smallrye-openapi.path=/openapi
+# Configuration des serveurs OpenAPI pour que Swagger UI génère les bonnes URLs
+quarkus.smallrye-openapi.servers=https://api.lions.dev/afterwork
+# Configuration explicite de l'URL OpenAPI pour Swagger UI
+# Essayer avec URL absolue pour forcer le bon chemin
+quarkus.swagger-ui.urls.default=https://api.lions.dev/afterwork/openapi
# ====================================================================
# Base de données PostgreSQL
@@ -35,9 +53,18 @@ quarkus.datasource.jdbc.min-size=5
quarkus.datasource.devservices.enabled=false
# ====================================================================
-# Hibernate ORM
+# Flyway - Migrations SQL automatiques
# ====================================================================
-quarkus.hibernate-orm.database.generation=update
+quarkus.flyway.migrate-at-start=true
+quarkus.flyway.locations=db/migration
+quarkus.flyway.baseline-on-migrate=true
+quarkus.flyway.baseline-version=1
+quarkus.flyway.validate-on-migrate=true
+
+# ====================================================================
+# Hibernate ORM - Mode validation (Flyway gere le schema)
+# ====================================================================
+quarkus.hibernate-orm.database.generation=none
quarkus.hibernate-orm.log.sql=false
quarkus.hibernate-orm.sql-load-script=no-file
quarkus.hibernate-orm.jdbc.statement-batch-size=20
@@ -64,6 +91,23 @@ quarkus.log.category."com.lions.dev".level=INFO
quarkus.log.category."org.hibernate".level=WARN
quarkus.log.category."io.quarkus".level=INFO
+# ====================================================================
+# Kafka Configuration (Production)
+# ====================================================================
+# Kafka est deploye dans le namespace 'kafka' du cluster Kubernetes
+# Service: kafka-service.kafka.svc.cluster.local:9092
+kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVERS:kafka-service.kafka.svc.cluster.local:9092}
+
+# Configuration de resilience Kafka
+mp.messaging.connector.smallrye-kafka.health-enabled=true
+mp.messaging.connector.smallrye-kafka.health-readiness-enabled=true
+
+# Topics auto-crees par Quarkus SmallRye Kafka:
+# - notifications
+# - chat.messages
+# - reactions
+# - presence.updates
+
# ====================================================================
# WebSocket
# ====================================================================
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 2004b19..9967b7d 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -55,7 +55,7 @@ quarkus.http.limits.max-body-size=10M
# ====================================================================
# Kafka Configuration (commun à tous les environnements)
# ====================================================================
-kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVERS:localhost:9092}
+kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVERS:kafka-service.kafka.svc.cluster.local:9092}
# ====================================================================
# Kafka Topics - Outgoing (Services → Kafka)
diff --git a/src/main/resources/db/migration/V1__Baseline.sql b/src/main/resources/db/migration/V1__Baseline.sql
new file mode 100644
index 0000000..48f9883
--- /dev/null
+++ b/src/main/resources/db/migration/V1__Baseline.sql
@@ -0,0 +1,5 @@
+-- V1__Baseline.sql
+-- Script de baseline pour Flyway
+-- Ce script est vide car le schema initial a ete cree par Hibernate
+-- Flyway utilisera ce point comme reference pour les migrations suivantes
+SELECT 1;