diff --git a/config.yaml b/config.yaml
index 835fe88b93..8f84d933f3 100644
--- a/config.yaml
+++ b/config.yaml
@@ -165,6 +165,14 @@ server:
DB_PASS: "snailshell"
INIT_CONNECTION_POOL_TIMEOUT: 90 # Seconds
+ PG_DB_NAME: "cosmic"
+ PG_DB_HOST: "localhost"
+ PG_DB_SCHEMA: "cosmic"
+ PG_DB_ADMIN_USERNAME: "cosmic_admin"
+ PG_DB_ADMIN_PASSWORD: "redsnailshell"
+ PG_DB_USERNAME: "cosmic_server"
+ PG_DB_PASSWORD: "bluesnailshell"
+
#Login Configuration
WORLDS: 1 #Initial number of worlds on the server.
WLDLIST_SIZE: 21 #Max possible worlds on the server.
diff --git a/database/postgresql/create-admin-user.sql b/database/postgresql/create-admin-user.sql
new file mode 100644
index 0000000000..08eb0b59d5
--- /dev/null
+++ b/database/postgresql/create-admin-user.sql
@@ -0,0 +1,3 @@
+CREATE USER cosmic_admin WITH ENCRYPTED PASSWORD 'redsnailshell';
+GRANT ALL PRIVILEGES ON DATABASE cosmic TO cosmic_admin;
+ALTER ROLE cosmic_admin WITH CREATEROLE;
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index c5ac497114..be55b0e352 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,6 +32,8 @@
1.0
5.0.1
8.0.30
+ 42.5.4
+ 9.15.1
3.35.0
5.9.0
4.7.0
@@ -60,11 +62,21 @@
mysql-connector-java
${mysql-connector-java.version}
+
+ org.postgresql
+ postgresql
+ ${postgresql.version}
+
org.jdbi
jdbi3-core
${jdbi-version}
+
+ org.flywaydb
+ flyway-core
+ ${flyway.version}
+
diff --git a/src/main/java/config/ServerConfig.java b/src/main/java/config/ServerConfig.java
index 064599729a..8a07d5109e 100644
--- a/src/main/java/config/ServerConfig.java
+++ b/src/main/java/config/ServerConfig.java
@@ -12,6 +12,15 @@ public class ServerConfig {
public String DB_PASS;
public int INIT_CONNECTION_POOL_TIMEOUT;
+ // PostgreSQL database configuration
+ public String PG_DB_NAME;
+ public String PG_DB_HOST;
+ public String PG_DB_SCHEMA;
+ public String PG_DB_ADMIN_USERNAME;
+ public String PG_DB_ADMIN_PASSWORD;
+ public String PG_DB_USERNAME;
+ public String PG_DB_PASSWORD;
+
//Login Configuration
public int WORLDS;
public int WLDLIST_SIZE;
diff --git a/src/main/java/database/PgDatabaseConfig.java b/src/main/java/database/PgDatabaseConfig.java
new file mode 100644
index 0000000000..a290f23007
--- /dev/null
+++ b/src/main/java/database/PgDatabaseConfig.java
@@ -0,0 +1,30 @@
+package database;
+
+import java.time.Duration;
+
+public record PgDatabaseConfig(
+ String databaseName, String host, String schema,
+ String adminUsername, String adminPassword,
+ String username, String password,
+ Duration poolInitTimeout
+) {
+ public PgDatabaseConfig {
+ verifyNotBlank(databaseName);
+ verifyNotBlank(host);
+ verifyNotBlank(schema);
+ verifyNotBlank(adminUsername);
+ verifyNotBlank(adminPassword);
+ verifyNotBlank(username);
+ verifyNotBlank(password);
+ }
+
+ private void verifyNotBlank(String value) {
+ if (value == null || value.isBlank()) {
+ throw new IllegalArgumentException("Missing or blank value in PG database config");
+ }
+ }
+
+ public String getJdbcUrl() {
+ return "jdbc:postgresql://%s:5432/%s".formatted(host, databaseName);
+ }
+}
diff --git a/src/main/java/database/migration/FlywayRunner.java b/src/main/java/database/migration/FlywayRunner.java
new file mode 100644
index 0000000000..960ffea00b
--- /dev/null
+++ b/src/main/java/database/migration/FlywayRunner.java
@@ -0,0 +1,22 @@
+package database.migration;
+
+import database.PgDatabaseConfig;
+import org.flywaydb.core.Flyway;
+import org.flywaydb.core.api.FlywayException;
+
+public class FlywayRunner {
+ private final PgDatabaseConfig dbConfig;
+
+ public FlywayRunner(PgDatabaseConfig dbConfig) {
+ this.dbConfig = dbConfig;
+ }
+
+ public void migrate() throws FlywayException {
+ Flyway flyway = Flyway.configure()
+ .dataSource(dbConfig.getJdbcUrl(), dbConfig.adminUsername(), dbConfig.adminPassword())
+ .schemas(dbConfig.schema())
+ .createSchemas(true)
+ .load();
+ flyway.migrate();
+ }
+}
diff --git a/src/main/java/net/server/Server.java b/src/main/java/net/server/Server.java
index 5b854bebcd..19e1490f11 100644
--- a/src/main/java/net/server/Server.java
+++ b/src/main/java/net/server/Server.java
@@ -31,11 +31,14 @@ import client.inventory.ItemFactory;
import client.inventory.manipulator.CashIdGenerator;
import client.newyear.NewYearCardRecord;
import client.processor.npc.FredrickProcessor;
+import config.ServerConfig;
import config.YamlConfig;
import constants.game.GameConstants;
import constants.inventory.ItemConstants;
import constants.net.OpcodeConstants;
import constants.net.ServerConstants;
+import database.PgDatabaseConfig;
+import database.migration.FlywayRunner;
import database.note.NoteDao;
import net.ChannelDependencies;
import net.PacketProcessor;
@@ -840,6 +843,8 @@ public class Server {
Runtime.getRuntime().addShutdownHook(new Thread(shutdown(false)));
}
+ runDatabaseMigration();
+
if (!DatabaseConnection.initializeConnectionPool()) {
throw new IllegalStateException("Failed to initiate a connection to the database");
}
@@ -922,6 +927,22 @@ public class Server {
}
}
+ private void runDatabaseMigration() {
+ PgDatabaseConfig pgDbConfig = readPgDbConfig();
+ FlywayRunner flywayRunner = new FlywayRunner(pgDbConfig);
+ flywayRunner.migrate();
+ }
+
+ private PgDatabaseConfig readPgDbConfig() {
+ final ServerConfig serverConfig = YamlConfig.config.server;
+ return new PgDatabaseConfig(
+ serverConfig.PG_DB_NAME, serverConfig.PG_DB_HOST, serverConfig.PG_DB_SCHEMA,
+ serverConfig.PG_DB_ADMIN_USERNAME, serverConfig.PG_DB_ADMIN_PASSWORD,
+ serverConfig.PG_DB_USERNAME, serverConfig.PG_DB_PASSWORD,
+ Duration.ofSeconds(serverConfig.INIT_CONNECTION_POOL_TIMEOUT)
+ );
+ }
+
private ChannelDependencies registerChannelDependencies() {
NoteService noteService = new NoteService(new NoteDao());
FredrickProcessor fredrickProcessor = new FredrickProcessor(noteService);
diff --git a/src/main/resources/db/migration/postgresql/V0__test.sql b/src/main/resources/db/migration/postgresql/V0__test.sql
new file mode 100644
index 0000000000..e554e389ed
--- /dev/null
+++ b/src/main/resources/db/migration/postgresql/V0__test.sql
@@ -0,0 +1,4 @@
+CREATE TABLE flyway_test(
+ id SERIAL PRIMARY KEY,
+ dummy TEXT
+);
\ No newline at end of file
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
index 7bc44f142e..2eb24eaa3a 100644
--- a/src/main/resources/log4j2.xml
+++ b/src/main/resources/log4j2.xml
@@ -100,5 +100,7 @@
+
+
\ No newline at end of file