diff --git a/.env.example b/.env.example new file mode 100644 index 00000000000..c24b95f81e8 --- /dev/null +++ b/.env.example @@ -0,0 +1,7 @@ +# Database Configuration +# Copy this file to .env and fill in your actual database credentials +# Defaults to config.yaml if not set, remove lines to use config.yaml's values +DB_HOST=localhost +DB_USER=root +DB_PASS=your_password_here +DB_URL_FORMAT=jdbc:mysql://%s:3306/cosmic diff --git a/.gitignore b/.gitignore index 27980c65f98..5bdcfc32f7c 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ database/docker-pg-db-data # macOS files .DS_Store + +# Environment variables +.env diff --git a/pom.xml b/pom.xml index 945a417fd89..4f1884059a2 100644 --- a/pom.xml +++ b/pom.xml @@ -69,6 +69,7 @@ 4.32.0 5.13.1 5.18.0 + 3.0.0 @@ -82,6 +83,11 @@ jcip-annotations ${jcip-annotations.version} + + io.github.cdimascio + dotenv-java + ${dotenv-java.version} + diff --git a/src/main/java/tools/DatabaseConnection.java b/src/main/java/tools/DatabaseConnection.java index b0313b92fac..31da2a2cf3a 100644 --- a/src/main/java/tools/DatabaseConnection.java +++ b/src/main/java/tools/DatabaseConnection.java @@ -46,18 +46,17 @@ public static Handle getHandle() { private static String getDbUrl() { // Environment variables override what's defined in the config file // This feature is used for the Docker support - String hostOverride = System.getenv("DB_HOST"); - String host = hostOverride != null ? hostOverride : YamlConfig.config.server.DB_HOST; - String dbUrl = String.format(YamlConfig.config.server.DB_URL_FORMAT, host); - return dbUrl; + String host = EnvironmentConfig.get("DB_HOST", YamlConfig.config.server.DB_HOST); + String urlFormat = EnvironmentConfig.get("DB_URL_FORMAT", YamlConfig.config.server.DB_URL_FORMAT); + return String.format(urlFormat, host); } private static HikariConfig getConfig() { HikariConfig config = new HikariConfig(); config.setJdbcUrl(getDbUrl()); - config.setUsername(YamlConfig.config.server.DB_USER); - config.setPassword(YamlConfig.config.server.DB_PASS); + config.setUsername(EnvironmentConfig.get("DB_USER", YamlConfig.config.server.DB_USER)); + config.setPassword(EnvironmentConfig.get("DB_PASS", YamlConfig.config.server.DB_PASS)); final int initFailTimeoutSeconds = YamlConfig.config.server.INIT_CONNECTION_POOL_TIMEOUT; config.setInitializationFailTimeout(SECONDS.toMillis(initFailTimeoutSeconds)); diff --git a/src/main/java/tools/EnvironmentConfig.java b/src/main/java/tools/EnvironmentConfig.java new file mode 100644 index 00000000000..e582aae1cc7 --- /dev/null +++ b/src/main/java/tools/EnvironmentConfig.java @@ -0,0 +1,50 @@ +package tools; + +import io.github.cdimascio.dotenv.Dotenv; + +/** + * Provides access to configuration values from .env files and system environment variables. + * Priority order: + * 1. .env file values + * 2. System environment variables + * 3. Provided default value + */ +public class EnvironmentConfig { + private static final Dotenv dotenv; + + static { + dotenv = Dotenv.configure() + .ignoreIfMissing() + .load(); + } + + /** + * Get an environment variable value with fallback to a default. + * + * @param key the environment variable key + * @param defaultValue the default value to use if the variable is not found + * @return the environment variable value, or the default if not found + */ + public static String get(String key, String defaultValue) { + if (key == null || key.isEmpty()) { + return defaultValue; + } + + // First try .env file + if (dotenv != null) { + String value = dotenv.get(key); + if (value != null && !value.isEmpty()) { + return value; + } + } + + // Then try system environment + String value = System.getenv(key); + if (value != null && !value.isEmpty()) { + return value; + } + + // Finally use the provided default + return defaultValue; + } +} diff --git a/src/test/java/tools/EnvironmentConfigTest.java b/src/test/java/tools/EnvironmentConfigTest.java new file mode 100644 index 00000000000..bfde0309c04 --- /dev/null +++ b/src/test/java/tools/EnvironmentConfigTest.java @@ -0,0 +1,14 @@ +package tools; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class EnvironmentConfigTest { + + @Test + void getShouldReturnDefaultWhenVariableNotFound() { + String value = EnvironmentConfig.get("NONEXISTENT_VARIABLE_XYZ", "my_default"); + assertEquals("my_default", value); + } +}