Implemented Form Handling. Closes #4

pull/21/head
Niclas Thobaben 2022-02-14 16:11:38 +01:00
parent 7366459279
commit 76ee50b63f
10 changed files with 256 additions and 7 deletions

View File

@ -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"));
}
}

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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;
}
}

View File

@ -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()) {

View File

@ -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;
}

View File

@ -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));
}
}

View File

@ -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);

View File

@ -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>