unified translation of events and event-related emails
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
FROM alpine:3.22
|
FROM alpine:3.22
|
||||||
LABEL Maintainer "Stephan Richter <s.richter@srsoftware.de>"
|
LABEL Maintainer "Stephan Richter"
|
||||||
ARG UID=1000
|
ARG UID=1000
|
||||||
ARG GID=1000
|
ARG GID=1000
|
||||||
RUN apk add bash npm
|
RUN apk add bash npm
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import static java.util.Optional.*;
|
|||||||
|
|
||||||
import de.srsoftware.tools.Diff;
|
import de.srsoftware.tools.Diff;
|
||||||
import de.srsoftware.tools.Mappable;
|
import de.srsoftware.tools.Mappable;
|
||||||
|
import de.srsoftware.umbrella.core.model.Translatable;
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -45,7 +46,7 @@ public abstract class Event<Payload extends Mappable> {
|
|||||||
|
|
||||||
public abstract Collection<UmbrellaUser> audience();
|
public abstract Collection<UmbrellaUser> audience();
|
||||||
|
|
||||||
public abstract String describe();
|
public abstract Translatable describe();
|
||||||
|
|
||||||
private Map<String, Object> dropMarkdown(Map<String, Object> map) {
|
private Map<String, Object> dropMarkdown(Map<String, Object> map) {
|
||||||
var result = new HashMap<String, Object>();
|
var result = new HashMap<String, Object>();
|
||||||
@@ -96,5 +97,5 @@ public abstract class Event<Payload extends Mappable> {
|
|||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract String subject();
|
public abstract Translatable subject();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/* © SRSoftware 2025 */
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.messagebus.events;
|
package de.srsoftware.umbrella.messagebus.events;
|
||||||
|
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Field.OBJECT;
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Field.USER;
|
||||||
import static de.srsoftware.umbrella.core.constants.Module.PROJECT;
|
import static de.srsoftware.umbrella.core.constants.Module.PROJECT;
|
||||||
import static java.text.MessageFormat.format;
|
import static de.srsoftware.umbrella.core.model.Translatable.t;
|
||||||
|
|
||||||
import de.srsoftware.umbrella.core.model.Member;
|
import de.srsoftware.umbrella.core.model.*;
|
||||||
import de.srsoftware.umbrella.core.model.Project;
|
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -26,8 +26,9 @@ public class ProjectEvent extends Event<Project>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String describe() {
|
public Translatable describe() {
|
||||||
return diff().orElse("[TODO: ProjectEvent.describe]");
|
return diff().map(UnTranslatable::new).map(Translatable.class::cast)
|
||||||
|
.orElseGet(() -> t("[TODO: {object}.describe]",OBJECT,this.getClass().getSimpleName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -39,7 +40,7 @@ public class ProjectEvent extends Event<Project>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String subject() {
|
public Translatable subject() {
|
||||||
return format("{0} edited {1}",initiator(),payload());
|
return t("{user} edited {object}",USER,initiator(),OBJECT,payload());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
package de.srsoftware.umbrella.messagebus.events;
|
package de.srsoftware.umbrella.messagebus.events;
|
||||||
|
|
||||||
|
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Field.OBJECT;
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Field.USER;
|
||||||
import static de.srsoftware.umbrella.core.constants.Module.TASK;
|
import static de.srsoftware.umbrella.core.constants.Module.TASK;
|
||||||
import static java.text.MessageFormat.format;
|
import static de.srsoftware.umbrella.core.model.Translatable.t;
|
||||||
|
|
||||||
import de.srsoftware.umbrella.core.model.Member;
|
import de.srsoftware.umbrella.core.model.*;
|
||||||
import de.srsoftware.umbrella.core.model.Task;
|
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -27,8 +27,9 @@ public class TaskEvent extends Event<Task>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String describe() {
|
public Translatable describe() {
|
||||||
return diff().orElse("[TODO: TaskEvent.describe()]");
|
return diff().map(UnTranslatable::new).map(Translatable.class::cast)
|
||||||
|
.orElseGet(() -> t("[TODO: {object}.describe]",OBJECT,this.getClass().getSimpleName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -40,7 +41,6 @@ public class TaskEvent extends Event<Task>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String subject() {
|
public Translatable subject() {
|
||||||
return format("{0} edited {1}",initiator(),payload());
|
return t("{user} edited {object}",USER,initiator(),OBJECT,payload());
|
||||||
}
|
}}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/* © SRSoftware 2025 */
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.messagebus.events;
|
package de.srsoftware.umbrella.messagebus.events;
|
||||||
|
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Field.OBJECT;
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Field.USER;
|
||||||
import static de.srsoftware.umbrella.core.constants.Module.WIKI;
|
import static de.srsoftware.umbrella.core.constants.Module.WIKI;
|
||||||
import static java.text.MessageFormat.format;
|
import static de.srsoftware.umbrella.core.model.Translatable.t;
|
||||||
|
|
||||||
import de.srsoftware.umbrella.core.model.Member;
|
import de.srsoftware.umbrella.core.model.*;
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
|
||||||
import de.srsoftware.umbrella.core.model.WikiPage;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -26,12 +26,13 @@ public class WikiEvent extends Event<WikiPage>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String describe() {
|
public Translatable describe() {
|
||||||
return diff().orElse("[TODO: WikiEvent.describe()]");
|
return diff().map(UnTranslatable::new).map(Translatable.class::cast)
|
||||||
|
.orElseGet(() -> t("[TODO: {object}.describe]",OBJECT,this.getClass().getSimpleName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String subject() {
|
public Translatable subject() {
|
||||||
return format("{0} edited {1}",initiator(),payload());
|
return t("{user} edited {object}",USER,initiator(),OBJECT,payload());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import java.util.*;
|
|||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public record Message(UmbrellaUser sender, String subject, String body, Map<String,String> fills, List<Attachment> attachments) {
|
public record Message(UmbrellaUser sender, Translatable subject, Translatable body, List<Attachment> attachments) {
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (!(o instanceof Message message)) return false;
|
if (!(o instanceof Message message)) return false;
|
||||||
@@ -43,7 +43,7 @@ public record Message(UmbrellaUser sender, String subject, String body, Map<Stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Message(sender,subject,body,null, attachments);
|
return new Message(sender,new UnTranslatable(subject),new UnTranslatable(body),attachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
/* © SRSoftware 2025 */
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.core.model;
|
package de.srsoftware.umbrella.core.model;
|
||||||
|
|
||||||
|
import static de.srsoftware.tools.Optionals.*;
|
||||||
|
|
||||||
import de.srsoftware.umbrella.core.ModuleRegistry;
|
import de.srsoftware.umbrella.core.ModuleRegistry;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class Translatable {
|
public class Translatable {
|
||||||
private final String message;
|
protected final String message;
|
||||||
private Map<String, Object> fills;
|
private final Map<String, Object> fills;
|
||||||
private final HashMap<String,String> translated = new HashMap<>();
|
private final HashMap<String,String> translated = new HashMap<>();
|
||||||
|
|
||||||
public Translatable(String message, Map<String,Object> fills){
|
public Translatable(String message, Map<String,Object> fills){
|
||||||
@@ -39,7 +41,7 @@ public class Translatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String translate(String language){
|
public String translate(String language){
|
||||||
var translation = language != null ? translated.get(language) : null;
|
var translation = language == null ? null : translated.get(language);
|
||||||
if (translation == null){
|
if (translation == null){
|
||||||
var translatedFills = new HashMap<String,String>();
|
var translatedFills = new HashMap<String,String>();
|
||||||
if (fills != null) {
|
if (fills != null) {
|
||||||
@@ -54,7 +56,7 @@ public class Translatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
translation = ModuleRegistry.translator().translate(language,message,translatedFills);
|
translation = ModuleRegistry.translator().translate(language,message,translatedFills);
|
||||||
if (translation != null) translated.put(language,translation);
|
if (allSet(language, translation)) translated.put(language,translation);
|
||||||
}
|
}
|
||||||
return translation;
|
return translation;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/* © SRSoftware 2025 */
|
||||||
|
package de.srsoftware.umbrella.core.model;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class UnTranslatable extends Translatable{
|
||||||
|
public UnTranslatable(String message) {
|
||||||
|
super(message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String translate(String language){
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -577,7 +577,7 @@ public class DocumentApi extends BaseHandler implements DocumentService {
|
|||||||
LOG.log(WARNING,e);
|
LOG.log(WARNING,e);
|
||||||
}
|
}
|
||||||
var attachment = new Attachment(doc.number()+".pdf",rendered.mimeType(),rendered.bytes());
|
var attachment = new Attachment(doc.number()+".pdf",rendered.mimeType(),rendered.bytes());
|
||||||
var message = new Message(user,subject,content,null,List.of(attachment));
|
var message = new Message(user,new UnTranslatable(subject),new UnTranslatable(content),List.of(attachment));
|
||||||
var envelope = new Envelope(message,new User(doc.customer().shortName(),new EmailAddress(email),doc.customer().language()));
|
var envelope = new Envelope(message,new User(doc.customer().shortName(),new EmailAddress(email),doc.customer().language()));
|
||||||
postBox().send(envelope);
|
postBox().send(envelope);
|
||||||
db.save(doc.set(SENT));
|
db.save(doc.set(SENT));
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import static de.srsoftware.tools.PathHandler.CONTENT_TYPE;
|
|||||||
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
||||||
import static de.srsoftware.umbrella.core.constants.Constants.UTF8;
|
import static de.srsoftware.umbrella.core.constants.Constants.UTF8;
|
||||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingConfig;
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingConfig;
|
||||||
|
import static de.srsoftware.umbrella.core.model.Translatable.t;
|
||||||
import static de.srsoftware.umbrella.message.Constants.*;
|
import static de.srsoftware.umbrella.message.Constants.*;
|
||||||
import static de.srsoftware.umbrella.messagebus.MessageBus.messageBus;
|
import static de.srsoftware.umbrella.messagebus.MessageBus.messageBus;
|
||||||
import static java.lang.System.Logger.Level.*;
|
import static java.lang.System.Logger.Level.*;
|
||||||
import static java.text.MessageFormat.format;
|
|
||||||
|
|
||||||
import de.srsoftware.configuration.Configuration;
|
import de.srsoftware.configuration.Configuration;
|
||||||
import de.srsoftware.umbrella.core.ModuleRegistry;
|
import de.srsoftware.umbrella.core.ModuleRegistry;
|
||||||
@@ -21,7 +21,7 @@ import de.srsoftware.umbrella.message.model.CombinedMessage;
|
|||||||
import de.srsoftware.umbrella.messagebus.EventListener;
|
import de.srsoftware.umbrella.messagebus.EventListener;
|
||||||
import de.srsoftware.umbrella.messagebus.events.Event;
|
import de.srsoftware.umbrella.messagebus.events.Event;
|
||||||
import jakarta.activation.DataHandler;
|
import jakarta.activation.DataHandler;
|
||||||
import jakarta.mail.Message;
|
import jakarta.mail.Message.RecipientType;
|
||||||
import jakarta.mail.MessagingException;
|
import jakarta.mail.MessagingException;
|
||||||
import jakarta.mail.Session;
|
import jakarta.mail.Session;
|
||||||
import jakarta.mail.Transport;
|
import jakarta.mail.Transport;
|
||||||
@@ -31,7 +31,6 @@ import jakarta.mail.internet.MimeMultipart;
|
|||||||
import jakarta.mail.util.ByteArrayDataSource;
|
import jakarta.mail.util.ByteArrayDataSource;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
public class MessageSystem implements PostBox, EventListener {
|
public class MessageSystem implements PostBox, EventListener {
|
||||||
public static final System.Logger LOG = System.getLogger(MessageSystem.class.getSimpleName());
|
public static final System.Logger LOG = System.getLogger(MessageSystem.class.getSimpleName());
|
||||||
@@ -95,14 +94,8 @@ public class MessageSystem implements PostBox, EventListener {
|
|||||||
@Override
|
@Override
|
||||||
public void onEvent(Event<?> event) {
|
public void onEvent(Event<?> event) {
|
||||||
for (var user : event.audience()){
|
for (var user : event.audience()){
|
||||||
if (!"s.richter@srsoftware.de".equals(user.email().toString())) continue;
|
if (debugAddress != null && !debugAddress.equals(user.email().toString())) continue;
|
||||||
var verb = switch (event.eventType()){
|
var message = new de.srsoftware.umbrella.core.model.Message(event.initiator(),event.subject(),event.describe(),null);
|
||||||
case UPDATE -> "updated";
|
|
||||||
case CREATE -> "created";
|
|
||||||
case DELETE -> "deleted";
|
|
||||||
};
|
|
||||||
var title = format("{0} {1} {2} {3}",event.initiator().name(),verb,event.module(), event.payload());
|
|
||||||
var message = new de.srsoftware.umbrella.core.model.Message(event.initiator(),title,event.describe(),null,null);
|
|
||||||
var envelope = new Envelope(message,user);
|
var envelope = new Envelope(message,user);
|
||||||
send(envelope);
|
send(envelope);
|
||||||
}
|
}
|
||||||
@@ -135,14 +128,12 @@ public class MessageSystem implements PostBox, EventListener {
|
|||||||
var date = new Date();
|
var date = new Date();
|
||||||
|
|
||||||
for (var receiver : dueRecipients){
|
for (var receiver : dueRecipients){
|
||||||
BiFunction<String,Map<String,String>,String> translateFunction = (text,fills) -> ModuleRegistry.translator().translate(receiver.language(),text,fills);
|
var combined = new CombinedMessage(t("Collected messages"),receiver);
|
||||||
|
|
||||||
var combined = new CombinedMessage("Collected messages",translateFunction);
|
|
||||||
var envelopes = queue.stream().filter(env -> env.isFor(receiver)).toList();
|
var envelopes = queue.stream().filter(env -> env.isFor(receiver)).toList();
|
||||||
for (var envelope : envelopes) combined.merge(envelope.message());
|
for (var envelope : envelopes) combined.merge(envelope.message());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
send(combined,receiver,date);
|
send(combined,date);
|
||||||
for (var envelope : envelopes){
|
for (var envelope : envelopes){
|
||||||
var audience = envelope.receivers();
|
var audience = envelope.receivers();
|
||||||
audience.remove(receiver);
|
audience.remove(receiver);
|
||||||
@@ -176,7 +167,8 @@ public class MessageSystem implements PostBox, EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void send(CombinedMessage message, User receiver, Date date) throws MessagingException {
|
private void send(CombinedMessage message, Date date) throws MessagingException {
|
||||||
|
var receiver = message.receiver();
|
||||||
LOG.log(TRACE,"Sending combined message to {0}…",receiver);
|
LOG.log(TRACE,"Sending combined message to {0}…",receiver);
|
||||||
session = session();
|
session = session();
|
||||||
MimeMessage msg = new MimeMessage(session);
|
MimeMessage msg = new MimeMessage(session);
|
||||||
@@ -187,7 +179,7 @@ public class MessageSystem implements PostBox, EventListener {
|
|||||||
msg.setSubject(message.subject(), UTF8);
|
msg.setSubject(message.subject(), UTF8);
|
||||||
msg.setSentDate(date);
|
msg.setSentDate(date);
|
||||||
var toEmail = debugAddress != null ? debugAddress : receiver.email().toString();
|
var toEmail = debugAddress != null ? debugAddress : receiver.email().toString();
|
||||||
msg.setRecipients(Message.RecipientType.TO, toEmail);
|
msg.setRecipients(RecipientType.TO, toEmail);
|
||||||
|
|
||||||
if (message.attachments().isEmpty()){
|
if (message.attachments().isEmpty()){
|
||||||
msg.setText(message.body(), UTF8);
|
msg.setText(message.body(), UTF8);
|
||||||
|
|||||||
@@ -5,33 +5,31 @@ import static java.lang.System.Logger.Level.DEBUG;
|
|||||||
import static java.lang.System.Logger.Level.TRACE;
|
import static java.lang.System.Logger.Level.TRACE;
|
||||||
import static java.text.MessageFormat.format;
|
import static java.text.MessageFormat.format;
|
||||||
|
|
||||||
import de.srsoftware.umbrella.core.model.Attachment;
|
import de.srsoftware.umbrella.core.model.*;
|
||||||
import de.srsoftware.umbrella.core.model.Message;
|
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
public class CombinedMessage {
|
public class CombinedMessage {
|
||||||
private static final System.Logger LOG = System.getLogger(CombinedMessage.class.getSimpleName());
|
private static final System.Logger LOG = System.getLogger(CombinedMessage.class.getSimpleName());
|
||||||
|
|
||||||
private final Set<Attachment> attachments = new HashSet<>();
|
private final Set<Attachment> attachments = new HashSet<>();
|
||||||
private final StringBuilder combinedBody = new StringBuilder();
|
private final StringBuilder combinedBody = new StringBuilder();
|
||||||
|
private final User receiver;
|
||||||
private String combinedSubject = null;
|
private String combinedSubject = null;
|
||||||
private final List<Message> mergedMessages = new ArrayList<>();
|
private final List<Message> mergedMessages = new ArrayList<>();
|
||||||
private final String subjectForCombinedMessage;
|
private final Translatable subjectForCombinedMessage;
|
||||||
private final BiFunction<String,Map<String,String>,String> translate;
|
|
||||||
private UmbrellaUser sender = null;
|
private UmbrellaUser sender = null;
|
||||||
|
|
||||||
public CombinedMessage(String subjectForCombinedMessage, BiFunction<String, Map<String,String>,String> translateFunction){
|
public CombinedMessage(Translatable subjectForCombinedMessage, User receiver){
|
||||||
LOG.log(DEBUG,"Creating combined message…");
|
LOG.log(DEBUG,"Creating combined message…");
|
||||||
this.subjectForCombinedMessage = subjectForCombinedMessage;
|
this.subjectForCombinedMessage = subjectForCombinedMessage;
|
||||||
translate = translateFunction;
|
this.receiver = receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void merge(Message message) {
|
public void merge(Message message) {
|
||||||
LOG.log(TRACE,"Merging {0} into combined message…",message);
|
LOG.log(TRACE,"Merging {0} into combined message…",message);
|
||||||
var body = translate.apply(message.body(),message.fills());
|
var lang = receiver.language();
|
||||||
var subject = translate.apply(message.subject(),message.fills());
|
var body = message.body().translate(lang);
|
||||||
|
var subject = message.subject().translate(lang);
|
||||||
switch (mergedMessages.size()){
|
switch (mergedMessages.size()){
|
||||||
case 0:
|
case 0:
|
||||||
combinedBody.append(body);
|
combinedBody.append(body);
|
||||||
@@ -40,7 +38,7 @@ public class CombinedMessage {
|
|||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
combinedBody.insert(0,format("# {0}:\n# {1}:\n\n",sender,subject)); // insert sender and subject of first message right before the body of the first message
|
combinedBody.insert(0,format("# {0}:\n# {1}:\n\n",sender,subject)); // insert sender and subject of first message right before the body of the first message
|
||||||
combinedSubject = subjectForCombinedMessage;
|
combinedSubject = subjectForCombinedMessage.translate(lang);
|
||||||
// no break here, we need to append the subject and content
|
// no break here, we need to append the subject and content
|
||||||
default:
|
default:
|
||||||
combinedBody.append("\n\n# ").append(message.sender()).append(":\n");
|
combinedBody.append("\n\n# ").append(message.sender()).append(":\n");
|
||||||
@@ -59,6 +57,14 @@ public class CombinedMessage {
|
|||||||
return combinedBody.toString();
|
return combinedBody.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Message> messages() {
|
||||||
|
return mergedMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User receiver(){
|
||||||
|
return receiver;
|
||||||
|
}
|
||||||
|
|
||||||
public UmbrellaUser sender() {
|
public UmbrellaUser sender() {
|
||||||
return sender;
|
return sender;
|
||||||
}
|
}
|
||||||
@@ -67,7 +73,10 @@ public class CombinedMessage {
|
|||||||
return combinedSubject;
|
return combinedSubject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Message> messages() {
|
@Override
|
||||||
return mergedMessages;
|
public String toString() {
|
||||||
|
var body = body();
|
||||||
|
if (body.length()>100) body = body.substring(0,99)+"…";
|
||||||
|
return format("{0} for {1} ({2}): {3}",getClass().getSimpleName(),receiver.email(),subject(),body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,7 +143,6 @@
|
|||||||
|
|
||||||
"given_name": "Vorname",
|
"given_name": "Vorname",
|
||||||
"go": "los!",
|
"go": "los!",
|
||||||
"go_to_url_to_reset_password": "Um ein neues Passwort zu erhalten, öffnen Sie bitte den folgenden Link: {url}",
|
|
||||||
"gross_sum": "Brutto-Summe",
|
"gross_sum": "Brutto-Summe",
|
||||||
|
|
||||||
"head": "Kopf-Text",
|
"head": "Kopf-Text",
|
||||||
@@ -345,6 +344,7 @@
|
|||||||
"title_not_available": "„{title}“ ist als Seitenname nicht mehr verfügbar!",
|
"title_not_available": "„{title}“ ist als Seitenname nicht mehr verfügbar!",
|
||||||
"title_or_desc": "Titel/Beschreibung",
|
"title_or_desc": "Titel/Beschreibung",
|
||||||
"toggle_objects": "{objects} an/ausschalten",
|
"toggle_objects": "{objects} an/ausschalten",
|
||||||
|
"To receive a new password, open the following link: {url}": "Um ein neues Passwort zu erhalten, öffnen Sie bitte den folgenden Link: {url}",
|
||||||
"tutorial": "Tutorial",
|
"tutorial": "Tutorial",
|
||||||
"type": "Dokumententyp",
|
"type": "Dokumententyp",
|
||||||
"type_confirmation": "Bestätigung",
|
"type_confirmation": "Bestätigung",
|
||||||
@@ -384,6 +384,6 @@
|
|||||||
"visible_to_guests": "Für Besucher sichtbar",
|
"visible_to_guests": "Für Besucher sichtbar",
|
||||||
|
|
||||||
"year": "Jahr",
|
"year": "Jahr",
|
||||||
"your_password_reset_token" : "Ihr Token zum Erstellen eines neuen Passworts",
|
"Your token to create a new password" : "Ihr Token zum Erstellen eines neuen Passworts",
|
||||||
"your_profile": "dein Profil"
|
"your_profile": "dein Profil"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,7 +143,6 @@
|
|||||||
|
|
||||||
"given_name": "given name",
|
"given_name": "given name",
|
||||||
"go": "go!",
|
"go": "go!",
|
||||||
"go_to_url_to_reset_password": "To receive a new password, open the following link: {url}",
|
|
||||||
"gross_sum": "gross sum",
|
"gross_sum": "gross sum",
|
||||||
|
|
||||||
"head": "header text",
|
"head": "header text",
|
||||||
@@ -345,6 +344,7 @@
|
|||||||
"title_not_available": "„{title}“ is not available as page name!",
|
"title_not_available": "„{title}“ is not available as page name!",
|
||||||
"title_or_desc": "title/description",
|
"title_or_desc": "title/description",
|
||||||
"toggle_objects": "toggle {objects}",
|
"toggle_objects": "toggle {objects}",
|
||||||
|
"To receive a new password, open the following link: {url}": "To receive a new password, open the following link: {url}",
|
||||||
"tutorial": "tutorial",
|
"tutorial": "tutorial",
|
||||||
"type": "type",
|
"type": "type",
|
||||||
"type_confirmation": "confirmation",
|
"type_confirmation": "confirmation",
|
||||||
@@ -384,6 +384,6 @@
|
|||||||
"visible_to_guests": "visible to guests",
|
"visible_to_guests": "visible to guests",
|
||||||
|
|
||||||
"year": "year",
|
"year": "year",
|
||||||
"your_password_reset_token" : "Your token to create a new password",
|
"Your token to create a new password" : "Your token to create a new password",
|
||||||
"your_profile": "your profile"
|
"your_profile": "your profile"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import static de.srsoftware.umbrella.core.constants.Field.STATE;
|
|||||||
import static de.srsoftware.umbrella.core.constants.Field.USER;
|
import static de.srsoftware.umbrella.core.constants.Field.USER;
|
||||||
import static de.srsoftware.umbrella.core.constants.Path.*;
|
import static de.srsoftware.umbrella.core.constants.Path.*;
|
||||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
||||||
|
import static de.srsoftware.umbrella.core.model.Translatable.t;
|
||||||
import static de.srsoftware.umbrella.user.Constants.*;
|
import static de.srsoftware.umbrella.user.Constants.*;
|
||||||
import static de.srsoftware.umbrella.user.Paths.*;
|
import static de.srsoftware.umbrella.user.Paths.*;
|
||||||
import static de.srsoftware.umbrella.user.Paths.IMPERSONATE;
|
import static de.srsoftware.umbrella.user.Paths.IMPERSONATE;
|
||||||
@@ -502,11 +503,10 @@ public class UserModule extends BaseHandler implements UserService {
|
|||||||
if (oldToken != null) tokenMap.remove(oldToken);
|
if (oldToken != null) tokenMap.remove(oldToken);
|
||||||
tokenMap.put(token,email);
|
tokenMap.put(token,email);
|
||||||
tokenMap.put(email,token);
|
tokenMap.put(email,token);
|
||||||
var subject = "user.your_password_reset_token";
|
|
||||||
var content = "user.go_to_url_to_reset_password";
|
|
||||||
var url = url(ex).replace("/api/user/reset_pw","/user/reset/pw")+"?token="+token;
|
var url = url(ex).replace("/api/user/reset_pw","/user/reset/pw")+"?token="+token;
|
||||||
var fills = Map.of("url",url);
|
var subject = t("Your token to create a new password");
|
||||||
var message = new Message(user,subject,content,fills,null);
|
var content = t("To receive a new password, open the following link: {url}",URL,url);
|
||||||
|
var message = new Message(user,subject,content,null);
|
||||||
var envelope = new Envelope(message,user);
|
var envelope = new Envelope(message,user);
|
||||||
postBox().send(envelope);
|
postBox().send(envelope);
|
||||||
} catch (UmbrellaException e){
|
} catch (UmbrellaException e){
|
||||||
|
|||||||
Reference in New Issue
Block a user