feat(validation): add request and domain validation for email use case
This commit is contained in:
parent
421d160c12
commit
fff9362ea8
@ -5,6 +5,7 @@ import com.pablotj.restemailbridge.application.port.in.EmailDefaultConfigPort;
|
|||||||
import com.pablotj.restemailbridge.application.port.out.EmailPort;
|
import com.pablotj.restemailbridge.application.port.out.EmailPort;
|
||||||
import com.pablotj.restemailbridge.domain.model.Email;
|
import com.pablotj.restemailbridge.domain.model.Email;
|
||||||
import com.pablotj.restemailbridge.domain.repository.EmailRepository;
|
import com.pablotj.restemailbridge.domain.repository.EmailRepository;
|
||||||
|
import com.pablotj.restemailbridge.domain.service.EmailValidatorService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -18,20 +19,13 @@ public class SendEmailUseCase {
|
|||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(SendEmailUseCase.class);
|
private static final Logger log = LoggerFactory.getLogger(SendEmailUseCase.class);
|
||||||
|
|
||||||
|
private final EmailValidatorService emailValidatorService;
|
||||||
private final EmailDefaultConfigPort emailConfigurationPort;
|
private final EmailDefaultConfigPort emailConfigurationPort;
|
||||||
private final EmailPort emailService;
|
private final EmailPort emailService;
|
||||||
private final EmailRepository emailRepository;
|
private final EmailRepository emailRepository;
|
||||||
|
|
||||||
/**
|
public SendEmailUseCase(EmailValidatorService emailValidatorService, EmailDefaultConfigPort emailConfigurationPort, EmailPort emailService, EmailRepository emailRepository) {
|
||||||
* Constructor injecting required ports.
|
this.emailValidatorService = emailValidatorService;
|
||||||
*
|
|
||||||
* @param emailConfigurationPort Port to retrieve configuration
|
|
||||||
* @param emailService Service to send emails
|
|
||||||
* @param emailRepository Repository to persist emails
|
|
||||||
*/
|
|
||||||
public SendEmailUseCase(EmailDefaultConfigPort emailConfigurationPort,
|
|
||||||
EmailPort emailService,
|
|
||||||
EmailRepository emailRepository) {
|
|
||||||
this.emailConfigurationPort = emailConfigurationPort;
|
this.emailConfigurationPort = emailConfigurationPort;
|
||||||
this.emailService = emailService;
|
this.emailService = emailService;
|
||||||
this.emailRepository = emailRepository;
|
this.emailRepository = emailRepository;
|
||||||
@ -44,16 +38,19 @@ public class SendEmailUseCase {
|
|||||||
*/
|
*/
|
||||||
public void handle(EmailDTO emailDTO) {
|
public void handle(EmailDTO emailDTO) {
|
||||||
String to = emailConfigurationPort.getDefaultRecipient();
|
String to = emailConfigurationPort.getDefaultRecipient();
|
||||||
|
|
||||||
|
Email email = Email.builder()
|
||||||
|
.from(emailDTO.from())
|
||||||
|
.to(to)
|
||||||
|
.subject(emailDTO.subject())
|
||||||
|
.body(emailDTO.body())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
emailValidatorService.validate(email);
|
||||||
|
|
||||||
log.info("Sending email from {} to {}", emailDTO.from(), to);
|
log.info("Sending email from {} to {}", emailDTO.from(), to);
|
||||||
|
|
||||||
Email email = emailService.sendEmail(
|
email = emailService.sendEmail(email);
|
||||||
Email.builder()
|
|
||||||
.from(emailDTO.from())
|
|
||||||
.to(to)
|
|
||||||
.subject(emailDTO.subject())
|
|
||||||
.body(emailDTO.body())
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
|
|
||||||
emailRepository.save(email);
|
emailRepository.save(email);
|
||||||
log.info("Email successfully sent and persisted to repository for recipient {}", to);
|
log.info("Email successfully sent and persisted to repository for recipient {}", to);
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.pablotj.restemailbridge.domain.service;
|
||||||
|
|
||||||
|
import com.pablotj.restemailbridge.domain.model.Email;
|
||||||
|
|
||||||
|
|
||||||
|
public class EmailValidatorService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates business rules for Email.
|
||||||
|
*/
|
||||||
|
public void validate(Email email) {
|
||||||
|
if (email == null) throw new IllegalArgumentException("Email cannot be null");
|
||||||
|
if (email.getTo() == null || !email.getTo().matches(".+@.+\\..+"))
|
||||||
|
throw new IllegalArgumentException("Recipient email is invalid");
|
||||||
|
if (email.getFrom() == null || email.getFrom().isBlank())
|
||||||
|
throw new IllegalArgumentException("Sender email is required");
|
||||||
|
if (email.getSubject() == null || email.getSubject().isBlank())
|
||||||
|
throw new IllegalArgumentException("Subject is required");
|
||||||
|
if (email.getBody() == null || email.getBody().isBlank())
|
||||||
|
throw new IllegalArgumentException("Body is required");
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ import com.pablotj.restemailbridge.application.port.in.EmailDefaultConfigPort;
|
|||||||
import com.pablotj.restemailbridge.application.port.out.EmailPort;
|
import com.pablotj.restemailbridge.application.port.out.EmailPort;
|
||||||
import com.pablotj.restemailbridge.application.usecase.SendEmailUseCase;
|
import com.pablotj.restemailbridge.application.usecase.SendEmailUseCase;
|
||||||
import com.pablotj.restemailbridge.domain.repository.EmailRepository;
|
import com.pablotj.restemailbridge.domain.repository.EmailRepository;
|
||||||
|
import com.pablotj.restemailbridge.domain.service.EmailValidatorService;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@ -12,6 +13,6 @@ public class UseCaseConfig {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SendEmailUseCase sendEmailUseCase(EmailDefaultConfigPort emailConfigurationPort, EmailPort emailService, EmailRepository emailRepository) {
|
public SendEmailUseCase sendEmailUseCase(EmailDefaultConfigPort emailConfigurationPort, EmailPort emailService, EmailRepository emailRepository) {
|
||||||
return new SendEmailUseCase(emailConfigurationPort, emailService, emailRepository);
|
return new SendEmailUseCase(new EmailValidatorService(), emailConfigurationPort, emailService, emailRepository);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -19,15 +19,15 @@ public class MailJpa {
|
|||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Column(nullable = false)
|
@Column(length = 100, nullable = false)
|
||||||
private String sender;
|
private String sender;
|
||||||
|
|
||||||
@Column(nullable = false)
|
@Column(length = 100, nullable = false)
|
||||||
private String recipient;
|
private String recipient;
|
||||||
|
|
||||||
@Column(nullable = false)
|
@Column(length = 50, nullable = false)
|
||||||
private String subjet;
|
private String subjet;
|
||||||
|
|
||||||
@Column(nullable = false)
|
@Column(length = 40000, nullable = false)
|
||||||
private String body;
|
private String body;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.pablotj.restemailbridge.infrastructure.rest;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||||
|
public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
|
||||||
|
Map<String, String> errors = new HashMap<>();
|
||||||
|
ex.getBindingResult().getFieldErrors().forEach(error ->
|
||||||
|
errors.put(error.getField(), error.getDefaultMessage()));
|
||||||
|
return ResponseEntity.badRequest().body(errors);
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,12 @@
|
|||||||
package com.pablotj.restemailbridge.infrastructure.rest.dto;
|
package com.pablotj.restemailbridge.infrastructure.rest.dto;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Email;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
|
||||||
public record SendMailRequest(
|
public record SendMailRequest(
|
||||||
String from,
|
@NotBlank @Email @Length(min = 4, max = 100) String from,
|
||||||
String subject,
|
@NotBlank @Length(min=1, max = 30) String subject,
|
||||||
String body
|
@NotBlank @Length(min=1, max = 4000) String body
|
||||||
) {
|
) {
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user