Compare commits

..

1 Commits

Author SHA1 Message Date
8c351440c8 bugfix: renamed cosntant to make system use the right string
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2026-01-19 22:48:28 +01:00
8 changed files with 40 additions and 65 deletions

View File

@@ -22,9 +22,8 @@ RUN adduser -D umbrella
COPY --from=java_build /Umbrella/backend/build/libs/backend.jar /home/umbrella/jar/ COPY --from=java_build /Umbrella/backend/build/libs/backend.jar /home/umbrella/jar/
RUN chown -R umbrella /home/umbrella RUN chown -R umbrella /home/umbrella
ADD https://github.com/plantuml/plantuml/releases/download/v1.2025.10/plantuml-1.2025.10.jar /home/umbrella/plantuml.jar ADD https://github.com/plantuml/plantuml/releases/download/v1.2025.10/plantuml-1.2025.10.jar /home/umbrella/plantuml.jar
WORKDIR /home/umbrella
RUN chmod a+rx plantuml.jar
USER umbrella USER umbrella
WORKDIR /home/umbrella
RUN mkdir .config && ln -s /host/config.json .config/Umbrella.json RUN mkdir .config && ln -s /host/config.json .config/Umbrella.json
EXPOSE 80 EXPOSE 80
CMD java -jar jar/backend.jar CMD java -jar jar/backend.jar

View File

@@ -35,12 +35,11 @@ import org.json.JSONObject;
public class Util { public class Util {
public static final System.Logger LOG = System.getLogger("Util"); public static final System.Logger LOG = System.getLogger("Util");
private static final Pattern UML_PATTERN = Pattern.compile("@start(\\w+)(.*?)@end(\\1)",Pattern.DOTALL); private static final Pattern UML_PATTERN = Pattern.compile("@start(\\w+)(.*)@end(\\1)",Pattern.DOTALL);
private static File plantumlJar = null; private static File plantumlJar = null;
private static final JParsedown MARKDOWN = new JParsedown(); private static final JParsedown MARKDOWN = new JParsedown();
public static final String SHA1 = "SHA-1"; public static final String SHA1 = "SHA-1";
private static final MessageDigest SHA1_DIGEST; private static final MessageDigest SHA1_DIGEST;
private static final Map<Integer,String> umlCache = new HashMap<>();
static { static {
try { try {
@@ -80,22 +79,11 @@ public class Util {
try { try {
if (plantumlJar != null && plantumlJar.exists()) { if (plantumlJar != null && plantumlJar.exists()) {
var matcher = UML_PATTERN.matcher(source); var matcher = UML_PATTERN.matcher(source);
while (matcher.find()) { if (matcher.find()) {
var uml = matcher.group(0).trim(); var uml = matcher.group(0).trim();
var start = matcher.start(0); var start = matcher.start(0);
var end = matcher.end(0); var end = matcher.end(0);
var umlHash = uml.hashCode();
LOG.log(DEBUG,"Hash of Plantuml code: {0}",umlHash);
var svg = umlCache.get(umlHash);
if (svg != null){
LOG.log(DEBUG,"Serving Plantuml generated SVG from cache…");
source = source.substring(0, start) + svg + source.substring(end);
matcher = UML_PATTERN.matcher(source);
continue;
}
LOG.log(DEBUG,"Cache miss. Generating SVG from plantuml code…");
ProcessBuilder processBuilder = new ProcessBuilder("java", "-jar", plantumlJar.getAbsolutePath(), "-tsvg", "-pipe"); ProcessBuilder processBuilder = new ProcessBuilder("java", "-jar", plantumlJar.getAbsolutePath(), "-tsvg", "-pipe");
var ignored = processBuilder.redirectErrorStream(); var ignored = processBuilder.redirectErrorStream();
var process = processBuilder.start(); var process = processBuilder.start();
@@ -106,11 +94,8 @@ public class Util {
try (InputStream is = process.getInputStream()) { try (InputStream is = process.getInputStream()) {
byte[] out = is.readAllBytes(); byte[] out = is.readAllBytes();
LOG.log(DEBUG,"Generated SVG. Pushing to cache…"); var svg = new String(out, UTF_8);
svg = new String(out, UTF_8);
umlCache.put(umlHash,svg);
source = source.substring(0, start) + svg + source.substring(end); source = source.substring(0, start) + svg + source.substring(end);
matcher = UML_PATTERN.matcher(source);
} }
} }
} }

View File

@@ -2,23 +2,19 @@
package de.srsoftware.umbrella.message; package de.srsoftware.umbrella.message;
public class Constants { public class Constants {
public static final String AUTH = "mail.smtp.auth";
public static final String CONFIG_DB = "umbrella.modules.message.database"; public static final String CONFIG_DB = "umbrella.modules.message.database";
public static final String CONFIG_SMTP_FROM = "umbrella.modules.message.smtp.from";
public static final String CONFIG_SMTP_HOST = "umbrella.modules.message.smtp.host"; public static final String CONFIG_SMTP_HOST = "umbrella.modules.message.smtp.host";
public static final String CONFIG_SMTP_PASS = "umbrella.modules.message.smtp.pass"; public static final String CONFIG_SMTP_PASS = "umbrella.modules.message.smtp.pass";
public static final String CONFIG_SMTP_PORT = "umbrella.modules.message.smtp.port"; public static final String CONFIG_SMTP_PORT = "umbrella.modules.message.smtp.port";
public static final String CONFIG_SMTP_USER = "umbrella.modules.message.smtp.user"; public static final String CONFIG_SMTP_USER = "umbrella.modules.message.smtp.user";
public static final String DEBUG_ADDREESS = "umbrella.modules.message.debug_address"; public static final String DEBUG_ADDREESS = "umbrella.modules.message.debug_address";
public static final String ENVELOPE_FROM = "mail.smtp.from"; public static final String SMTP_AUTH = "mail.smtp.auth";
public static final String FIELD_MESSAGES = "messages"; public static final String SMTP_HOST = "mail.smtp.host";
public static final String FIELD_HOST = "host"; public static final String SMTP_FROM = "mail.smtp.from";
public static final String FIELD_PORT = "port"; public static final String SMTP_PORT = "mail.smtp.port";
public static final String HOST = "mail.smtp.host"; public static final String SMTP_SSL = "mail.smtp.ssl.enable";
public static final String PORT = "mail.smtp.port";
public static final String SSL = "mail.smtp.ssl.enable";
public static final String SUBMISSION = "submission"; public static final String SUBMISSION = "submission";
} }

View File

@@ -3,7 +3,6 @@ package de.srsoftware.umbrella.message;
import static de.srsoftware.tools.PathHandler.CONTENT_TYPE; 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.ModuleRegistry.translator;
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.message.Constants.*; import static de.srsoftware.umbrella.message.Constants.*;
@@ -13,7 +12,6 @@ import de.srsoftware.configuration.Configuration;
import de.srsoftware.umbrella.core.ModuleRegistry; import de.srsoftware.umbrella.core.ModuleRegistry;
import de.srsoftware.umbrella.core.api.PostBox; import de.srsoftware.umbrella.core.api.PostBox;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.EmailAddress;
import de.srsoftware.umbrella.core.model.Envelope; import de.srsoftware.umbrella.core.model.Envelope;
import de.srsoftware.umbrella.core.model.UmbrellaUser; import de.srsoftware.umbrella.core.model.UmbrellaUser;
import de.srsoftware.umbrella.core.model.User; import de.srsoftware.umbrella.core.model.User;
@@ -78,10 +76,10 @@ public class MessageSystem implements PostBox {
db = new SqliteMessageDb(connect(dbFile)); db = new SqliteMessageDb(connect(dbFile));
debugAddress = config.get(DEBUG_ADDREESS).map(Object::toString).orElse(null); debugAddress = config.get(DEBUG_ADDREESS).map(Object::toString).orElse(null);
port = config.get(CONFIG_SMTP_PORT,587); port = config.get(CONFIG_SMTP_PORT,587);
host = config.get(CONFIG_SMTP_HOST).map(Object::toString).orElseThrow(() -> missingConfig(CONFIG_SMTP_HOST)); host = config.get(CONFIG_SMTP_HOST).map(Object::toString).orElseThrow(() -> new RuntimeException("umbrella.modules.message.smtp.host not configured!"));
user = config.get(CONFIG_SMTP_USER).map(Object::toString).orElseThrow(() -> missingConfig(CONFIG_SMTP_USER)); user = config.get(CONFIG_SMTP_USER).map(Object::toString).orElseThrow(() -> new RuntimeException("umbrella.modules.message.smtp.user not configured!"));
pass = config.get(CONFIG_SMTP_PASS).map(Object::toString).orElseThrow(() -> missingConfig(CONFIG_SMTP_PASS)); pass = config.get(CONFIG_SMTP_PASS).map(Object::toString).orElseThrow(() -> new RuntimeException("umbrella.modules.message.smtp.pass not configured!"));
from = config.get(CONFIG_SMTP_FROM).map(Object::toString).orElseThrow(() -> missingConfig(CONFIG_SMTP_FROM)); from = user;
ModuleRegistry.add(this); ModuleRegistry.add(this);
new SubmissionTask(8).schedule(); new SubmissionTask(8).schedule();
new SubmissionTask(10).schedule(); new SubmissionTask(10).schedule();
@@ -118,9 +116,9 @@ public class MessageSystem implements PostBox {
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) -> translator().translate(receiver.language(),text,fills); BiFunction<String,Map<String,String>,String> translateFunction = (text,fills) -> ModuleRegistry.translator().translate(receiver.language(),text,fills);
var fallbackSender = new User("Umbrella",new EmailAddress(from),null);
var combined = new CombinedMessage("Collected messages",translateFunction,fallbackSender); 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());
@@ -144,11 +142,11 @@ public class MessageSystem implements PostBox {
private Session session() { private Session session() {
if (session == null){ if (session == null){
Properties props = new Properties(); Properties props = new Properties();
props.put(HOST, host); props.put(SMTP_HOST, host);
props.put(PORT, port); props.put(SMTP_PORT, port);
props.put(AUTH, true); props.put(SMTP_AUTH, true);
props.put(SSL, true); props.put(SMTP_SSL, true);
props.put(ENVELOPE_FROM,from); props.put(SMTP_FROM,from);
session = Session.getInstance(props); session = Session.getInstance(props);
} }
return session; return session;

View File

@@ -5,7 +5,9 @@ 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.*; import de.srsoftware.umbrella.core.model.Attachment;
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; import java.util.function.BiFunction;
@@ -14,17 +16,15 @@ public class CombinedMessage {
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 fallbackSender;
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 String subjectForCombinedMessage;
private final BiFunction<String,Map<String,String>,String> translate; private final BiFunction<String,Map<String,String>,String> translate;
private User sender = null; private UmbrellaUser sender = null;
public CombinedMessage(String subjectForCombinedMessage, BiFunction<String, Map<String,String>,String> translateFunction, User fallbackSender){ public CombinedMessage(String subjectForCombinedMessage, BiFunction<String, Map<String,String>,String> translateFunction){
LOG.log(DEBUG,"Creating combined message…"); LOG.log(DEBUG,"Creating combined message…");
this.subjectForCombinedMessage = translateFunction.apply(subjectForCombinedMessage,null); this.subjectForCombinedMessage = subjectForCombinedMessage;
this.fallbackSender = fallbackSender;
translate = translateFunction; translate = translateFunction;
} }
@@ -39,12 +39,12 @@ public class CombinedMessage {
combinedSubject = subject; combinedSubject = subject;
break; break;
case 1: case 1:
if (!sender.equals(message.sender())) sender = fallbackSender; 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} / {1}:\n\n",sender,subject)); // insert sender and subject of first message right before the body of the first message
combinedSubject = subjectForCombinedMessage; combinedSubject = subjectForCombinedMessage;
// 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(" / ").append(subject).append(":\n\n"); combinedBody.append("\n\n# ").append(message.sender()).append(":\n");
combinedBody.append("# ").append(subject).append(":\n\n");
combinedBody.append(body); combinedBody.append(body);
} }
if (message.attachments() != null) attachments.addAll(message.attachments()); if (message.attachments() != null) attachments.addAll(message.attachments());
@@ -59,7 +59,7 @@ public class CombinedMessage {
return combinedBody.toString(); return combinedBody.toString();
} }
public User sender() { public UmbrellaUser sender() {
return sender; return sender;
} }

View File

@@ -57,9 +57,8 @@ footer {
margin: 5px; margin: 5px;
} }
img, svg { img {
max-width: 100%; max-width: 100%;
height: auto !important;
} }
nav { nav {

View File

@@ -57,9 +57,8 @@ footer {
margin: 5px; margin: 5px;
} }
img, svg { img {
max-width: 100%; max-width: 100%;
height: auto !important;
} }
nav { nav {

View File

@@ -57,18 +57,17 @@ footer {
margin: 5px; margin: 5px;
} }
img, svg { img {
max-width: 100%; max-width: 100%;
height: auto !important;
} }
nav { nav {
position: sticky; position: sticky;
z-index: 100; z-index: 100;
top: 0; top: 0;
padding: 5px; padding: 5px;
margin: 0 0 10px 0; margin: 0 0 10px 0;
border-bottom: 1px solid; border-bottom: 1px solid;
} }
td, tr{ td, tr{