Jottyfan 2022-12-30 21:56:01 +01:00
parent 5fb79908f5
commit 06d87a2cd6
9 changed files with 252 additions and 8 deletions

View File

@ -18,7 +18,7 @@ apply plugin: 'war'
apply plugin: 'application' apply plugin: 'application'
group = 'de.jottyfan.camporganizer' group = 'de.jottyfan.camporganizer'
version = '0.2.4' version = '0.2.5'
sourceCompatibility = 17 sourceCompatibility = 17
mainClassName = "de.jottyfan.camporganizer.Main" mainClassName = "de.jottyfan.camporganizer.Main"

View File

@ -1,12 +1,22 @@
package de.jottyfan.camporganizer.module.admin; package de.jottyfan.camporganizer.module.admin;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import de.jottyfan.camporganizer.module.camplist.CommonController; import de.jottyfan.camporganizer.module.camplist.CommonController;
import de.jottyfan.camporganizer.module.mail.MailBean;
/** /**
* *
@ -16,6 +26,37 @@ import de.jottyfan.camporganizer.module.camplist.CommonController;
@Controller @Controller
public class AdminController extends CommonController { public class AdminController extends CommonController {
private static final Logger LOGGER = LogManager.getLogger(AdminController.class);
@Autowired
private AdminService service;
@Value("${spring.mail.username}")
private String from;
@GetMapping("/admin/mail")
public String getMail(Model model, HttpServletRequest request) {
super.setupSession(model, request);
MailBean mailBean = new MailBean();
mailBean.setFrom(from);
mailBean.getTo().add(getCurrentEmail(request));
model.addAttribute("bean", mailBean);
return "/admin/mail";
}
@PostMapping("/admin/mail/send")
public String sendMail(@Valid @ModelAttribute("bean") MailBean bean, final BindingResult bindingResult, Model model,
HttpServletRequest request) {
super.setupSession(model, request);
if (bindingResult.hasErrors()) {
for (ObjectError error : bindingResult.getAllErrors())
LOGGER.error("error {}: {}", error.getCode(), error.getDefaultMessage());
return "/admin/mail";
}
service.sendMail(bean);
return "redirect:/admin";
}
@GetMapping("/admin") @GetMapping("/admin")
public String getMain(Model model, HttpServletRequest request) { public String getMain(Model model, HttpServletRequest request) {
super.setupSession(model, request); super.setupSession(model, request);

View File

@ -0,0 +1,26 @@
package de.jottyfan.camporganizer.module.admin;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.module.mail.MailBean;
import de.jottyfan.camporganizer.module.mail.MailRepository;
/**
*
* @author jotty
*
*/
@Service
public class AdminService {
@Autowired
private MailRepository mailRepository;
public void sendMail(@Valid MailBean bean) {
mailRepository.sendMail(bean);
}
}

View File

@ -24,6 +24,18 @@ public abstract class CommonController {
return ksc == null ? null : ksc.getIdToken().getPreferredUsername(); return ksc == null ? null : ksc.getIdToken().getPreferredUsername();
} }
/**
* try to get th currnt keycloak email
*
* @param request the request
* @return the email or null
*/
public String getCurrentEmail(HttpServletRequest request) {
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request
.getAttribute(KeycloakSecurityContext.class.getName());
return ksc == null ? null : ksc.getIdToken().getEmail();
}
/** /**
* setup the session for the template * setup the session for the template
* *

View File

@ -12,9 +12,7 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -38,6 +36,7 @@ import de.jottyfan.camporganizer.db.jooq.tables.records.TCampRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord; import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TRssRecord; import de.jottyfan.camporganizer.db.jooq.tables.records.TRssRecord;
import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper; import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
import de.jottyfan.camporganizer.module.mail.MailBean;
import de.jottyfan.camporganizer.module.mail.MailRepository; import de.jottyfan.camporganizer.module.mail.MailRepository;
/** /**
@ -251,11 +250,13 @@ public class PersonGateway {
} }
} }
if (sendMail) { if (sendMail) {
Set<String> to = new HashSet<>();
to.add(email);
to.add(bean.getEmail());
try { try {
mailRepository.sendMail(to, subject, buf.toString()); // no matter if the sending works MailBean mailBean = new MailBean();
mailBean.getTo().add(email);
mailBean.getTo().add(bean.getEmail());
mailBean.setSubject(subject);
mailBean.setMessage(buf.toString());
mailRepository.sendMail(mailBean); // no matter if the sending works
} catch (Exception e) { } catch (Exception e) {
LOGGER.error(e.getMessage(), e); LOGGER.error(e.getMessage(), e);
} }

View File

@ -0,0 +1,94 @@
package de.jottyfan.camporganizer.module.mail;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
/**
*
* @author jotty
*
*/
public class MailBean implements Serializable {
private static final long serialVersionUID = 1L;
@NotEmpty
private final Set<String> to;
@NotBlank
private String from;
private String subject;
private String message;
public MailBean() {
this.to = new HashSet<>();
}
public String getTos() {
StringBuilder buf = new StringBuilder();
boolean first = true;
for (String s : to) {
buf.append(first ? "" : ";").append(s);
first = false;
}
return buf.toString();
}
public void setTos(String tos) {
this.to.clear();
this.to.addAll(List.of(tos.split(";")));
}
/**
* @return the from
*/
public String getFrom() {
return from;
}
/**
* @param from the from to set
*/
public void setFrom(String from) {
this.from = from;
}
/**
* @return the subject
*/
public String getSubject() {
return subject;
}
/**
* @param subject the subject to set
*/
public void setSubject(String subject) {
this.subject = subject;
}
/**
* @return the message
*/
public String getMessage() {
return message;
}
/**
* @param message the message to set
*/
public void setMessage(String message) {
this.message = message;
}
/**
* @return the to
*/
public Set<String> getTo() {
return to;
}
}

View File

@ -30,6 +30,16 @@ public class MailRepository {
@Value("${spring.mail.username}") @Value("${spring.mail.username}")
private String username; private String username;
/**
* Send an email with the message to the recipient. If email is blank, do
* nothing
*
* @param bean the mail
*/
public void sendMail(MailBean bean) {
sendMail(bean.getTo(), bean.getSubject(), bean.getMessage());
}
/** /**
* Send an email with the message to the recipient. If email is blank, do * Send an email with the message to the recipient. If email is blank, do
* nothing * nothing
@ -38,7 +48,7 @@ public class MailRepository {
* @param subject the subject * @param subject the subject
* @param message the message * @param message the message
*/ */
public void sendMail(Set<String> to, String subject, String message) { private void sendMail(Set<String> to, String subject, String message) {
if (to != null && to.size() > 0) { if (to != null && to.size() > 0) {
if (username != null && !username.isBlank()) { if (username != null && !username.isBlank()) {
try { try {

View File

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" layout:decorate="~{template}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<title>Camp Organizer Confirmation</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<th:block layout:fragment="header">
<ul class="navbar-nav mb-2 mb-lg-0">
<li class="nav-item"><a th:href="@{/}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
</ul>
<ul class="navbar-nav mb-2 mb-lg-0" sec:authorize="hasRole('admin')">
<li class="nav-item"><a th:href="@{/admin}" class="btn btn-seconary btn-icon-silent">Admin</a></li>
</ul>
</th:block>
<th:block layout:fragment="content">
<div sec:authorize="hasRole('admin')">
<form th:action="@{/admin/mail/send}" th:object="${bean}" method="post">
<div class="card" style="max-width: 1024px; margin-left: auto; margin-right: auto">
<div class="card-header">
<span>eine Test-E-Mail verschicken</span>
</div>
<div class="card-body">
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-3">Absender</div>
<div class="col-sm-12 col-md-9">
<span th:text="${bean.from}"></span> <input type="hidden" th:field="*{from}" />
</div>
<span class="error" th:each="error : ${#fields.errors('from')}">[[${error}]]<br /></span>
<div class="col-sm-12 col-md-3">Empfänger</div>
<div class="col-sm-12 col-md-9">
<span th:text="${bean.tos}"></span> <input type="hidden" th:field="*{tos}" />
</div>
<span class="error" th:each="error : ${#fields.errors('tos')}">[[${error}]]<br /></span>
<div class="col-sm-12 col-md-3">Betreff</div>
<div class="col-sm-12 col-md-9">
<input type="text" th:field="*{subject}" th:class="${'form-control ' + (#fields.hasErrors('subject') ? 'inputerror' : '')}" />
</div>
<span class="error" th:each="error : ${#fields.errors('subject')}">[[${error}]]<br /></span>
<div class="col-sm-12 col-md-3">Nachricht</div>
<div class="col-sm-12 col-md-9">
<textarea th:field="*{message}" th:class="${'form-control ' + (#fields.hasErrors('message') ? 'inputerror' : '')}" rows="5"></textarea>
</div>
<span class="error" th:each="error : ${#fields.errors('message')}">[[${error}]]<br /></span>
</div>
</div>
</div>
<div class="card-footer">
<input type="submit" value="absenden" class="btn btn-outline-success from-control" />
</div>
</div>
</form>
</div>
</th:block>
</body>
</html>

View File

@ -12,6 +12,9 @@
<ul class="navbar-nav mb-2 mb-lg-0"> <ul class="navbar-nav mb-2 mb-lg-0">
<li class="nav-item"><a th:href="@{/}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li> <li class="nav-item"><a th:href="@{/}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
</ul> </ul>
<ul class="navbar-nav mb-2 mb-lg-0" sec:authorize="hasRole('admin')">
<li class="nav-item"><a th:href="@{/admin/mail}" class="btn btn-secondary btn-icon-silent">Testmail</a></li>
</ul>
</th:block> </th:block>
<th:block layout:fragment="content"> <th:block layout:fragment="content">
<div sec:authorize="hasRole('admin')"> <div sec:authorize="hasRole('admin')">