From d3525eb3598f3443976ab254d23023489b10fead Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Wed, 1 Jan 2025 14:13:15 +0000 Subject: [PATCH] #2270 moving db container to a separate compose file --- .../docker-compose-latest-fat-security.yml | 16 +++--- ...ocker-compose-latest-security-with-sso.yml | 7 +-- .../docker-compose-latest-security.yml | 24 ++------- ...ker-compose-latest-ultra-lite-security.yml | 7 +-- exampleYmlFiles/docker-compose-postgres.yml | 18 +++++++ .../software/SPDF/EE/LicenseKeyChecker.java | 10 ++-- .../security/database/DatabaseConfig.java | 53 ++++++++++++------- .../SPDF/model/ApplicationProperties.java | 1 + src/main/resources/settings.yml.template | 3 +- .../security/database/DatabaseConfigTest.java | 45 +++++++++++++--- 10 files changed, 117 insertions(+), 67 deletions(-) create mode 100644 exampleYmlFiles/docker-compose-postgres.yml diff --git a/exampleYmlFiles/docker-compose-latest-fat-security.yml b/exampleYmlFiles/docker-compose-latest-fat-security.yml index 591091b0fe0..3b5541cbeca 100644 --- a/exampleYmlFiles/docker-compose-latest-fat-security.yml +++ b/exampleYmlFiles/docker-compose-latest-fat-security.yml @@ -1,3 +1,6 @@ +include: + - docker-compose-postgres.yml + services: stirling-pdf: container_name: Stirling-PDF-Security-Fat @@ -14,9 +17,9 @@ services: ports: - 8080:8080 volumes: - - /stirling/latest/data:/usr/share/tessdata:rw - - /stirling/latest/config:/configs:rw - - /stirling/latest/logs:/logs:rw + - ./stirling/latest/data:/usr/share/tessdata:rw + - ./stirling/latest/config:/configs:rw + - ./stirling/latest/logs:/logs:rw environment: DOCKER_ENABLE_SECURITY: "true" SECURITY_ENABLELOGIN: "false" @@ -30,11 +33,8 @@ services: SYSTEM_MAXFILESIZE: "100" METRICS_ENABLED: "true" SYSTEM_GOOGLEVISIBILITY: "true" - SYSTEM_DATASOURCE_TYPE: "postgresql" - SYSTEM_DATASOURCE_HOSTNAME: "db" - SYSTEM_DATASOURCE_PORT: "5432" - SYSTEM_DATASOURCE_NAME: "stirling_pdf" - SYSTEM_DATASOURCE_ENABLECUSTOMDATABASE: "false" + SYSTEM_DATASOURCE_ENABLECUSTOMDATABASE: "true" + SYSTEM_DATASOURCE_CUSTOMDATABASEURL: "jdbc:postgresql://db:5432/stirling_pdf" SYSTEM_DATASOURCE_USERNAME: "admin" SYSTEM_DATASOURCE_PASSWORD: "stirling" restart: on-failure:5 diff --git a/exampleYmlFiles/docker-compose-latest-security-with-sso.yml b/exampleYmlFiles/docker-compose-latest-security-with-sso.yml index fd399c5ec5b..1490d421d82 100644 --- a/exampleYmlFiles/docker-compose-latest-security-with-sso.yml +++ b/exampleYmlFiles/docker-compose-latest-security-with-sso.yml @@ -38,11 +38,8 @@ services: SYSTEM_MAXFILESIZE: "100" METRICS_ENABLED: "true" SYSTEM_GOOGLEVISIBILITY: "true" - SYSTEM_DATASOURCE_TYPE: "postgresql" - SYSTEM_DATASOURCE_HOSTNAME: "db" - SYSTEM_DATASOURCE_PORT: "5432" - SYSTEM_DATASOURCE_NAME: "stirling_pdf" - SYSTEM_DATASOURCE_ENABLECUSTOMDATABASE: "false" + SYSTEM_DATASOURCE_ENABLECUSTOMDATABASE: "true" + SYSTEM_DATASOURCE_CUSTOMDATABASEURL: "jdbc:postgresql://db:5432/stirling_pdf" SYSTEM_DATASOURCE_USERNAME: "admin" SYSTEM_DATASOURCE_PASSWORD: "stirling" restart: on-failure:5 diff --git a/exampleYmlFiles/docker-compose-latest-security.yml b/exampleYmlFiles/docker-compose-latest-security.yml index 1d2cd2c8217..db597047408 100644 --- a/exampleYmlFiles/docker-compose-latest-security.yml +++ b/exampleYmlFiles/docker-compose-latest-security.yml @@ -1,7 +1,7 @@ services: stirling-pdf: container_name: Stirling-PDF-Security - image: stirlingtools/stirling-pdf:test + image: stirlingtools/stirling-pdf:latest deploy: resources: limits: @@ -16,9 +16,9 @@ services: ports: - "8080:8080" volumes: - - /stirling/latest/data:/usr/share/tessdata:rw - - /stirling/latest/config:/configs:rw - - /stirling/latest/logs:/logs:rw + - ./stirling/latest/data:/usr/share/tessdata:rw + - ./stirling/latest/config:/configs:rw + - ./stirling/latest/logs:/logs:rw environment: DOCKER_ENABLE_SECURITY: "true" SECURITY_ENABLELOGIN: "true" @@ -32,22 +32,8 @@ services: SYSTEM_MAXFILESIZE: "100" METRICS_ENABLED: "true" SYSTEM_GOOGLEVISIBILITY: "true" - SYSTEM_DATASOURCE_TYPE: "postgresql" - SYSTEM_DATASOURCE_HOSTNAME: "db" - SYSTEM_DATASOURCE_PORT: "5432" - SYSTEM_DATASOURCE_NAME: "stirling_pdf" SYSTEM_DATASOURCE_ENABLECUSTOMDATABASE: "true" + SYSTEM_DATASOURCE_CUSTOMDATABASEURL: "jdbc:postgresql://db:5432/stirling_pdf" SYSTEM_DATASOURCE_USERNAME: "admin" SYSTEM_DATASOURCE_PASSWORD: "stirling" restart: on-failure:5 - - db: - image: 'postgres:17.2-alpine' - restart: on-failure:5 - container_name: db - ports: - - "5432:5432" - environment: - POSTGRES_DB: "stirling_pdf" - POSTGRES_USER: "admin" - POSTGRES_PASSWORD: "stirling" \ No newline at end of file diff --git a/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml b/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml index 881c433087c..0505eff0bbd 100644 --- a/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml +++ b/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml @@ -27,11 +27,8 @@ services: SYSTEM_MAXFILESIZE: "100" METRICS_ENABLED: "true" SYSTEM_GOOGLEVISIBILITY: "true" - SYSTEM_DATASOURCE_TYPE: "postgresql" - SYSTEM_DATASOURCE_HOSTNAME: "db" - SYSTEM_DATASOURCE_PORT: "5432" - SYSTEM_DATASOURCE_NAME: "stirling_pdf" - SYSTEM_DATASOURCE_ENABLECUSTOMDATABASE: "false" + SYSTEM_DATASOURCE_ENABLECUSTOMDATABASE: "true" + SYSTEM_DATASOURCE_CUSTOMDATABASEURL: "jdbc:postgresql://db:5432/stirling_pdf" SYSTEM_DATASOURCE_USERNAME: "admin" SYSTEM_DATASOURCE_PASSWORD: "stirling" restart: on-failure:5 diff --git a/exampleYmlFiles/docker-compose-postgres.yml b/exampleYmlFiles/docker-compose-postgres.yml new file mode 100644 index 00000000000..61729f3c2e2 --- /dev/null +++ b/exampleYmlFiles/docker-compose-postgres.yml @@ -0,0 +1,18 @@ +services: + db: + image: 'postgres:17.2-alpine' + restart: on-failure:5 + container_name: db + ports: + - "5432:5432" + environment: + POSTGRES_DB: "stirling_pdf" + POSTGRES_USER: "admin" + POSTGRES_PASSWORD: "stirling" + healthcheck: + test: [ "CMD-SHELL", "pg_isready -U admin stirling_pdf" ] + interval: 1s + timeout: 5s + retries: 10 + volumes: + - ./stirling/latest/data:/pgdata \ No newline at end of file diff --git a/src/main/java/stirling/software/SPDF/EE/LicenseKeyChecker.java b/src/main/java/stirling/software/SPDF/EE/LicenseKeyChecker.java index 108ee30204b..4636c892643 100644 --- a/src/main/java/stirling/software/SPDF/EE/LicenseKeyChecker.java +++ b/src/main/java/stirling/software/SPDF/EE/LicenseKeyChecker.java @@ -18,7 +18,7 @@ public class LicenseKeyChecker { private final ApplicationProperties applicationProperties; - private boolean enterpriseEnbaledResult = false; + private boolean enterpriseEnabledResult = false; @Autowired public LicenseKeyChecker( @@ -35,12 +35,12 @@ public void checkLicensePeriodically() { private void checkLicense() { if (!applicationProperties.getEnterpriseEdition().isEnabled()) { - enterpriseEnbaledResult = false; + enterpriseEnabledResult = false; } else { - enterpriseEnbaledResult = + enterpriseEnabledResult = licenseService.verifyLicense( applicationProperties.getEnterpriseEdition().getKey()); - if (enterpriseEnbaledResult) { + if (enterpriseEnabledResult) { log.info("License key is valid."); } else { log.info("License key is invalid."); @@ -55,6 +55,6 @@ public void updateLicenseKey(String newKey) throws IOException { } public boolean getEnterpriseEnabledResult() { - return enterpriseEnbaledResult; + return enterpriseEnabledResult; } } diff --git a/src/main/java/stirling/software/SPDF/config/security/database/DatabaseConfig.java b/src/main/java/stirling/software/SPDF/config/security/database/DatabaseConfig.java index f7efef2add4..f835ca7252c 100644 --- a/src/main/java/stirling/software/SPDF/config/security/database/DatabaseConfig.java +++ b/src/main/java/stirling/software/SPDF/config/security/database/DatabaseConfig.java @@ -3,6 +3,7 @@ import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -25,10 +26,12 @@ public class DatabaseConfig { public static final String POSTGRES_DRIVER = "org.postgresql.Driver"; private final ApplicationProperties applicationProperties; + private final boolean runningEE; @Autowired - public DatabaseConfig(ApplicationProperties applicationProperties) { + public DatabaseConfig(ApplicationProperties applicationProperties, boolean runningEE) { this.applicationProperties = applicationProperties; + this.runningEE = runningEE; } /** @@ -40,35 +43,49 @@ public DatabaseConfig(ApplicationProperties applicationProperties) { * @throws UnsupportedProviderException if the type of database selected is not supported */ @Bean + @Qualifier("dataSource") public DataSource dataSource() throws UnsupportedProviderException { - ApplicationProperties.System system = applicationProperties.getSystem(); - ApplicationProperties.Datasource datasource = system.getDatasource(); DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); - if (!datasource.isEnableCustomDatabase()) { - log.info("Using default H2 database"); + if (!runningEE) { + return useDefaultDataSource(dataSourceBuilder); + } - dataSourceBuilder.driverClassName(DEFAULT_DRIVER); - dataSourceBuilder.url(DATASOURCE_DEFAULT_URL); - dataSourceBuilder.username(DEFAULT_USERNAME); + ApplicationProperties.System system = applicationProperties.getSystem(); + ApplicationProperties.Datasource datasource = system.getDatasource(); - return dataSourceBuilder.build(); + if (!datasource.isEnableCustomDatabase()) { + return useDefaultDataSource(dataSourceBuilder); } - log.info("Using custom database"); - dataSourceBuilder.driverClassName(getDriverClassName(datasource.getType())); - dataSourceBuilder.url( - getDataSourceUrl( - datasource.getType(), - datasource.getHostName(), - datasource.getPort(), - datasource.getName())); + log.info("Using custom database configuration"); + + if (!datasource.getCustomDatabaseUrl().isBlank()) { + dataSourceBuilder.url(datasource.getCustomDatabaseUrl()); + } else { + dataSourceBuilder.driverClassName(getDriverClassName(datasource.getType())); + dataSourceBuilder.url( + generateCustomDataSourceUrl( + datasource.getType(), + datasource.getHostName(), + datasource.getPort(), + datasource.getName())); + } dataSourceBuilder.username(datasource.getUsername()); dataSourceBuilder.password(datasource.getPassword()); return dataSourceBuilder.build(); } + private DataSource useDefaultDataSource(DataSourceBuilder dataSourceBuilder) { + log.info("Using default H2 database"); + + dataSourceBuilder.url(DATASOURCE_DEFAULT_URL); + dataSourceBuilder.username(DEFAULT_USERNAME); + + return dataSourceBuilder.build(); + } + /** * Generate the URL the DataSource will use to connect to the database * @@ -78,7 +95,7 @@ public DataSource dataSource() throws UnsupportedProviderException { * @param dataSourceName the name the database to connect to * @return the DataSource URL */ - private String getDataSourceUrl( + private String generateCustomDataSourceUrl( String dataSourceType, String hostname, Integer port, String dataSourceName) { return DATASOURCE_URL_TEMPLATE.formatted(dataSourceType, hostname, port, dataSourceName); } diff --git a/src/main/java/stirling/software/SPDF/model/ApplicationProperties.java b/src/main/java/stirling/software/SPDF/model/ApplicationProperties.java index 19e1431b7c4..051fdb47ea1 100644 --- a/src/main/java/stirling/software/SPDF/model/ApplicationProperties.java +++ b/src/main/java/stirling/software/SPDF/model/ApplicationProperties.java @@ -253,6 +253,7 @@ public static class System { @Data public static class Datasource { private boolean enableCustomDatabase; + private String customDatabaseUrl; private String type; private String hostName; private Integer port; diff --git a/src/main/resources/settings.yml.template b/src/main/resources/settings.yml.template index 8942b0b1278..28fe882a24a 100644 --- a/src/main/resources/settings.yml.template +++ b/src/main/resources/settings.yml.template @@ -86,7 +86,8 @@ system: tessdataDir: /usr/share/tessdata # path to the directory containing the Tessdata files. This setting is relevant for Windows systems. For Windows users, this path should be adjusted to point to the appropriate directory where the Tessdata files are stored. enableAnalytics: undefined # set to 'true' to enable analytics, set to 'false' to disable analytics; for enterprise users, this is set to true datasource: - enableCustomDatabase: true # set this property to 'true' if you would like to use the default database configuration + enableCustomDatabase: true # set this property to 'true' if you would like to use your own custom database configuration + customDatabaseUrl: jdbc:postgresql://localhost:5432/postgres # set the url for your own custom database connection type: postgresql # the type of the database to set (e.g. 'h2', 'postgresql') hostName: localhost # the host name to use for the database url. Set to 'localhost' when running the app locally. Set to match the name of the container name of your database container when running the app on a server (Docker configuration) port: 5432 # set the port number of the database. Ensure this matches the port the database is listening to diff --git a/src/test/java/stirling/software/SPDF/config/security/database/DatabaseConfigTest.java b/src/test/java/stirling/software/SPDF/config/security/database/DatabaseConfigTest.java index 868b9b248ec..4c54e37380d 100644 --- a/src/test/java/stirling/software/SPDF/config/security/database/DatabaseConfigTest.java +++ b/src/test/java/stirling/software/SPDF/config/security/database/DatabaseConfigTest.java @@ -1,5 +1,6 @@ package stirling.software.SPDF.config.security.database; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -22,9 +23,22 @@ class DatabaseConfigTest { @Mock private ApplicationProperties applicationProperties; - @InjectMocks private DatabaseConfig databaseConfig; + @BeforeEach + void setUp() { + databaseConfig = new DatabaseConfig(applicationProperties, true); + } + + @Test + void testDataSource_whenRunningEEIsFalse() throws UnsupportedProviderException { + databaseConfig = new DatabaseConfig(applicationProperties, false); + + var result = databaseConfig.dataSource(); + + assertInstanceOf(DataSource.class, result); + } + @Test void testDefaultConfigurationForDataSource() throws UnsupportedProviderException { var system = mock(ApplicationProperties.System.class); @@ -39,6 +53,23 @@ void testDefaultConfigurationForDataSource() throws UnsupportedProviderException assertInstanceOf(DataSource.class, result); } + @Test + void testCustomUrlForDataSource() throws UnsupportedProviderException { + var system = mock(ApplicationProperties.System.class); + var datasource = mock(ApplicationProperties.Datasource.class); + + when(applicationProperties.getSystem()).thenReturn(system); + when(system.getDatasource()).thenReturn(datasource); + when(datasource.isEnableCustomDatabase()).thenReturn(true); + when(datasource.getCustomDatabaseUrl()).thenReturn("jdbc:postgresql://mockUrl"); + when(datasource.getUsername()).thenReturn("test"); + when(datasource.getPassword()).thenReturn("pass"); + + var result = databaseConfig.dataSource(); + + assertInstanceOf(DataSource.class, result); + } + @Test void testCustomConfigurationForDataSource() throws UnsupportedProviderException { var system = mock(ApplicationProperties.System.class); @@ -47,12 +78,13 @@ void testCustomConfigurationForDataSource() throws UnsupportedProviderException when(applicationProperties.getSystem()).thenReturn(system); when(system.getDatasource()).thenReturn(datasource); when(datasource.isEnableCustomDatabase()).thenReturn(true); + when(datasource.getCustomDatabaseUrl()).thenReturn(""); when(datasource.getType()).thenReturn("postgresql"); - when(datasource.getHostName()).thenReturn("localhost"); - when(datasource.getPort()).thenReturn(5432); - when(datasource.getName()).thenReturn("postgres"); - when(datasource.getUsername()).thenReturn("postgres"); - when(datasource.getPassword()).thenReturn("postgres"); + when(datasource.getHostName()).thenReturn("test"); + when(datasource.getPort()).thenReturn(1234); + when(datasource.getName()).thenReturn("test_db"); + when(datasource.getUsername()).thenReturn("test"); + when(datasource.getPassword()).thenReturn("pass"); var result = databaseConfig.dataSource(); @@ -68,6 +100,7 @@ void exceptionThrownWhenDBTypeIsUnsupported(String datasourceType) { when(applicationProperties.getSystem()).thenReturn(system); when(system.getDatasource()).thenReturn(datasource); when(datasource.isEnableCustomDatabase()).thenReturn(true); + when(datasource.getCustomDatabaseUrl()).thenReturn(""); when(datasource.getType()).thenReturn(datasourceType); assertThrows(UnsupportedProviderException.class, () -> databaseConfig.dataSource());