chore(quarkus-327): bump to Quarkus 3.27.3 LTS, rename quarkus-resteasy-reactive → quarkus-rest, fix testGetAuditQuestions map vs list, rename deprecated config keys

This commit is contained in:
2026-04-23 14:47:47 +00:00
parent c336984bec
commit 51265fb0fa
127 changed files with 17488 additions and 9557 deletions

View File

@@ -1,201 +1,201 @@
package dev.lions.services;
import dev.lions.models.EmailMessage;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import dev.lions.config.ApplicationConfig;
import dev.lions.models.EmailTemplate;
import dev.lions.models.Notification;
import dev.lions.exceptions.EmailException;
import dev.lions.utils.TemplateProcessor;
import java.util.Map;
import java.util.Properties;
/**
* Service gérant l'envoi des emails dans l'application.
* Cette classe assure la configuration SMTP, le traitement des modèles
* et l'envoi sécurisé des emails.
*/
@Slf4j
@ApplicationScoped
public class EmailService {
@Inject
ApplicationConfig config;
@Inject
TemplateProcessor templateProcessor;
private static final int MAX_RETRY_ATTEMPTS = 3;
private static final long RETRY_DELAY_MS = 1000;
/**
* Envoie un email basé sur un modèle.
*
* @param template Modèle d'email à utiliser
*/
public void sendTemplatedEmail(@Valid @NotNull EmailTemplate template) {
log.info("Préparation de l'envoi d'email avec le modèle : {}",
template.getTemplateName());
try {
String htmlContent = processTemplate(template);
EmailMessage message = EmailMessage.builder()
.from(config.getSystemEmailAddress())
.to(template.getRecipient())
.subject(template.getSubject())
.htmlContent(htmlContent)
.build();
sendEmailWithRetry(message);
} catch (Exception e) {
log.error("Erreur lors de l'envoi de l'email", e);
throw new EmailException("Impossible d'envoyer l'email");
}
}
/**
* Traite le contenu du modèle avec les paramètres fournis.
*/
private String processTemplate(EmailTemplate template) {
log.debug("Traitement du modèle d'email : {}", template.getTemplateName());
return templateProcessor.process(
template.getContent(),
template.getParameters()
);
}
/**
* Envoie un email avec mécanisme de reprise en cas d'échec.
*/
private void sendEmailWithRetry(EmailMessage message) {
Exception lastException = null;
for (int attempt = 1; attempt <= MAX_RETRY_ATTEMPTS; attempt++) {
try {
sendEmail(message);
log.info("Email envoyé avec succès à : {}", message.getTo());
return;
} catch (Exception e) {
lastException = e;
log.warn("Échec de l'envoi (tentative {}/{})",
attempt, MAX_RETRY_ATTEMPTS);
if (attempt < MAX_RETRY_ATTEMPTS) {
sleep(RETRY_DELAY_MS * attempt);
}
}
}
throw new EmailException(
"Échec de l'envoi après " + MAX_RETRY_ATTEMPTS + " tentatives");
}
/**
* Envoie effectif de l'email via SMTP.
*/
private void sendEmail(EmailMessage message) throws MessagingException {
Properties props = configureSmtpProperties();
Session session = createSmtpSession(props);
MimeMessage mimeMessage = new MimeMessage(session);
configureMimeMessage(mimeMessage, message);
Transport.send(mimeMessage);
}
/**
* Configure les propriétés SMTP.
*/
private Properties configureSmtpProperties() {
Properties props = new Properties();
props.put("mail.smtp.host", config.getSmtpHost());
props.put("mail.smtp.port", config.getSmtpPort());
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.connectiontimeout", "5000");
props.put("mail.smtp.timeout", "5000");
if (config.isSmtpSslEnabled()) {
props.put("mail.smtp.ssl.enable", "true");
props.put("mail.smtp.ssl.trust", config.getSmtpHost());
}
return props;
}
/**
* Crée une session SMTP authentifiée.
*/
private Session createSmtpSession(Properties props) {
return Session.getInstance(props, new jakarta.mail.Authenticator() {
@Override
protected jakarta.mail.PasswordAuthentication getPasswordAuthentication() {
return new jakarta.mail.PasswordAuthentication(
config.getSmtpUsername().orElseThrow(() ->
new EmailException("Nom d'utilisateur SMTP manquant")),
config.getSmtpPassword().orElseThrow(() ->
new EmailException("Mot de passe SMTP manquant"))
);
}
});
}
/**
* Configure le message MIME avec les paramètres fournis.
*/
private void configureMimeMessage(MimeMessage mimeMessage, EmailMessage message)
throws MessagingException {
mimeMessage.setFrom(new InternetAddress(message.getFrom()));
mimeMessage.setRecipients(
Message.RecipientType.TO,
InternetAddress.parse(message.getTo())
);
mimeMessage.setSubject(message.getSubject());
mimeMessage.setContent(message.getHtmlContent(), "text/html; charset=utf-8");
}
/**
* Envoie une notification par email.
*/
public void sendNotificationEmail(@NotNull Notification notification) {
EmailTemplate template = EmailTemplate.builder()
.templateName("notification-email")
.recipient(config.getAdminEmailAddress())
.subject("Notification système : " + notification.getTitle())
.parameters(Map.of(
"title", notification.getTitle(),
"message", notification.getMessage(),
"type", notification.getType().toString(),
"timestamp", notification.getTimestamp().toString(),
"actionUrl", notification.getActionUrl()
))
.build();
sendTemplatedEmail(template);
}
private void sleep(long milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new EmailException("Interruption pendant la reprise");
}
}
}
package dev.lions.services;
import dev.lions.models.EmailMessage;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import dev.lions.config.ApplicationConfig;
import dev.lions.models.EmailTemplate;
import dev.lions.models.Notification;
import dev.lions.exceptions.EmailException;
import dev.lions.utils.TemplateProcessor;
import java.util.Map;
import java.util.Properties;
/**
* Service gérant l'envoi des emails dans l'application.
* Cette classe assure la configuration SMTP, le traitement des modèles
* et l'envoi sécurisé des emails.
*/
@Slf4j
@ApplicationScoped
public class EmailService {
@Inject
ApplicationConfig config;
@Inject
TemplateProcessor templateProcessor;
private static final int MAX_RETRY_ATTEMPTS = 3;
private static final long RETRY_DELAY_MS = 1000;
/**
* Envoie un email basé sur un modèle.
*
* @param template Modèle d'email à utiliser
*/
public void sendTemplatedEmail(@Valid @NotNull EmailTemplate template) {
log.info("Préparation de l'envoi d'email avec le modèle : {}",
template.getTemplateName());
try {
String htmlContent = processTemplate(template);
EmailMessage message = EmailMessage.builder()
.from(config.getSystemEmailAddress())
.to(template.getRecipient())
.subject(template.getSubject())
.htmlContent(htmlContent)
.build();
sendEmailWithRetry(message);
} catch (Exception e) {
log.error("Erreur lors de l'envoi de l'email", e);
throw new EmailException("Impossible d'envoyer l'email");
}
}
/**
* Traite le contenu du modèle avec les paramètres fournis.
*/
private String processTemplate(EmailTemplate template) {
log.debug("Traitement du modèle d'email : {}", template.getTemplateName());
return templateProcessor.process(
template.getContent(),
template.getParameters()
);
}
/**
* Envoie un email avec mécanisme de reprise en cas d'échec.
*/
private void sendEmailWithRetry(EmailMessage message) {
Exception lastException = null;
for (int attempt = 1; attempt <= MAX_RETRY_ATTEMPTS; attempt++) {
try {
sendEmail(message);
log.info("Email envoyé avec succès à : {}", message.getTo());
return;
} catch (Exception e) {
lastException = e;
log.warn("Échec de l'envoi (tentative {}/{})",
attempt, MAX_RETRY_ATTEMPTS);
if (attempt < MAX_RETRY_ATTEMPTS) {
sleep(RETRY_DELAY_MS * attempt);
}
}
}
throw new EmailException(
"Échec de l'envoi après " + MAX_RETRY_ATTEMPTS + " tentatives");
}
/**
* Envoie effectif de l'email via SMTP.
*/
private void sendEmail(EmailMessage message) throws MessagingException {
Properties props = configureSmtpProperties();
Session session = createSmtpSession(props);
MimeMessage mimeMessage = new MimeMessage(session);
configureMimeMessage(mimeMessage, message);
Transport.send(mimeMessage);
}
/**
* Configure les propriétés SMTP.
*/
private Properties configureSmtpProperties() {
Properties props = new Properties();
props.put("mail.smtp.host", config.getSmtpHost());
props.put("mail.smtp.port", config.getSmtpPort());
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.connectiontimeout", "5000");
props.put("mail.smtp.timeout", "5000");
if (config.isSmtpSslEnabled()) {
props.put("mail.smtp.ssl.enable", "true");
props.put("mail.smtp.ssl.trust", config.getSmtpHost());
}
return props;
}
/**
* Crée une session SMTP authentifiée.
*/
private Session createSmtpSession(Properties props) {
return Session.getInstance(props, new jakarta.mail.Authenticator() {
@Override
protected jakarta.mail.PasswordAuthentication getPasswordAuthentication() {
return new jakarta.mail.PasswordAuthentication(
config.getSmtpUsername().orElseThrow(() ->
new EmailException("Nom d'utilisateur SMTP manquant")),
config.getSmtpPassword().orElseThrow(() ->
new EmailException("Mot de passe SMTP manquant"))
);
}
});
}
/**
* Configure le message MIME avec les paramètres fournis.
*/
private void configureMimeMessage(MimeMessage mimeMessage, EmailMessage message)
throws MessagingException {
mimeMessage.setFrom(new InternetAddress(message.getFrom()));
mimeMessage.setRecipients(
Message.RecipientType.TO,
InternetAddress.parse(message.getTo())
);
mimeMessage.setSubject(message.getSubject());
mimeMessage.setContent(message.getHtmlContent(), "text/html; charset=utf-8");
}
/**
* Envoie une notification par email.
*/
public void sendNotificationEmail(@NotNull Notification notification) {
EmailTemplate template = EmailTemplate.builder()
.templateName("notification-email")
.recipient(config.getAdminEmailAddress())
.subject("Notification système : " + notification.getTitle())
.parameters(Map.of(
"title", notification.getTitle(),
"message", notification.getMessage(),
"type", notification.getType().toString(),
"timestamp", notification.getTimestamp().toString(),
"actionUrl", notification.getActionUrl()
))
.build();
sendTemplatedEmail(template);
}
private void sleep(long milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new EmailException("Interruption pendant la reprise");
}
}
}