From 994af77d6fdf8d2adc7c4598c93b4a44d950b273 Mon Sep 17 00:00:00 2001 From: sama Date: Tue, 9 Sep 2025 13:54:52 +0200 Subject: [PATCH 1/4] add: mysql driver and new mysql/mariadb schema --- controller-runtime/build.gradle.kts | 1 + .../controller/runtime/database/Database.kt | 31 ++++++++++++++----- gradle/libs.versions.toml | 3 ++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/controller-runtime/build.gradle.kts b/controller-runtime/build.gradle.kts index e23d62d..2af9b40 100644 --- a/controller-runtime/build.gradle.kts +++ b/controller-runtime/build.gradle.kts @@ -9,6 +9,7 @@ dependencies { api(libs.bundles.jooq) api(libs.sqlite.jdbc) + implementation(libs.mysql.connector) implementation(libs.simplecloud.metrics) implementation(libs.bundles.log4j) implementation(libs.clikt) diff --git a/controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/database/Database.kt b/controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/database/Database.kt index 99266b9..553562f 100644 --- a/controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/database/Database.kt +++ b/controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/database/Database.kt @@ -1,6 +1,8 @@ package app.simplecloud.controller.runtime.database import org.jooq.DSLContext +import org.jooq.SQLDialect +import org.jooq.impl.DSL class Database( val context: DSLContext @@ -9,14 +11,27 @@ class Database( fun setup() { System.setProperty("org.jooq.no-logo", "true") System.setProperty("org.jooq.no-tips", "true") - val setupInputStream = Database::class.java.getResourceAsStream("/schema.sql") - ?: throw IllegalArgumentException("Database schema not found.") - val setupCommands = setupInputStream.bufferedReader().use { it.readText() }.split(";") - setupCommands.forEach { - val trimmed = it.trim() - if (trimmed.isNotEmpty()) - context.execute(org.jooq.impl.DSL.sql(trimmed)) + + val schemaFile = when (context.dialect().family()) { + SQLDialect.MARIADB, SQLDialect.MYSQL -> "/schema-mysql.sql" + else -> "/schema.sql" + } + + val setupInputStream = Database::class.java.getResourceAsStream(schemaFile) + ?: throw IllegalArgumentException("Database schema not found: $schemaFile") + + val setupCommands = setupInputStream.bufferedReader().use { it.readText() } + .split(";") + .map { it.trim() } + .filter { it.isNotEmpty() } + + setupCommands.forEach { command -> + try { + context.execute(DSL.using(context.dialect()).parser().parseQuery(command)) + } catch (e: Exception) { + System.err.println("Error executing SQL command: $command") + throw e + } } } - } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index da698d3..de52a09 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,6 +14,7 @@ sonatype-central-portal-publisher = "1.2.3" spotify-completablefutures = "0.3.6" spring-crypto = "6.3.4" envoy = "1.0.46" +mysql-connector = "8.0.33" [libraries] kotlin-jvm = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" } @@ -45,6 +46,8 @@ spotify-completablefutures = { module = "com.spotify:completable-futures", versi spring-crypto = { module = "org.springframework.security:spring-security-crypto", version.ref = "spring-crypto" } envoy-controlplane = { module = "io.envoyproxy.controlplane:server", version.ref = "envoy" } +mysql-connector = { module = "mysql:mysql-connector-java", version.ref = "mysql-connector" } + [bundles] log4j = [ From 6bc99703885fdc256eb715464227ce9aedd219e1 Mon Sep 17 00:00:00 2001 From: sama Date: Tue, 9 Sep 2025 13:57:51 +0200 Subject: [PATCH 2/4] add: schema --- .../src/main/db/schema-mysql.sql | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 controller-runtime/src/main/db/schema-mysql.sql diff --git a/controller-runtime/src/main/db/schema-mysql.sql b/controller-runtime/src/main/db/schema-mysql.sql new file mode 100644 index 0000000..450f4ea --- /dev/null +++ b/controller-runtime/src/main/db/schema-mysql.sql @@ -0,0 +1,70 @@ +/** + MySQL-spezifisches Schema für den v3 Backend. + Diese Datei enthält Anpassungen für MySQL/MariaDB. + Wird automatisch verwendet, wenn MySQL als Datenbank konfiguriert ist. +*/ + +CREATE TABLE IF NOT EXISTS cloud_servers ( + unique_id VARCHAR(36) NOT NULL PRIMARY KEY, + group_name VARCHAR(255) NOT NULL, + host_id VARCHAR(36) NOT NULL, + numerical_id INT NOT NULL, + ip VARCHAR(45) NOT NULL, + port INT NOT NULL, + minimum_memory INT NOT NULL, + maximum_memory INT NOT NULL, + max_players INT NOT NULL, + player_count INT NOT NULL, + state VARCHAR(50) NOT NULL, + type VARCHAR(50) NOT NULL, + created_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + updated_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS cloud_server_properties ( + server_id VARCHAR(36) NOT NULL, + `key` VARCHAR(255) NOT NULL, + value TEXT, + PRIMARY KEY (server_id, `key`), + CONSTRAINT fk_server_props_server FOREIGN KEY (server_id) + REFERENCES cloud_servers(unique_id) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS oauth2_client_details ( + client_id VARCHAR(36) PRIMARY KEY, + client_secret VARCHAR(255), + redirect_uri VARCHAR(512), + grant_types TEXT, + scope TEXT +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS oauth2_users ( + user_id VARCHAR(36) PRIMARY KEY, + scopes TEXT, + username VARCHAR(255) UNIQUE NOT NULL, + hashed_password VARCHAR(255) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS oauth2_tokens ( + token_id VARCHAR(36) PRIMARY KEY, + client_id VARCHAR(36), + access_token TEXT, + scope TEXT, + expires_in TIMESTAMP NULL DEFAULT NULL, + user_id VARCHAR(36), + CONSTRAINT fk_token_user FOREIGN KEY (user_id) + REFERENCES oauth2_users(user_id) ON DELETE CASCADE, + CONSTRAINT fk_token_client FOREIGN KEY (client_id) + REFERENCES oauth2_client_details(client_id) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS oauth2_groups ( + group_name VARCHAR(255) PRIMARY KEY, + scopes TEXT +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS oauth2_user_groups ( + user_id VARCHAR(36), + group_name VARCHAR(255), + PRIMARY KEY (user_id, group_name) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; From 60a6b7abcc7eb2b2951c563594dc8e8526809a49 Mon Sep 17 00:00:00 2001 From: coinsapi Date: Tue, 9 Sep 2025 18:45:58 +0200 Subject: [PATCH 3/4] using logger --- .../app/simplecloud/controller/runtime/database/Database.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/database/Database.kt b/controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/database/Database.kt index 553562f..20ca26e 100644 --- a/controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/database/Database.kt +++ b/controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/database/Database.kt @@ -1,5 +1,6 @@ package app.simplecloud.controller.runtime.database +import org.apache.logging.log4j.LogManager import org.jooq.DSLContext import org.jooq.SQLDialect import org.jooq.impl.DSL @@ -8,6 +9,8 @@ class Database( val context: DSLContext ) { + private val logger = LogManager.getLogger(Database::class.java) + fun setup() { System.setProperty("org.jooq.no-logo", "true") System.setProperty("org.jooq.no-tips", "true") @@ -29,7 +32,7 @@ class Database( try { context.execute(DSL.using(context.dialect()).parser().parseQuery(command)) } catch (e: Exception) { - System.err.println("Error executing SQL command: $command") + logger.error("Error executing SQL command: {}", command, e) throw e } } From ac648807f367e072c61fd9467c62e64b07640262 Mon Sep 17 00:00:00 2001 From: coinsapi Date: Tue, 9 Sep 2025 19:07:33 +0200 Subject: [PATCH 4/4] add schema directory and renamed files --- controller-runtime/build.gradle.kts | 2 +- .../src/main/db/{schema.sql => schema/default.sql} | 0 .../src/main/db/{schema-mysql.sql => schema/mysql.sql} | 0 .../app/simplecloud/controller/runtime/database/Database.kt | 4 ++-- 4 files changed, 3 insertions(+), 3 deletions(-) rename controller-runtime/src/main/db/{schema.sql => schema/default.sql} (100%) rename controller-runtime/src/main/db/{schema-mysql.sql => schema/mysql.sql} (100%) diff --git a/controller-runtime/build.gradle.kts b/controller-runtime/build.gradle.kts index 2af9b40..33ab999 100644 --- a/controller-runtime/build.gradle.kts +++ b/controller-runtime/build.gradle.kts @@ -63,7 +63,7 @@ jooq { // - ? matches a single character in a directory / file name property { key = "scripts" - value = "src/main/db/schema.sql" + value = "src/main/db/schema/default.sql" } // The sort order of the scripts within a directory, where: diff --git a/controller-runtime/src/main/db/schema.sql b/controller-runtime/src/main/db/schema/default.sql similarity index 100% rename from controller-runtime/src/main/db/schema.sql rename to controller-runtime/src/main/db/schema/default.sql diff --git a/controller-runtime/src/main/db/schema-mysql.sql b/controller-runtime/src/main/db/schema/mysql.sql similarity index 100% rename from controller-runtime/src/main/db/schema-mysql.sql rename to controller-runtime/src/main/db/schema/mysql.sql diff --git a/controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/database/Database.kt b/controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/database/Database.kt index 20ca26e..a0d6e3b 100644 --- a/controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/database/Database.kt +++ b/controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/database/Database.kt @@ -16,8 +16,8 @@ class Database( System.setProperty("org.jooq.no-tips", "true") val schemaFile = when (context.dialect().family()) { - SQLDialect.MARIADB, SQLDialect.MYSQL -> "/schema-mysql.sql" - else -> "/schema.sql" + SQLDialect.MARIADB, SQLDialect.MYSQL -> "/schema/mysql.sql" + else -> "/schema/default.sql" } val setupInputStream = Database::class.java.getResourceAsStream(schemaFile)