implemented storing of messages in db

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
2026-01-25 23:43:20 +01:00
parent 50fa610837
commit fc1c735036
4 changed files with 112 additions and 58 deletions

View File

@@ -84,7 +84,9 @@ public class Field {
public static final String LOCATION_ID = "location_id"; public static final String LOCATION_ID = "location_id";
public static final String LOCATIONS = "locations"; public static final String LOCATIONS = "locations";
public static final String LOGIN = "login"; public static final String LOGIN = "login";
public static final String MEMBERS = "members"; public static final String MEMBERS = "members";
public static final String MESSAGE_ID = "message_id";
public static final String MIME = "mime"; public static final String MIME = "mime";
public static final String MODULE = "module"; public static final String MODULE = "module";
@@ -125,6 +127,7 @@ public class Field {
public static final String REQUIRED_TASKS_IDS = "required_tasks_ids"; public static final String REQUIRED_TASKS_IDS = "required_tasks_ids";
public static final String SENDER = "sender"; public static final String SENDER = "sender";
public static final String SENDER_USER_ID = "sender_user_id";
public static final String SETTINGS = "settings"; public static final String SETTINGS = "settings";
public static final String SHOW_CLOSED = "show_closed"; public static final String SHOW_CLOSED = "show_closed";
public static final String SILENT = "silent"; public static final String SILENT = "silent";

View File

@@ -12,12 +12,13 @@ public class Constants {
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 ENVELOPE_FROM = "mail.smtp.from";
public static final String FIELD_MESSAGES = "messages";
public static final String FIELD_HOST = "host";
public static final String FIELD_PORT = "port";
public static final String HOST = "mail.smtp.host";
public static final String PORT = "mail.smtp.port"; public static final String PORT = "mail.smtp.port";
public static final String SSL = "mail.smtp.ssl.enable"; public static final String SSL = "mail.smtp.ssl.enable";
public static final String SUBMISSION = "submission";
public static final String TABLE_ATTACHMENTS = "attachments";
public static final String TABLE_MESSAGES = "messages";
public static final String TABLE_RECEIVERS = "receivers";
public static final String TABLE_SUBMISSIONS = "message_submission";
} }

View File

@@ -84,8 +84,9 @@ public class MessageSystem extends BaseHandler implements PostBox, EventListener
public MessageSystem(Configuration config) throws UmbrellaException { public MessageSystem(Configuration config) throws UmbrellaException {
var dbFile = config.get(CONFIG_DB).orElseThrow(() -> missingConfig(CONFIG_DB)); var dbFile = config.get(CONFIG_DB).orElseThrow(() -> missingConfig(CONFIG_DB));
db = new SqliteMessageDb(connect(dbFile)); var sqlite = new SqliteMessageDb(connect(dbFile));
queue = new InMemoryQueue(); db = sqlite;
queue = sqlite;
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);

View File

@@ -9,9 +9,14 @@ import static de.srsoftware.umbrella.core.constants.Constants.TABLE_SETTINGS;
import static de.srsoftware.umbrella.core.constants.Field.*; import static de.srsoftware.umbrella.core.constants.Field.*;
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.core.model.Translatable.t;
import static de.srsoftware.umbrella.message.Constants.*;
import static de.srsoftware.umbrella.message.model.Schedule.schedule; import static de.srsoftware.umbrella.message.model.Schedule.schedule;
import static java.text.MessageFormat.format; import static java.text.MessageFormat.format;
import static java.time.ZoneOffset.UTC;
import de.srsoftware.tools.jdbc.Query;
import de.srsoftware.umbrella.core.BaseDb;
import de.srsoftware.umbrella.core.constants.Field;
import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.constants.Text;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Envelope; import de.srsoftware.umbrella.core.model.Envelope;
@@ -22,28 +27,73 @@ import de.srsoftware.umbrella.message.model.Instantly;
import de.srsoftware.umbrella.message.model.Settings; import de.srsoftware.umbrella.message.model.Settings;
import de.srsoftware.umbrella.message.model.Silent; import de.srsoftware.umbrella.message.model.Silent;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.time.ZoneOffset;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Stream; import java.util.stream.Stream;
public class SqliteMessageDb implements MessageDb, MessageQueue<TranslatedMessage> { public class SqliteMessageDb extends BaseDb implements MessageDb, MessageQueue<TranslatedMessage> {
private static final System.Logger LOG = System.getLogger(SqliteMessageDb.class.getSimpleName()); private static final System.Logger LOG = System.getLogger(SqliteMessageDb.class.getSimpleName());
private final Connection db;
private static final String DB_VERSION = "message_db_version";
private static final int INITIAL_DB_VERSION = 1;
private static final String TABLE_SUBMISSIONS = "message_submission";
public SqliteMessageDb(Connection conn){ public SqliteMessageDb(Connection conn){
db = conn; super(conn);
init(); }
private void createMessageTables() {
var sql = """
CREATE TABLE IF NOT EXISTS {0} (
{1} INTEGER PRIMARY KEY,
{2} LONG NOT NULL,
{3} LONG NOT NULL,
{4} TEXT,
{5} TEXT
);
""";
sql = format(sql,TABLE_MESSAGES, ID, TIMESTAMP, SENDER_USER_ID, SUBJECT, BODY);
try {
db.prepareStatement(sql).execute();
} catch (SQLException e) {
throw failedToCreateTable(TABLE_MESSAGES);
}
sql = """
CREATE TABLE IF NOT EXISTS {0} (
{1} INTEGER NOT NULL,
{2} VARCHAR(255) NOT NULL,
{3} VARCHAR(255),
PRIMARY KEY ({1}, {2})
);
""";
sql = format(sql,TABLE_RECEIVERS, MESSAGE_ID, EMAIL, NAME);
try {
db.prepareStatement(sql).execute();
} catch (SQLException e) {
throw failedToCreateTable(TABLE_MESSAGES);
}
sql = """
CREATE TABLE IF NOT EXISTS {0} (
{1} INTEGER NOT NULL,
{2} VARCHAR(255) NOT NULL,
{3} VARCHAR(100),
{4} BLOB NOT NULL,
PRIMARY KEY ({1}, {2})
);
""";
sql = format(sql,TABLE_ATTACHMENTS, MESSAGE_ID, NAME, MIME, DATA);
try {
db.prepareStatement(sql).execute();
} catch (SQLException e) {
throw failedToCreateTable(TABLE_MESSAGES);
}
} }
private void createSubmissionTable() { private void createSubmissionTable() {
var createTable = """ var createTable = """
CREATE TABLE IF NOT EXISTS {0} ( {1} Integer PRIMARY KEY, {2} VARCHAR(255) NOT NULL); CREATE TABLE IF NOT EXISTS {0} ( {1} INTEGER PRIMARY KEY, {2} VARCHAR(255) NOT NULL);
"""; """;
try { try {
var stmt = db.prepareStatement(format(createTable,TABLE_SUBMISSIONS, USER_ID, VALUE)); var stmt = db.prepareStatement(format(createTable,TABLE_SUBMISSIONS, USER_ID, VALUE));
@@ -54,37 +104,16 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} Integer PRIMARY KEY, {2} VARCHAR(255) NOT N
} }
} }
@Override
private int createSettingsTable() { protected int createTables() {
var createTable = """ int currentVersion = createSettingsTable();
CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255) NOT NULL); switch (currentVersion){
"""; case 0:
try {
var stmt = db.prepareStatement(format(createTable,TABLE_SETTINGS, KEY, VALUE));
stmt.execute();
stmt.close();
} catch (SQLException e) {
throw failedToCreateTable(TABLE_SETTINGS).causedBy(e);
}
Integer version = null;
try {
var rs = select(VALUE).from(TABLE_SETTINGS).where(KEY, equal(DB_VERSION)).exec(db);
if (rs.next()) version = rs.getInt(VALUE);
rs.close();
if (version == null) {
version = INITIAL_DB_VERSION;
insertInto(TABLE_SETTINGS, KEY, VALUE).values(DB_VERSION,version).execute(db).close();
}
return version;
} catch (SQLException e) {
throw databaseException(FAILED_TO_UPDATE_OBJECT, OBJECT,DB_VERSION).causedBy(e);
}
}
private int createTables() {
createSubmissionTable(); createSubmissionTable();
return createSettingsTable(); case 1:
createMessageTables();
}
return setCurrentVersion(2);
} }
@Override @Override
@@ -132,8 +161,28 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255)
} }
@Override @Override
public void push(Envelope<TranslatedMessage> message) { public void push(Envelope<TranslatedMessage> envelope) {
throw new UmbrellaException(HTTP_SERVER_ERROR,"{class}.push(message) not implemented!","class",getClass().getSimpleName()); // TODO var timestamp = envelope.time().toEpochSecond(UTC);
var message = envelope.message();
var sender = message.sender().id();
var subject = message.subject();
var body = message.body();
try {
var rs = insertInto(TABLE_MESSAGES, TIMESTAMP, SENDER_USER_ID, SUBJECT, BODY).values(timestamp, sender, subject, body).execute(db).getGeneratedKeys();
Long messageId = null;
if (rs.next()) messageId = rs.getLong(1);
rs.close();
if (messageId == null) throw failedToStoreObject(envelope);
for (var receiver : envelope.receivers()){
insertInto(TABLE_RECEIVERS,MESSAGE_ID,EMAIL,NAME).values(messageId,receiver.email(),receiver.name()).execute(db).close();
}
for (var attachment : envelope.message().attachments()){
insertInto(TABLE_ATTACHMENTS,MESSAGE_ID,NAME,MIME,DATA).values(messageId,attachment.name(),attachment.mime(),attachment.content()).execute(db).close();
}
} catch (SQLException e) {
throw failedToStoreObject(envelope).causedBy(e);
}
} }
private Settings toSettings(ResultSet rs) throws SQLException { private Settings toSettings(ResultSet rs) throws SQLException {