Implemented Form Handling. Closes #4
parent
7366459279
commit
76ee50b63f
|
@ -0,0 +1,89 @@
|
|||
package de.nclazz.service.mailrelay;
|
||||
|
||||
import de.nclazz.service.mailrelay.domain.Relay;
|
||||
import de.nclazz.service.mailrelay.domain.RelayAccount;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest
|
||||
@ActiveProfiles("integration")
|
||||
@AutoConfigureMockMvc
|
||||
public class ForwardMessageFormTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
private static final LocalDateTime FIXED_TIME = LocalDateTime.of(2019, 4, 25, 13, 12);
|
||||
private static final String TOKEN = "my-token";
|
||||
|
||||
@TestConfiguration
|
||||
static class TestConfig {
|
||||
@Bean
|
||||
public Clock clock() {
|
||||
return FakeClock.fixed(FIXED_TIME);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Relay relay() {
|
||||
RelayAccount account = new RelayAccount(UUID.randomUUID(), "company-account", TOKEN, List.of("vip@company.com"));
|
||||
Relay relay = new Relay();
|
||||
relay.addAccount(account);
|
||||
return relay;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void forwardMessageRedirectsToOnSuccessUrl() throws Exception {
|
||||
mockMvc.perform(post("/form").contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.param("token", TOKEN)
|
||||
.param("subject", "subject")
|
||||
.param("message", "message")
|
||||
.param("from", "sender@company.com")
|
||||
.param("onSuccess", "http://mysite.com/next")
|
||||
)
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://mysite.com/next"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void forwardMessageRedirectsToRefererIfOnSuccessIsNotSet() throws Exception {
|
||||
mockMvc.perform(post("/form").contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.param("token", TOKEN)
|
||||
.param("subject", "subject")
|
||||
.param("message", "message")
|
||||
.param("from", "sender@company.com")
|
||||
.header("Referer", "http://myorigin.com")
|
||||
)
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://myorigin.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void forwardMessageRedirectsToOnErrorWhenAnErrorOccurs() throws Exception {
|
||||
mockMvc.perform(post("/form").contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.param("subject", "subject")
|
||||
.param("message", "message")
|
||||
.param("from", "sender@company.com")
|
||||
.param("onError", "http://myerrorsite.com")
|
||||
)
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://myerrorsite.com"));
|
||||
}
|
||||
|
||||
}
|
|
@ -35,17 +35,15 @@ public class ForwardMessageRestTest {
|
|||
|
||||
@TestConfiguration
|
||||
static class TestConfig {
|
||||
|
||||
@Bean
|
||||
public Clock clock() {
|
||||
return FakeClock.fixed(FIXED_TIME);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void forwardMessageReturnsForwardedMessageAndIsAlwaysOK() throws Exception {
|
||||
MessageForm form = new MessageForm("my-token", "subject", "message", "sender@company.com");
|
||||
MessageForm form = MessageForm.of("my-token", "subject", "message", "sender@company.com");
|
||||
Message message = form.toMessage(FIXED_TIME);
|
||||
|
||||
mockMvc.perform(post("/").contentType(APPLICATION_JSON)
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
package de.nclazz.service.mailrelay;
|
||||
|
||||
import de.nclazz.service.mailrelay.domain.Relay;
|
||||
import de.nclazz.service.mailrelay.domain.RelayAccount;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@SpringBootApplication
|
||||
public class MailRelayApplication {
|
||||
|
@ -18,4 +22,14 @@ public class MailRelayApplication {
|
|||
return Clock.systemDefaultZone();
|
||||
}
|
||||
|
||||
// Temporary setup for testing. Will be removed when persistence is enabled
|
||||
@Bean
|
||||
public Relay relay() {
|
||||
Relay relay = new Relay();
|
||||
RelayAccount account = new RelayAccount(UUID.randomUUID(), "My Company", "my-token", List.of("vip@mycompany.com"));
|
||||
relay.addAccount(account);
|
||||
|
||||
return relay;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,18 @@ public class MessageForm {
|
|||
private String content;
|
||||
private String from;
|
||||
|
||||
private String onSuccess;
|
||||
private String onError;
|
||||
|
||||
public static MessageForm of(String token, String subject, String content, String from) {
|
||||
MessageForm form = new MessageForm();
|
||||
form.setToken(token);
|
||||
form.setSubject(subject);
|
||||
form.setContent(content);
|
||||
form.setFrom(from);
|
||||
return form;
|
||||
}
|
||||
|
||||
public Message toMessage(@NonNull LocalDateTime timestamp) {
|
||||
return new Message(
|
||||
this.subject,
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package de.nclazz.service.mailrelay.adapter.web;
|
||||
|
||||
import de.nclazz.service.mailrelay.domain.Message;
|
||||
import de.nclazz.service.mailrelay.domain.Relay;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Controller
|
||||
@Slf4j
|
||||
@RequestMapping("form")
|
||||
@RequiredArgsConstructor
|
||||
public class MessageFormController {
|
||||
|
||||
private final Relay relay;
|
||||
private final Clock clock;
|
||||
|
||||
@PostMapping
|
||||
public String forwardMessage(@RequestHeader(name = "Referer", required = false)String referer,
|
||||
MessageForm form) {
|
||||
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();
|
||||
}
|
||||
|
||||
String redirect = referer;
|
||||
|
||||
if(form.getOnSuccess() != null) {
|
||||
redirect = form.getOnSuccess();
|
||||
}
|
||||
|
||||
return "redirect:" + redirect;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -2,14 +2,15 @@ package de.nclazz.service.mailrelay.domain;
|
|||
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.stereotype.Service;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
@Service
|
||||
@Slf4j
|
||||
//@Service
|
||||
public class Relay {
|
||||
|
||||
private final Set<RelayAccount> accounts = new HashSet<>();
|
||||
|
@ -18,7 +19,8 @@ public class Relay {
|
|||
this.accounts.add(account);
|
||||
}
|
||||
|
||||
public Message forwardMessage(String token, Message message) {
|
||||
public Message forwardMessage(@NonNull String token, @NonNull Message message) {
|
||||
log.info("Forward message '{}' to <{}>", message.getSubject(), token);
|
||||
Optional<RelayAccount> accountOptional = findAccountByToken(token);
|
||||
|
||||
if(accountOptional.isPresent()) {
|
||||
|
|
|
@ -3,12 +3,14 @@ package de.nclazz.service.mailrelay.domain;
|
|||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Data
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class RelayAccount {
|
||||
|
||||
|
@ -21,6 +23,7 @@ public class RelayAccount {
|
|||
private final List<Message> sentMessages = new ArrayList<>();
|
||||
|
||||
public Message forwardMessage(@NonNull Message message) {
|
||||
log.info("Forward message '{}' on <{}> ({} <{}>)", message.getSubject(), this.token, this.name, this.guid);
|
||||
this.sentMessages.add(message);
|
||||
return message;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package de.nclazz.service.mailrelay.adapter.web;
|
||||
|
||||
import de.nclazz.service.mailrelay.FakeClock;
|
||||
import de.nclazz.service.mailrelay.domain.Message;
|
||||
import de.nclazz.service.mailrelay.domain.Relay;
|
||||
import de.nclazz.service.mailrelay.domain.RelayAccount;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class MessageFormControllerTest {
|
||||
|
||||
@Test
|
||||
void forwardMessageShouldForwardMessageAccordingly() {
|
||||
String token = "my-token";
|
||||
RelayAccount account = new RelayAccount(
|
||||
UUID.randomUUID(),
|
||||
"relay account name",
|
||||
token,
|
||||
List.of("vip@account.com")
|
||||
);
|
||||
|
||||
Relay relay = new Relay();
|
||||
relay.addAccount(account);
|
||||
|
||||
LocalDateTime now = LocalDateTime.of(2020, 12, 24, 12, 54);
|
||||
Clock fakeClock = FakeClock.fixed(now);
|
||||
|
||||
MessageForm form = MessageForm.of(token, "Subject", "Message", "sender@company.com");
|
||||
|
||||
MessageFormController controller = new MessageFormController(relay, fakeClock);
|
||||
controller.forwardMessage("http://mysite.org", form);
|
||||
|
||||
|
||||
assertThat(account.getSentMessages())
|
||||
.hasSize(1)
|
||||
.containsExactly(new Message("Subject", "Message", "sender@company.com", now));
|
||||
}
|
||||
|
||||
}
|
|
@ -31,7 +31,7 @@ class MessageRestControllerTest {
|
|||
LocalDateTime now = LocalDateTime.of(2020, 12, 24, 12, 54);
|
||||
Clock fakeClock = FakeClock.fixed(now);
|
||||
|
||||
MessageForm form = new MessageForm(token, "Subject", "Message", "sender@company.com");
|
||||
MessageForm form = MessageForm.of(token, "Subject", "Message", "sender@company.com");
|
||||
|
||||
MessageRestController controller = new MessageRestController(relay, fakeClock);
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Mail Relay - Example</title>
|
||||
|
||||
<style>
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 650px;
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
padding: 0.5em;
|
||||
background-color: royalblue;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Mail Relay - Example</h1>
|
||||
|
||||
<form action="http://localhost:8080/form" method="post">
|
||||
<input type="hidden" name="token" value="my-token">
|
||||
<input type="hidden" name="onSuccess" value="/nclazz-mail-relay/example.html">
|
||||
<input type="text" name="subject" placeholder="Subject">
|
||||
<input type="text" name="from" placeholder="Email">
|
||||
<textarea name="content" placeholder="Message..." rows="12"></textarea>
|
||||
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue