Implemented Validation of MessageForm in RestController and FormController. Closes #13
parent
34e6e55ea4
commit
333ee23c42
|
@ -88,5 +88,4 @@ public class ForwardMessageFormTest {
|
|||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://myerrorsite.com"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.springframework.test.web.servlet.MockMvc;
|
|||
import java.time.Clock;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
@ -53,4 +54,15 @@ public class ForwardMessageRestTest {
|
|||
.andExpect(jsonPath("$.timestamp").value("2019-04-25T13:12:00"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void forwardMessageWithInvalidFormReturns400StatusCode() throws Exception {
|
||||
MessageForm form = MessageForm.of("", null, "", "sender @ company.com");
|
||||
|
||||
mockMvc.perform(post("/").contentType(APPLICATION_JSON)
|
||||
.content(mapper.writeValueAsString(form)))
|
||||
.andExpect(status().is4xxClientError())
|
||||
.andExpect(content().contentType(APPLICATION_JSON))
|
||||
.andExpect(jsonPath("$.[*].target").value(containsInAnyOrder("token", "subject", "content", "from")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,23 +5,19 @@ import de.nclazz.service.mailrelay.domain.Relay;
|
|||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("accounts")
|
||||
|
@ -62,13 +58,4 @@ public class AccountRestController {
|
|||
account.setReceivers(form.getReceivers());
|
||||
return this.relay.saveAccount(account);
|
||||
}
|
||||
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public List<ValidationError> handleValidationExceptions(MethodArgumentNotValidException ex) {
|
||||
return ex.getBindingResult()
|
||||
.getAllErrors().stream()
|
||||
.map(ValidationError::fromObjectError)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
package de.nclazz.service.mailrelay.adapter.web;
|
||||
|
||||
import de.nclazz.service.mailrelay.domain.Message;
|
||||
import de.nclazz.service.mailrelay.domain.StringUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
|
@ -13,12 +16,20 @@ import java.time.LocalDateTime;
|
|||
@NoArgsConstructor
|
||||
public class MessageForm {
|
||||
|
||||
@NotBlank
|
||||
private String token;
|
||||
|
||||
@NotBlank
|
||||
private String subject;
|
||||
|
||||
@NotBlank
|
||||
private String content;
|
||||
|
||||
@Pattern(regexp = StringUtils.EMAIL_RFC_5322_REGEX)
|
||||
@NotBlank
|
||||
private String from;
|
||||
|
||||
|
||||
private String onSuccess;
|
||||
private String onError;
|
||||
|
||||
|
|
|
@ -5,10 +5,12 @@ import de.nclazz.service.mailrelay.domain.Relay;
|
|||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.time.Clock;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
|
@ -23,16 +25,17 @@ public class MessageFormController {
|
|||
|
||||
@PostMapping
|
||||
public String forwardMessage(@RequestHeader(name = "Referer", required = false)String referer,
|
||||
MessageForm form) {
|
||||
@Valid MessageForm form,
|
||||
BindingResult bindingResult) {
|
||||
|
||||
if(bindingResult.hasErrors()) {
|
||||
return "redirect:" + form.getOnError();
|
||||
}
|
||||
|
||||
String token = form.getToken();
|
||||
Message message = form.toMessage(LocalDateTime.now(this.clock));
|
||||
|
||||
try {
|
||||
this.relay.forwardMessage(token, message);
|
||||
}catch(Exception e) {
|
||||
log.error("An error occurred", e);
|
||||
return "redirect:" + form.getOnError();
|
||||
}
|
||||
this.relay.forwardMessage(token, message);
|
||||
|
||||
String redirect = referer;
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.PostMapping;
|
|||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.time.Clock;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
|
@ -18,7 +19,7 @@ public class MessageRestController {
|
|||
private final Clock clock;
|
||||
|
||||
@PostMapping
|
||||
public Message forwardMessage(@RequestBody MessageForm form) {
|
||||
public Message forwardMessage(@RequestBody @Valid MessageForm form) {
|
||||
String token = form.getToken();
|
||||
Message message = form.toMessage(LocalDateTime.now(this.clock));
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package de.nclazz.service.mailrelay.adapter.web;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ControllerAdvice
|
||||
public class NotValidExceptionHandler extends ResponseEntityExceptionHandler {
|
||||
|
||||
|
||||
@Override
|
||||
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
return ResponseEntity
|
||||
.badRequest()
|
||||
.body(mapBindingResultToValidationErrors(ex));
|
||||
}
|
||||
|
||||
private List<ValidationError> mapBindingResultToValidationErrors(MethodArgumentNotValidException ex) {
|
||||
return ex.getBindingResult()
|
||||
.getAllErrors().stream()
|
||||
.map(ValidationError::fromObjectError)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@ import de.nclazz.service.mailrelay.domain.Account;
|
|||
import de.nclazz.service.mailrelay.domain.Relay;
|
||||
import de.nclazz.service.mailrelay.domain.TestRelayBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.validation.BindingResult;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.LocalDateTime;
|
||||
|
@ -12,6 +13,7 @@ import java.util.List;
|
|||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
class MessageFormControllerTest {
|
||||
|
||||
|
@ -34,7 +36,7 @@ class MessageFormControllerTest {
|
|||
MessageForm form = MessageForm.of(token, "Subject", "Message", "sender@company.com");
|
||||
|
||||
MessageFormController controller = new MessageFormController(relay, fakeClock);
|
||||
controller.forwardMessage("http://mysite.org", form);
|
||||
controller.forwardMessage("http://mysite.org", form, mock(BindingResult.class));
|
||||
|
||||
assertThat(account.getSentMessages())
|
||||
.hasSize(1)
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package de.nclazz.service.mailrelay.adapter.web;
|
||||
|
||||
import org.hibernate.validator.HibernateValidator;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class MessageFormValidationTest {
|
||||
|
||||
private LocalValidatorFactoryBean localValidatorFactory;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
localValidatorFactory = new LocalValidatorFactoryBean();
|
||||
localValidatorFactory.setProviderClass(HibernateValidator.class);
|
||||
localValidatorFactory.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
void tokenAsNullStringShouldBeNotValid() {
|
||||
MessageForm form = MessageForm.of(null, "My Subject", "My Content", "mail@me.com");
|
||||
|
||||
assertThat(localValidatorFactory.validate(form))
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void tokenAsEmptyStringShouldBeNotValid() {
|
||||
MessageForm form = MessageForm.of("", "My Subject", "My Content", "mail@me.com");
|
||||
|
||||
assertThat(localValidatorFactory.validate(form))
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void subjectAsNullStringShouldBeNotValid() {
|
||||
MessageForm form = MessageForm.of("mytoken", null, "My Content", "mail@me.com");
|
||||
|
||||
assertThat(localValidatorFactory.validate(form))
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void subjectAsEmptyStringShouldBeNotValid() {
|
||||
MessageForm form = MessageForm.of("mytoken", "", "My Content", "mail@me.com");
|
||||
|
||||
assertThat(localValidatorFactory.validate(form))
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void contentAsNullStringShouldBeNotValid() {
|
||||
MessageForm form = MessageForm.of("mytoken", "Subject", null, "mail@me.com");
|
||||
|
||||
assertThat(localValidatorFactory.validate(form))
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void contentAsEmptyStringShouldBeNotValid() {
|
||||
MessageForm form = MessageForm.of("mytoken", "Subject", "", "mail@me.com");
|
||||
|
||||
assertThat(localValidatorFactory.validate(form))
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void fromAsNullStringShouldBeNotValid() {
|
||||
MessageForm form = MessageForm.of("mytoken", "Subject", "My Content", null);
|
||||
|
||||
assertThat(localValidatorFactory.validate(form))
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void fromAsEmptyStringShouldBeNotValid() {
|
||||
MessageForm form = MessageForm.of("mytoken", "Subject", "My Content", "");
|
||||
|
||||
assertThat(localValidatorFactory.validate(form))
|
||||
.isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void fromAsInvalidMailAddressShouldBeNotValid() {
|
||||
MessageForm form = MessageForm.of("mytoken", "Subject", "My Content", "invalid @ mail+address.com");
|
||||
|
||||
assertThat(localValidatorFactory.validate(form))
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue