Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion controller-runtime/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -62,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:
Expand Down
70 changes: 70 additions & 0 deletions controller-runtime/src/main/db/schema/mysql.sql
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@
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

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")
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/default.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) {
logger.error("Error executing SQL command: {}", command, e)
throw e
}
}
}

}
3 changes: 3 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down Expand Up @@ -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 = [
Expand Down