From 6aaedf52eaf071d3746934940247046b6ef83c02 Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Wed, 16 Apr 2025 16:56:18 +0100 Subject: [PATCH 01/15] wip - making db and sessions conditional --- .../SPDF/config/security/UserAuthenticationFilter.java | 2 ++ .../stirling/software/SPDF/config/security/UserService.java | 3 ++- .../SPDF/config/security/database/DatabaseConfig.java | 4 ++++ .../SPDF/config/security/session/SessionRegistryConfig.java | 2 ++ .../SPDF/config/security/session/SessionRepository.java | 2 ++ 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java b/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java index 70e65e23b9..5208e8f252 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java +++ b/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Optional; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; @@ -34,6 +35,7 @@ import stirling.software.common.model.ApplicationProperties.Security.SAML2; @Slf4j @Component +@ConditionalOnProperty(name = "premium.enabled", havingValue = "true") public class UserAuthenticationFilter extends OncePerRequestFilter { private final ApplicationProperties.Security securityProp; diff --git a/src/main/java/stirling/software/SPDF/config/security/UserService.java b/src/main/java/stirling/software/SPDF/config/security/UserService.java index 71aad721d2..068fde1d43 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserService.java +++ b/src/main/java/stirling/software/SPDF/config/security/UserService.java @@ -11,6 +11,7 @@ import java.util.Optional; import java.util.UUID; import org.springframework.context.MessageSource; +import org.springframework.context.annotation.Lazy; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -56,7 +57,7 @@ public class UserService implements UserServiceInterface { private final SessionPersistentRegistry sessionRegistry; - private final DatabaseInterface databaseService; + @Lazy private final DatabaseInterface databaseService; private final ApplicationProperties.Security.OAUTH2 oAuth2; 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 3deeee48a6..73ccbe3b73 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,9 +3,11 @@ package stirling.software.SPDF.config.security.database; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -16,7 +18,9 @@ import stirling.software.common.model.exception.UnsupportedProviderException; @Slf4j @Getter +@Lazy @Configuration +@ConditionalOnProperty(name = "premium.proFeatures.database", havingValue = "true") public class DatabaseConfig { public final String DATASOURCE_DEFAULT_URL; diff --git a/src/main/java/stirling/software/SPDF/config/security/session/SessionRegistryConfig.java b/src/main/java/stirling/software/SPDF/config/security/session/SessionRegistryConfig.java index 8fa24e95ab..18a84279cb 100644 --- a/src/main/java/stirling/software/SPDF/config/security/session/SessionRegistryConfig.java +++ b/src/main/java/stirling/software/SPDF/config/security/session/SessionRegistryConfig.java @@ -1,10 +1,12 @@ package stirling.software.SPDF.config.security.session; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.core.session.SessionRegistryImpl; @Configuration +@ConditionalOnProperty(name = "premium.enabled", havingValue = "true") public class SessionRegistryConfig { @Bean diff --git a/src/main/java/stirling/software/SPDF/config/security/session/SessionRepository.java b/src/main/java/stirling/software/SPDF/config/security/session/SessionRepository.java index b7f0133f33..d4f2f4bcce 100644 --- a/src/main/java/stirling/software/SPDF/config/security/session/SessionRepository.java +++ b/src/main/java/stirling/software/SPDF/config/security/session/SessionRepository.java @@ -3,6 +3,7 @@ package stirling.software.SPDF.config.security.session; import java.util.Date; import java.util.List; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -14,6 +15,7 @@ import jakarta.transaction.Transactional; import stirling.software.SPDF.model.SessionEntity; @Repository +@ConditionalOnProperty(name = "premium.enabled", havingValue = "true") public interface SessionRepository extends JpaRepository { List findByPrincipalName(String principalName); From 3d312c2fd1312ab8f6c863cd6af0f23828e58c80 Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Wed, 16 Apr 2025 16:56:18 +0100 Subject: [PATCH 02/15] creating new proprietary module --- src/main/resources/settings.yml.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/settings.yml.template b/src/main/resources/settings.yml.template index 0226776c53..2228b73a78 100644 --- a/src/main/resources/settings.yml.template +++ b/src/main/resources/settings.yml.template @@ -64,7 +64,7 @@ premium: key: 00000000-0000-0000-0000-000000000000 enabled: true # Enable license key checks for pro/enterprise features proFeatures: - database: true # Enable database features + customDatabase: false # Enable database features todo: use only for custom DB SSOAutoLogin: false CustomMetadata: autoUpdateMetadata: false From 58937a6e9187bf80a8c666cb5e63bfc3289438cc Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Fri, 9 May 2025 16:48:48 +0100 Subject: [PATCH 03/15] moving security package and relevant files over to proprietary --- LICENSE | 7 + build.gradle | 49 +-- .../gradle/wrapper/gradle-wrapper.properties | 6 + common/gradlew | 251 ++++++++++++++ common/gradlew.bat | 94 +++++ proprietary/.gitignore | 196 +++++++++++ proprietary/LICENSE-proprietary | 45 +++ proprietary/build.gradle | 68 ++++ .../gradle/wrapper/gradle-wrapper.properties | 6 + proprietary/gradlew | 251 ++++++++++++++ proprietary/gradlew.bat | 94 +++++ .../CustomAuthenticationFailureHandler.java | 18 +- .../CustomAuthenticationSuccessHandler.java | 16 +- .../security/CustomLogoutSuccessHandler.java | 32 +- .../security/InitialSecuritySetup.java | 19 +- .../security/RateLimitResetScheduler.java | 8 +- .../configuration}/DatabaseConfig.java | 35 +- .../security/configuration}/MailConfig.java | 3 +- .../configuration/SecurityConfiguration.java | 320 ++++++++++++++++++ .../controller/api/DatabaseController.java | 6 +- .../controller/api/EmailController.java | 6 +- .../controller/api/UserController.java | 16 +- .../controller/web/AccountWebController.java | 16 +- .../controller/web/DatabaseWebController.java | 4 +- .../security/database}/H2SQLCondition.java | 10 +- .../security/database/ScheduledTasks.java | 12 +- .../repository/AuthorityRepository.java | 5 +- .../repository/JPATokenRepositoryImpl.java | 5 +- .../repository/PersistentLoginRepository.java | 5 +- .../repository}/SessionRepository.java | 11 +- .../database}/repository/UserRepository.java | 5 +- .../filter}/EnterpriseEndpointFilter.java | 2 +- .../security/filter}/FirstLoginFilter.java | 27 +- .../filter}/IPRateLimitingFilter.java | 13 +- .../filter}/UserAuthenticationFilter.java | 27 +- .../filter}/UserBasedRateLimitingFilter.java | 24 +- .../model/ApiKeyAuthenticationToken.java | 2 +- .../security}/model/AttemptCounter.java | 2 +- .../security/model/AuthenticationType.java | 6 + .../security}/model/Authority.java | 2 +- .../security}/model/PersistentLogin.java | 2 +- .../security}/model/SessionEntity.java | 2 +- .../proprietary/security}/model/User.java | 3 +- .../proprietary/security/model/api/Email.java | 39 +++ .../model/api/user/UpdateUserDetails.java | 17 + .../model/api/user/UpdateUserUsername.java | 14 + .../security/model/api/user/Username.java | 14 + .../model/api/user/UsernameAndPass.java | 14 + .../exception/BackupNotFoundException.java | 2 +- .../exception/NoProviderFoundException.java | 2 +- ...tomOAuth2AuthenticationFailureHandler.java | 13 +- ...tomOAuth2AuthenticationSuccessHandler.java | 22 +- .../security/oauth2/OAuth2Configuration.java | 22 +- .../security/saml2/CertificateUtils.java | 3 +- .../CustomSaml2AuthenticatedPrincipal.java | 3 +- ...stomSaml2AuthenticationFailureHandler.java | 11 +- ...stomSaml2AuthenticationSuccessHandler.java | 24 +- ...mSaml2ResponseAuthenticationConverter.java | 19 +- .../security/saml2/SAML2Configuration.java | 12 +- .../service}/AppUpdateAuthService.java | 13 +- .../service}/CustomOAuth2UserService.java | 11 +- .../service}/CustomUserDetailsService.java | 13 +- .../security/service}/DatabaseService.java | 35 +- .../service/DatabaseServiceInterface.java | 4 +- .../security/service}/EmailService.java | 4 +- .../service}/LoginAttemptService.java | 14 +- .../security/service}/UserService.java | 32 +- .../session/CustomHttpSessionListener.java | 6 +- .../session/SessionPersistentRegistry.java | 22 +- .../session/SessionRegistryConfig.java | 8 +- .../security/session/SessionScheduled.java | 6 +- .../CustomLogoutSuccessHandlerTest.java | 15 +- .../configuration}/DatabaseConfigTest.java | 10 +- .../controller/api/EmailControllerTest.java | 6 +- .../security/service}/EmailServiceTest.java | 11 +- .../security/service}/MailConfigTest.java | 3 +- settings.gradle | 2 +- .../SPDF/config/AppUpdateService.java | 2 +- .../config/interfaces/ShowAdminInterface.java | 7 - .../security/SecurityConfiguration.java | 319 ----------------- .../converters/ConvertOfficeController.java | 2 +- .../api/pipeline/ApiDocService.java | 2 +- .../api/pipeline/PipelineProcessor.java | 2 +- .../api/security/SanitizeController.java | 13 +- .../SPDF/model/AuthenticationType.java | 6 - .../software/SPDF/model/PdfMetadata.java | 19 -- .../stirling/software/SPDF/model/Role.java | 66 ---- 87 files changed, 1758 insertions(+), 857 deletions(-) create mode 100644 common/gradle/wrapper/gradle-wrapper.properties create mode 100755 common/gradlew create mode 100644 common/gradlew.bat create mode 100644 proprietary/.gitignore create mode 100644 proprietary/LICENSE-proprietary create mode 100644 proprietary/build.gradle create mode 100644 proprietary/gradle/wrapper/gradle-wrapper.properties create mode 100755 proprietary/gradlew create mode 100644 proprietary/gradlew.bat rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/CustomAuthenticationFailureHandler.java (93%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/CustomAuthenticationSuccessHandler.java (92%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/CustomLogoutSuccessHandler.java (95%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/InitialSecuritySetup.java (91%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/RateLimitResetScheduler.java (78%) rename {src/main/java/stirling/software/SPDF/config/security/database => proprietary/src/main/java/stirling/software/proprietary/security/configuration}/DatabaseConfig.java (86%) rename {src/main/java/stirling/software/SPDF/config/security/mail => proprietary/src/main/java/stirling/software/proprietary/security/configuration}/MailConfig.java (96%) create mode 100644 proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security}/controller/api/DatabaseController.java (97%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security}/controller/api/EmailController.java (93%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security}/controller/api/UserController.java (97%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security}/controller/web/AccountWebController.java (97%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security}/controller/web/DatabaseWebController.java (92%) rename {src/main/java/stirling/software/SPDF/controller/api => proprietary/src/main/java/stirling/software/proprietary/security/database}/H2SQLCondition.java (77%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/database/ScheduledTasks.java (71%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security/database}/repository/AuthorityRepository.java (74%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security/database}/repository/JPATokenRepositoryImpl.java (93%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security/database}/repository/PersistentLoginRepository.java (65%) rename {src/main/java/stirling/software/SPDF/config/security/session => proprietary/src/main/java/stirling/software/proprietary/security/database/repository}/SessionRepository.java (79%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security/database}/repository/UserRepository.java (86%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary/security/filter}/EnterpriseEndpointFilter.java (95%) rename {src/main/java/stirling/software/SPDF/config/security => proprietary/src/main/java/stirling/software/proprietary/security/filter}/FirstLoginFilter.java (94%) rename {src/main/java/stirling/software/SPDF/config/security => proprietary/src/main/java/stirling/software/proprietary/security/filter}/IPRateLimitingFilter.java (90%) rename {src/main/java/stirling/software/SPDF/config/security => proprietary/src/main/java/stirling/software/proprietary/security/filter}/UserAuthenticationFilter.java (96%) rename {src/main/java/stirling/software/SPDF/config/security => proprietary/src/main/java/stirling/software/proprietary/security/filter}/UserBasedRateLimitingFilter.java (98%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security}/model/ApiKeyAuthenticationToken.java (96%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security}/model/AttemptCounter.java (93%) create mode 100644 proprietary/src/main/java/stirling/software/proprietary/security/model/AuthenticationType.java rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security}/model/Authority.java (94%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security}/model/PersistentLogin.java (91%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security}/model/SessionEntity.java (88%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security}/model/User.java (95%) create mode 100644 proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java create mode 100644 proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/UpdateUserDetails.java create mode 100644 proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/UpdateUserUsername.java create mode 100644 proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/Username.java create mode 100644 proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/UsernameAndPass.java rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security}/model/exception/BackupNotFoundException.java (70%) rename {src/main/java/stirling/software/SPDF => proprietary/src/main/java/stirling/software/proprietary/security}/model/exception/NoProviderFoundException.java (79%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java (97%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java (94%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/oauth2/OAuth2Configuration.java (96%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/saml2/CertificateUtils.java (97%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/saml2/CustomSaml2AuthenticatedPrincipal.java (93%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/saml2/CustomSaml2AuthenticationFailureHandler.java (96%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/saml2/CustomSaml2AuthenticationSuccessHandler.java (95%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/saml2/CustomSaml2ResponseAuthenticationConverter.java (94%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/saml2/SAML2Configuration.java (99%) rename {src/main/java/stirling/software/SPDF/config/security => proprietary/src/main/java/stirling/software/proprietary/security/service}/AppUpdateAuthService.java (83%) rename {src/main/java/stirling/software/SPDF/config/security/oauth2 => proprietary/src/main/java/stirling/software/proprietary/security/service}/CustomOAuth2UserService.java (94%) rename {src/main/java/stirling/software/SPDF/config/security => proprietary/src/main/java/stirling/software/proprietary/security/service}/CustomUserDetailsService.java (89%) rename {src/main/java/stirling/software/SPDF/config/security/database => proprietary/src/main/java/stirling/software/proprietary/security/service}/DatabaseService.java (91%) rename src/main/java/stirling/software/SPDF/config/interfaces/DatabaseInterface.java => proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseServiceInterface.java (77%) rename {src/main/java/stirling/software/SPDF/config/security/mail => proprietary/src/main/java/stirling/software/proprietary/security/service}/EmailService.java (96%) rename {src/main/java/stirling/software/SPDF/config/security => proprietary/src/main/java/stirling/software/proprietary/security/service}/LoginAttemptService.java (95%) rename {src/main/java/stirling/software/SPDF/config/security => proprietary/src/main/java/stirling/software/proprietary/security/service}/UserService.java (95%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/session/CustomHttpSessionListener.java (92%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/session/SessionPersistentRegistry.java (94%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/session/SessionRegistryConfig.java (57%) rename {src/main/java/stirling/software/SPDF/config => proprietary/src/main/java/stirling/software/proprietary}/security/session/SessionScheduled.java (95%) rename {src/test/java/stirling/software/SPDF/config => proprietary/src/test/java/stirling/software/proprietary}/security/CustomLogoutSuccessHandlerTest.java (98%) rename {src/test/java/stirling/software/SPDF/config/security/database => proprietary/src/test/java/stirling/software/proprietary/security/configuration}/DatabaseConfigTest.java (94%) rename {src/test/java/stirling/software/SPDF => proprietary/src/test/java/stirling/software/proprietary/security}/controller/api/EmailControllerTest.java (94%) rename {src/test/java/stirling/software/SPDF/config/security/mail => proprietary/src/test/java/stirling/software/proprietary/security/service}/EmailServiceTest.java (94%) rename {src/test/java/stirling/software/SPDF/config/security/mail => proprietary/src/test/java/stirling/software/proprietary/security/service}/MailConfigTest.java (94%) delete mode 100644 src/main/java/stirling/software/SPDF/config/interfaces/ShowAdminInterface.java delete mode 100644 src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java delete mode 100644 src/main/java/stirling/software/SPDF/model/AuthenticationType.java delete mode 100644 src/main/java/stirling/software/SPDF/model/PdfMetadata.java delete mode 100644 src/main/java/stirling/software/SPDF/model/Role.java diff --git a/LICENSE b/LICENSE index 10633f4a31..0cd290e886 100644 --- a/LICENSE +++ b/LICENSE @@ -2,6 +2,13 @@ MIT License Copyright (c) 2024 Stirling Tools +Portions of this software are licensed as follows: + +* All content that resides under the "proprietary/" directory of this repository, +if that directory exists, is licensed under the license defined in "proprietary/LICENSE". +* Content outside of the above mentioned directories or restrictions above is +available under the MIT License as defined below. + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights diff --git a/build.gradle b/build.gradle index 25d34635f8..cf5a3b7287 100644 --- a/build.gradle +++ b/build.gradle @@ -52,24 +52,7 @@ sourceSets { main { java { if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") { - exclude "stirling/software/SPDF/config/interfaces/DatabaseInterface.java" - exclude "stirling/software/SPDF/config/security/**" - exclude "stirling/software/SPDF/controller/api/DatabaseController.java" - exclude "stirling/software/SPDF/controller/api/EmailController.java" - exclude "stirling/software/SPDF/controller/api/H2SQLCondition.java" - exclude "stirling/software/SPDF/controller/api/UserController.java" - exclude "stirling/software/SPDF/controller/web/AccountWebController.java" - exclude "stirling/software/SPDF/controller/web/DatabaseWebController.java" - exclude "stirling/software/SPDF/model/api/Email.java" - exclude "stirling/software/SPDF/model/ApiKeyAuthenticationToken.java" - exclude "stirling/software/SPDF/model/AttemptCounter.java" - exclude "stirling/software/SPDF/model/Authority.java" - exclude "stirling/software/SPDF/model/exception/BackupNotFoundException.java" - exclude "stirling/software/SPDF/model/exception/NoProviderFoundException.java" - exclude "stirling/software/SPDF/model/PersistentLogin.java" - exclude "stirling/software/SPDF/model/SessionEntity.java" - exclude "stirling/software/SPDF/model/User.java" - exclude "stirling/software/SPDF/repository/**" + exclude "stirling/software/proprietary/security/**" } if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") { @@ -82,10 +65,7 @@ sourceSets { test { java { if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") { - exclude "stirling/software/SPDF/config/security/**" - exclude "stirling/software/SPDF/model/ApiKeyAuthenticationTokenTest.java" - exclude "stirling/software/SPDF/controller/api/EmailControllerTest.java" - exclude "stirling/software/SPDF/repository/**" + exclude "stirling/software/proprietary/security/**" } if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") { @@ -450,30 +430,7 @@ dependencies { if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") { - implementation 'io.micrometer:micrometer-registry-prometheus' - - implementation "org.springframework.boot:spring-boot-starter-security:$springBootVersion" - implementation "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.3.RELEASE" - implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion" - implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion" - implementation "org.springframework.boot:spring-boot-starter-mail:$springBootVersion" - - implementation "org.springframework.session:spring-session-core:3.5.0" - implementation "org.springframework:spring-jdbc:6.2.7" - - implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5' - // Don't upgrade h2database - runtimeOnly "com.h2database:h2:2.3.232" - runtimeOnly "org.postgresql:postgresql:42.7.6" - constraints { - implementation "org.opensaml:opensaml-core:$openSamlVersion" - implementation "org.opensaml:opensaml-saml-api:$openSamlVersion" - implementation "org.opensaml:opensaml-saml-impl:$openSamlVersion" - } - implementation "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion" - // implementation 'org.springframework.security:spring-security-core:$springSecuritySamlVersion' - implementation 'com.coveo:saml-client:5.0.0' - + implementation project(':proprietary') } implementation 'org.snakeyaml:snakeyaml-engine:2.9' diff --git a/common/gradle/wrapper/gradle-wrapper.properties b/common/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..f7664bccf7 --- /dev/null +++ b/common/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/common/gradlew b/common/gradlew new file mode 100755 index 0000000000..23d15a9367 --- /dev/null +++ b/common/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/common/gradlew.bat b/common/gradlew.bat new file mode 100644 index 0000000000..db3a6ac207 --- /dev/null +++ b/common/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/proprietary/.gitignore b/proprietary/.gitignore new file mode 100644 index 0000000000..90d48ccea0 --- /dev/null +++ b/proprietary/.gitignore @@ -0,0 +1,196 @@ +### Eclipse ### +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.exe +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders +.classpath +.project +version.properties + +#### Stirling-PDF Files ### +pipeline/watchedFolders/ +pipeline/finishedFolders/ +customFiles/ +configs/ +watchedFolders/ +clientWebUI/ +!cucumber/ +!cucumber/exampleFiles/ +!cucumber/exampleFiles/example_html.zip +exampleYmlFiles/stirling/ +/testing/file_snapshots +SwaggerDoc.json + +# Gradle +.gradle +.lock + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ +.apt_generated_test/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# Uncomment this line if you wish to ignore the project description file. +# Typically, this file would be tracked if it contains build/dependency configurations: +#.project + +### Eclipse Patch ### +# Spring Boot Tooling +.sts4-cache/ + +### Git ### +# Created by git for backups. To disable backups in Git: +# $ git config --global mergetool.keepBackup false +*.orig + +# Created by git when using merge tools for conflicts +*.BACKUP.* +*.BASE.* +*.LOCAL.* +*.REMOTE.* +*_BACKUP_*.txt +*_BASE_*.txt +*_LOCAL_*.txt +*_REMOTE_*.txt + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar +*.db +/build + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*.pyo + +# Virtual environments +.env* +.venv* +env*/ +venv*/ +ENV/ +env.bak/ +venv.bak/ + +# VS Code +/.vscode/**/* +!/.vscode/settings.json +!/.vscode/extensions.json + +# IntelliJ IDEA +.idea/ +*.iml +out/ + +# Ignore Mac DS_Store files +.DS_Store +**/.DS_Store + +# cucumber +/cucumber/reports/** + +# Certs and Security Files +*.p12 +*.pk8 +*.pem +*.crt +*.cer +*.cert +*.der +*.key +*.csr +*.kdbx +*.jks +*.asc + +# SSH Keys +*.pub +*.priv +id_rsa +id_rsa.pub +id_ecdsa +id_ecdsa.pub +id_ed25519 +id_ed25519.pub +.ssh/ +*ssh + +# cache +.cache +.ruff_cache +.mypy_cache +.pytest_cache +.ipynb_checkpoints + +**/jcef-bundle/ + +# node_modules +node_modules/ +*.mjs diff --git a/proprietary/LICENSE-proprietary b/proprietary/LICENSE-proprietary new file mode 100644 index 0000000000..f723a28092 --- /dev/null +++ b/proprietary/LICENSE-proprietary @@ -0,0 +1,45 @@ +Stirling PDF Enterprise Edition (EE) license (the “EE License”) + +Copyright (c) 2025-present Stirling Tools + +With regard to the Stirling PDF Software: + +This software and associated documentation files (the "Software") may only be +used in production, if you (and any entity that you represent) have agreed to, +and are in compliance with, the Stirling PDF Terms of Service, available +at https://www.stirlingpdf.com/terms-and-conditions (the “EE Terms”), or other +agreement governing the use of the Software, as agreed by you and Stirling PDF, +and otherwise have a valid Stirling PDF Enterprise Edition subscription for the +correct number of user seats. Subject to the foregoing sentence, you are free to +modify this Software and publish patches to the Software. You agree that Stirling PDF +and/or its licensors (as applicable) retain all right, title and interest in and +to all such modifications and/or patches, and all such modifications and/or +patches may only be used, copied, modified, displayed, distributed, or otherwise +exploited with a valid Stirling PDF Enterprise Edition subscription for the correct +number of user seats. Notwithstanding the foregoing, you may copy and modify +the Software for development and testing purposes, without requiring a +subscription. You agree that Stirling PDF and/or its licensors (as applicable) retain +all right, title and interest in and to all such modifications. You are not +granted any other rights beyond what is expressly stated herein. Subject to the +foregoing, it is forbidden to copy, merge, publish, distribute, sublicense, +and/or sell the Software. + +This EE License applies only to the part of this Software that is not +distributed as part of MIT License. Any part of this Software +distributed as part of MIT License or is served client-side as an image, font, +cascading stylesheet (CSS), file which produces or is compiled, arranged, +augmented, or combined into client-side JavaScript, in whole or in part, is +copyrighted under the MIT Expat license. The full text of this EE License shall +be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +For all third party components incorporated into the Stirling PDF Software, those +components are licensed under the original license provided by the owner of the +applicable component. diff --git a/proprietary/build.gradle b/proprietary/build.gradle new file mode 100644 index 0000000000..8f548a785f --- /dev/null +++ b/proprietary/build.gradle @@ -0,0 +1,68 @@ +plugins { + id 'java-library' + id 'io.spring.dependency-management' version '1.1.7' +} + +repositories { + mavenCentral() + maven { url = "https://build.shibboleth.net/maven/releases" } +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 +} + +configurations.all { + exclude group: 'commons-logging', module: 'commons-logging' + exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat" +} + +dependencyManagement { + imports { + mavenBom 'org.springframework.boot:spring-boot-dependencies:3.4.5' + } +} + +dependencies { + implementation project(':common') + + implementation 'org.springframework:spring-jdbc:6.2.7' + implementation 'org.springframework:spring-webmvc:6.2.7' + implementation 'org.springframework.boot:spring-boot-starter-jetty' + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' + implementation 'org.springframework.boot:spring-boot-starter-mail' + implementation "org.springframework.security:spring-security-core:$springSecuritySamlVersion" + implementation "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion" + implementation 'org.springframework.session:spring-session-core:3.4.3' + implementation 'io.swagger.core.v3:swagger-core-jakarta:2.2.30' + + implementation 'com.bucket4j:bucket4j_jdk17-core:8.14.0' + + // https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17 + implementation 'org.bouncycastle:bcprov-jdk18on:1.80' + + implementation 'io.github.pixee:java-security-toolkit:1.2.1' + implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.3.RELEASE' + implementation 'io.micrometer:micrometer-registry-prometheus' + implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5' + runtimeOnly 'com.h2database:h2:2.3.232' // Don't upgrade h2database + runtimeOnly 'org.postgresql:postgresql:42.7.5' + constraints { + implementation "org.opensaml:opensaml-core:$openSamlVersion" + implementation "org.opensaml:opensaml-saml-api:$openSamlVersion" + implementation "org.opensaml:opensaml-saml-impl:$openSamlVersion" + } + implementation 'com.coveo:saml-client:5.0.0' + + compileOnly "org.projectlombok:lombok:$lombokVersion" + annotationProcessor "org.projectlombok:lombok:$lombokVersion" + + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testRuntimeOnly 'org.mockito:mockito-inline:5.2.0' +} + +tasks.register('prepareKotlinBuildScriptModel') {} diff --git a/proprietary/gradle/wrapper/gradle-wrapper.properties b/proprietary/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..f7664bccf7 --- /dev/null +++ b/proprietary/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/proprietary/gradlew b/proprietary/gradlew new file mode 100755 index 0000000000..23d15a9367 --- /dev/null +++ b/proprietary/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/proprietary/gradlew.bat b/proprietary/gradlew.bat new file mode 100644 index 0000000000..db3a6ac207 --- /dev/null +++ b/proprietary/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationFailureHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java similarity index 93% rename from src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationFailureHandler.java rename to proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java index f4f103190d..ee726b9fb5 100644 --- a/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationFailureHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java @@ -1,8 +1,11 @@ -package stirling.software.SPDF.config.security; +package stirling.software.proprietary.security; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Optional; - +import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.InternalAuthenticationServiceException; @@ -10,14 +13,9 @@ import org.springframework.security.authentication.LockedException; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; - -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.model.User; +import stirling.software.proprietary.security.model.User; +import stirling.software.proprietary.security.service.LoginAttemptService; +import stirling.software.proprietary.security.service.UserService; @Slf4j public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { diff --git a/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationSuccessHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java similarity index 92% rename from src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationSuccessHandler.java rename to proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java index 0f4fbecb89..b9379ec748 100644 --- a/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationSuccessHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java @@ -1,19 +1,17 @@ -package stirling.software.SPDF.config.security; - -import java.io.IOException; - -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; -import org.springframework.security.web.savedrequest.SavedRequest; +package stirling.software.proprietary.security; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; - +import java.io.IOException; import lombok.extern.slf4j.Slf4j; - +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.security.web.savedrequest.SavedRequest; import stirling.software.common.util.RequestUriUtils; +import stirling.software.proprietary.security.service.LoginAttemptService; +import stirling.software.proprietary.security.service.UserService; @Slf4j public class CustomAuthenticationSuccessHandler diff --git a/src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/CustomLogoutSuccessHandler.java similarity index 95% rename from src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java rename to proprietary/src/main/java/stirling/software/proprietary/security/CustomLogoutSuccessHandler.java index 2f7fb25de6..244e16da03 100644 --- a/src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/CustomLogoutSuccessHandler.java @@ -1,35 +1,30 @@ -package stirling.software.SPDF.config.security; +package stirling.software.proprietary.security; +import com.coveo.saml.SamlClient; +import com.coveo.saml.SamlException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.util.ArrayList; import java.util.List; - +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.Resource; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler; - -import com.coveo.saml.SamlClient; -import com.coveo.saml.SamlException; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.SPDFApplication; -import stirling.software.SPDF.config.security.saml2.CertificateUtils; -import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal; +import stirling.software.common.configuration.AppConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.SAML2; import stirling.software.common.model.oauth2.KeycloakProvider; import stirling.software.common.util.UrlUtils; +import stirling.software.proprietary.security.saml2.CertificateUtils; +import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal; @Slf4j @RequiredArgsConstructor @@ -38,6 +33,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler { public static final String LOGOUT_PATH = "/login?logout=true"; private final ApplicationProperties applicationProperties; + private final AppConfig appConfig; @Override public void onLogoutSuccess( @@ -102,7 +98,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler { // Set service provider keys for the SamlClient samlClient.setSPKeys(certificate, privateKey); - // Redirect to identity provider for logout + // Redirect to identity provider for logout. todo: add relay state samlClient.redirectToIdentityProvider(response, null, nameIdValue); } catch (Exception e) { log.error( @@ -172,11 +168,11 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler { } } - private static SamlClient getSamlClient( + private SamlClient getSamlClient( String registrationId, SAML2 samlConf, List certificates) throws SamlException { String serverUrl = - SPDFApplication.getStaticBaseUrl() + ":" + SPDFApplication.getStaticPort(); + appConfig.getBaseUrl() + ":" + appConfig.getServerPort(); String relyingPartyIdentifier = serverUrl + "/saml2/service-provider-metadata/" + registrationId; diff --git a/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java b/proprietary/src/main/java/stirling/software/proprietary/security/InitialSecuritySetup.java similarity index 91% rename from src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java rename to proprietary/src/main/java/stirling/software/proprietary/security/InitialSecuritySetup.java index 3b1a8d5fb0..1353f21518 100644 --- a/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/InitialSecuritySetup.java @@ -1,19 +1,16 @@ -package stirling.software.SPDF.config.security; - -import java.sql.SQLException; -import java.util.UUID; - -import org.springframework.stereotype.Component; +package stirling.software.proprietary.security; import jakarta.annotation.PostConstruct; - +import java.sql.SQLException; +import java.util.UUID; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.config.interfaces.DatabaseInterface; -import stirling.software.SPDF.model.Role; +import org.springframework.stereotype.Component; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.exception.UnsupportedProviderException; +import stirling.software.common.model.enumeration.Role; +import stirling.software.proprietary.security.service.DatabaseServiceInterface; +import stirling.software.proprietary.security.service.UserService; @Slf4j @Component @@ -24,7 +21,7 @@ public class InitialSecuritySetup { private final ApplicationProperties applicationProperties; - private final DatabaseInterface databaseService; + private final DatabaseServiceInterface databaseService; @PostConstruct public void init() { diff --git a/src/main/java/stirling/software/SPDF/config/security/RateLimitResetScheduler.java b/proprietary/src/main/java/stirling/software/proprietary/security/RateLimitResetScheduler.java similarity index 78% rename from src/main/java/stirling/software/SPDF/config/security/RateLimitResetScheduler.java rename to proprietary/src/main/java/stirling/software/proprietary/security/RateLimitResetScheduler.java index 5751ec871b..4faeb90412 100644 --- a/src/main/java/stirling/software/SPDF/config/security/RateLimitResetScheduler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/RateLimitResetScheduler.java @@ -1,9 +1,9 @@ -package stirling.software.SPDF.config.security; - -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; +package stirling.software.proprietary.security; import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import stirling.software.proprietary.security.filter.IPRateLimitingFilter; @Component @RequiredArgsConstructor diff --git a/src/main/java/stirling/software/SPDF/config/security/database/DatabaseConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java similarity index 86% rename from src/main/java/stirling/software/SPDF/config/security/database/DatabaseConfig.java rename to proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java index 73ccbe3b73..8d686e4d77 100644 --- a/src/main/java/stirling/software/SPDF/config/security/database/DatabaseConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java @@ -1,34 +1,30 @@ -package stirling.software.SPDF.config.security.database; +package stirling.software.proprietary.security.configuration; import javax.sql.DataSource; - -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.jdbc.DataSourceBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Lazy; - import lombok.Getter; import lombok.extern.slf4j.Slf4j; - +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.boot.jdbc.DatabaseDriver; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import stirling.software.common.configuration.InstallationPathConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.exception.UnsupportedProviderException; @Slf4j @Getter -@Lazy @Configuration -@ConditionalOnProperty(name = "premium.proFeatures.database", havingValue = "true") +@EnableJpaRepositories(basePackages = "stirling.software.proprietary.security.database.repository") +@EntityScan({"stirling.software.proprietary.security.model"}) public class DatabaseConfig { public final String DATASOURCE_DEFAULT_URL; public static final String DATASOURCE_URL_TEMPLATE = "jdbc:%s://%s:%4d/%s"; - public static final String DEFAULT_DRIVER = "org.h2.Driver"; public static final String DEFAULT_USERNAME = "sa"; - public static final String POSTGRES_DRIVER = "org.postgresql.Driver"; private final ApplicationProperties.Datasource datasource; private final boolean runningProOrHigher; @@ -70,7 +66,7 @@ public class DatabaseConfig { if (!datasource.getCustomDatabaseUrl().isBlank()) { if (datasource.getCustomDatabaseUrl().contains("postgresql")) { - dataSourceBuilder.driverClassName(POSTGRES_DRIVER); + dataSourceBuilder.driverClassName(DatabaseDriver.POSTGRESQL.getDriverClassName()); } dataSourceBuilder.url(datasource.getCustomDatabaseUrl()); @@ -92,8 +88,9 @@ public class DatabaseConfig { private DataSource useDefaultDataSource(DataSourceBuilder dataSourceBuilder) { log.info("Using default H2 database"); - dataSourceBuilder.url(DATASOURCE_DEFAULT_URL); - dataSourceBuilder.username(DEFAULT_USERNAME); + dataSourceBuilder.url(DATASOURCE_DEFAULT_URL) + .driverClassName(DatabaseDriver.H2.getDriverClassName()) + .username(DEFAULT_USERNAME); return dataSourceBuilder.build(); } @@ -127,11 +124,11 @@ public class DatabaseConfig { switch (driver) { case H2 -> { log.debug("H2 driver selected"); - return DEFAULT_DRIVER; + return DatabaseDriver.H2.getDriverClassName(); } case POSTGRESQL -> { log.debug("Postgres driver selected"); - return POSTGRES_DRIVER; + return DatabaseDriver.POSTGRESQL.getDriverClassName(); } default -> { log.warn("{} driver selected", driverName); diff --git a/src/main/java/stirling/software/SPDF/config/security/mail/MailConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java similarity index 96% rename from src/main/java/stirling/software/SPDF/config/security/mail/MailConfig.java rename to proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java index 0181271d35..82d794d6ea 100644 --- a/src/main/java/stirling/software/SPDF/config/security/mail/MailConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.config.security.mail; +package stirling.software.proprietary.security.configuration; import java.util.Properties; @@ -10,7 +10,6 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; - import stirling.software.common.model.ApplicationProperties; /** diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java new file mode 100644 index 0000000000..c31d42dde4 --- /dev/null +++ b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java @@ -0,0 +1,320 @@ +package stirling.software.proprietary.security.configuration; + +import java.util.Optional; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; +import org.springframework.context.annotation.Lazy; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider; +import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; +import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; +import org.springframework.security.web.csrf.CookieCsrfTokenRepository; +import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; +import org.springframework.security.web.savedrequest.NullRequestCache; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import stirling.software.common.configuration.AppConfig; +import stirling.software.common.model.ApplicationProperties; +import stirling.software.proprietary.security.CustomAuthenticationFailureHandler; +import stirling.software.proprietary.security.CustomAuthenticationSuccessHandler; +import stirling.software.proprietary.security.CustomLogoutSuccessHandler; +import stirling.software.proprietary.security.database.repository.JPATokenRepositoryImpl; +import stirling.software.proprietary.security.database.repository.PersistentLoginRepository; +import stirling.software.proprietary.security.filter.FirstLoginFilter; +import stirling.software.proprietary.security.filter.IPRateLimitingFilter; +import stirling.software.proprietary.security.filter.UserAuthenticationFilter; +import stirling.software.proprietary.security.model.User; +import stirling.software.proprietary.security.oauth2.CustomOAuth2AuthenticationFailureHandler; +import stirling.software.proprietary.security.oauth2.CustomOAuth2AuthenticationSuccessHandler; +import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticationFailureHandler; +import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticationSuccessHandler; +import stirling.software.proprietary.security.saml2.CustomSaml2ResponseAuthenticationConverter; +import stirling.software.proprietary.security.service.CustomOAuth2UserService; +import stirling.software.proprietary.security.service.CustomUserDetailsService; +import stirling.software.proprietary.security.service.LoginAttemptService; +import stirling.software.proprietary.security.service.UserService; +import stirling.software.proprietary.security.session.SessionPersistentRegistry; + +@Slf4j +@Configuration +@EnableWebSecurity +@EnableMethodSecurity +@DependsOn("runningProOrHigher") +public class SecurityConfiguration { + + private final CustomUserDetailsService userDetailsService; + private final UserService userService; + private final boolean loginEnabledValue; + private final boolean runningProOrHigher; + + private final ApplicationProperties applicationProperties; + private final AppConfig appConfig; + private final UserAuthenticationFilter userAuthenticationFilter; + private final LoginAttemptService loginAttemptService; + private final FirstLoginFilter firstLoginFilter; + private final SessionPersistentRegistry sessionRegistry; + private final PersistentLoginRepository persistentLoginRepository; + private final GrantedAuthoritiesMapper oAuth2userAuthoritiesMapper; + private final RelyingPartyRegistrationRepository saml2RelyingPartyRegistrations; + private final OpenSaml4AuthenticationRequestResolver saml2AuthenticationRequestResolver; + + public SecurityConfiguration( + PersistentLoginRepository persistentLoginRepository, + CustomUserDetailsService userDetailsService, + @Lazy UserService userService, + @Qualifier("loginEnabled") boolean loginEnabledValue, + @Qualifier("runningProOrHigher") boolean runningProOrHigher, + AppConfig appConfig, + ApplicationProperties applicationProperties, + UserAuthenticationFilter userAuthenticationFilter, + LoginAttemptService loginAttemptService, + FirstLoginFilter firstLoginFilter, + SessionPersistentRegistry sessionRegistry, + @Autowired(required = false) GrantedAuthoritiesMapper oAuth2userAuthoritiesMapper, + @Autowired(required = false) + RelyingPartyRegistrationRepository saml2RelyingPartyRegistrations, + @Autowired(required = false) + OpenSaml4AuthenticationRequestResolver saml2AuthenticationRequestResolver) { + this.userDetailsService = userDetailsService; + this.userService = userService; + this.loginEnabledValue = loginEnabledValue; + this.runningProOrHigher = runningProOrHigher; + this.appConfig = appConfig; + this.applicationProperties = applicationProperties; + this.userAuthenticationFilter = userAuthenticationFilter; + this.loginAttemptService = loginAttemptService; + this.firstLoginFilter = firstLoginFilter; + this.sessionRegistry = sessionRegistry; + this.persistentLoginRepository = persistentLoginRepository; + this.oAuth2userAuthoritiesMapper = oAuth2userAuthoritiesMapper; + this.saml2RelyingPartyRegistrations = saml2RelyingPartyRegistrations; + this.saml2AuthenticationRequestResolver = saml2AuthenticationRequestResolver; + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + if (applicationProperties.getSecurity().getCsrfDisabled() || !loginEnabledValue) { + http.csrf(csrf -> csrf.disable()); + } + + if (loginEnabledValue) { + http.addFilterBefore( + userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); + if (!applicationProperties.getSecurity().getCsrfDisabled()) { + CookieCsrfTokenRepository cookieRepo = + CookieCsrfTokenRepository.withHttpOnlyFalse(); + CsrfTokenRequestAttributeHandler requestHandler = + new CsrfTokenRequestAttributeHandler(); + requestHandler.setCsrfRequestAttributeName(null); + http.csrf( + csrf -> + csrf.ignoringRequestMatchers( + request -> { + String apiKey = request.getHeader("X-API-KEY"); + // If there's no API key, don't ignore CSRF + // (return false) + if (apiKey == null || apiKey.trim().isEmpty()) { + return false; + } + // Validate API key using existing UserService + try { + Optional user = + userService.getUserByApiKey(apiKey); + // If API key is valid, ignore CSRF (return + // true) + // If API key is invalid, don't ignore CSRF + // (return false) + return user.isPresent(); + } catch (Exception e) { + // If there's any error validating the API + // key, don't ignore CSRF + return false; + } + }) + .csrfTokenRepository(cookieRepo) + .csrfTokenRequestHandler(requestHandler)); + } + http.addFilterBefore(rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class); + http.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class); + http.sessionManagement( + sessionManagement -> + sessionManagement + .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) + .maximumSessions(10) + .maxSessionsPreventsLogin(false) + .sessionRegistry(sessionRegistry) + .expiredUrl("/login?logout=true")); + http.authenticationProvider(daoAuthenticationProvider()); + http.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache())); + http.logout( + logout -> + logout.logoutRequestMatcher(new AntPathRequestMatcher("/logout")) + .logoutSuccessHandler( + new CustomLogoutSuccessHandler(applicationProperties, appConfig)) + .clearAuthentication(true) + .invalidateHttpSession(true) + .deleteCookies("JSESSIONID", "remember-me")); + http.rememberMe( + rememberMeConfigurer -> // Use the configurator directly + rememberMeConfigurer + .tokenRepository(persistentTokenRepository()) + .tokenValiditySeconds( // 14 days + 14 * 24 * 60 * 60) + .userDetailsService( // Your existing UserDetailsService + userDetailsService) + .useSecureCookie( // Enable secure cookie + true) + .rememberMeParameter( // Form parameter name + "remember-me") + .rememberMeCookieName( // Cookie name + "remember-me") + .alwaysRemember(false)); + http.authorizeHttpRequests( + authz -> + authz.requestMatchers( + req -> { + String uri = req.getRequestURI(); + String contextPath = req.getContextPath(); + // Remove the context path from the URI + String trimmedUri = + uri.startsWith(contextPath) + ? uri.substring( + contextPath.length()) + : uri; + return trimmedUri.startsWith("/login") + || trimmedUri.startsWith("/oauth") + || trimmedUri.startsWith("/saml2") + || trimmedUri.endsWith(".svg") + || trimmedUri.startsWith("/register") + || trimmedUri.startsWith("/error") + || trimmedUri.startsWith("/images/") + || trimmedUri.startsWith("/public/") + || trimmedUri.startsWith("/css/") + || trimmedUri.startsWith("/fonts/") + || trimmedUri.startsWith("/js/") + || trimmedUri.startsWith( + "/api/v1/info/status"); + }) + .permitAll() + .anyRequest() + .authenticated()); + // Handle User/Password Logins + if (applicationProperties.getSecurity().isUserPass()) { + http.formLogin( + formLogin -> + formLogin + .loginPage("/login") + .successHandler( + new CustomAuthenticationSuccessHandler( + loginAttemptService, userService)) + .failureHandler( + new CustomAuthenticationFailureHandler( + loginAttemptService, userService)) + .defaultSuccessUrl("/") + .permitAll()); + } + // Handle OAUTH2 Logins + if (applicationProperties.getSecurity().isOauth2Active()) { + http.oauth2Login( + oauth2 -> + oauth2.loginPage("/oauth2") + /* + This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database. + If user exists, login proceeds as usual. If user does not exist, then it is auto-created but only if 'OAUTH2AutoCreateUser' + is set as true, else login fails with an error message advising the same. + */ + .successHandler( + new CustomOAuth2AuthenticationSuccessHandler( + loginAttemptService, + applicationProperties, + userService)) + .failureHandler( + new CustomOAuth2AuthenticationFailureHandler()) + . // Add existing Authorities from the database + userInfoEndpoint( + userInfoEndpoint -> + userInfoEndpoint + .oidcUserService( + new CustomOAuth2UserService( + applicationProperties, + userService, + loginAttemptService)) + .userAuthoritiesMapper( + oAuth2userAuthoritiesMapper)) + .permitAll()); + } + // Handle SAML + if (applicationProperties.getSecurity().isSaml2Active() && runningProOrHigher) { + // Configure the authentication provider + OpenSaml4AuthenticationProvider authenticationProvider = + new OpenSaml4AuthenticationProvider(); + authenticationProvider.setResponseAuthenticationConverter( + new CustomSaml2ResponseAuthenticationConverter(userService)); + http.authenticationProvider(authenticationProvider) + .saml2Login( + saml2 -> { + try { + saml2.loginPage("/saml2") + .relyingPartyRegistrationRepository( + saml2RelyingPartyRegistrations) + .authenticationManager( + new ProviderManager(authenticationProvider)) + .successHandler( + new CustomSaml2AuthenticationSuccessHandler( + loginAttemptService, + applicationProperties, + userService)) + .failureHandler( + new CustomSaml2AuthenticationFailureHandler()) + .authenticationRequestResolver( + saml2AuthenticationRequestResolver); + } catch (Exception e) { + log.error("Error configuring SAML 2 login", e); + throw new RuntimeException(e); + } + }); + } + } else { + log.debug("Login is not enabled."); + http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll()); + } + return http.build(); + } + + public DaoAuthenticationProvider daoAuthenticationProvider() { + DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService); + provider.setPasswordEncoder(passwordEncoder()); + return provider; + } + + @Bean + public IPRateLimitingFilter rateLimitingFilter() { + // Example limit TODO add config level + int maxRequestsPerIp = 1000000; + return new IPRateLimitingFilter(maxRequestsPerIp, maxRequestsPerIp); + } + + @Bean + public PersistentTokenRepository persistentTokenRepository() { + return new JPATokenRepositoryImpl(persistentLoginRepository); + } +} diff --git a/src/main/java/stirling/software/SPDF/controller/api/DatabaseController.java b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java similarity index 97% rename from src/main/java/stirling/software/SPDF/controller/api/DatabaseController.java rename to proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java index 8e3484f23b..bbc84821f2 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/DatabaseController.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.controller.api; +package stirling.software.proprietary.security.controller.api; import java.io.IOException; import java.io.InputStream; @@ -26,8 +26,8 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.config.security.database.DatabaseService; +import stirling.software.proprietary.security.database.H2SQLCondition; +import stirling.software.proprietary.security.service.DatabaseService; @Slf4j @Controller diff --git a/src/main/java/stirling/software/SPDF/controller/api/EmailController.java b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java similarity index 93% rename from src/main/java/stirling/software/SPDF/controller/api/EmailController.java rename to proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java index dc1c9dff4a..7fb7675737 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/EmailController.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.controller.api; +package stirling.software.proprietary.security.controller.api; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.http.HttpStatus; @@ -18,8 +18,8 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import stirling.software.SPDF.config.security.mail.EmailService; -import stirling.software.SPDF.model.api.Email; +import stirling.software.proprietary.security.model.api.Email; +import stirling.software.proprietary.security.service.EmailService; /** * Controller for handling email-related API requests. This controller exposes an endpoint for diff --git a/src/main/java/stirling/software/SPDF/controller/api/UserController.java b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java similarity index 97% rename from src/main/java/stirling/software/SPDF/controller/api/UserController.java rename to proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java index 1f2ccd1fda..dec5905bad 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/UserController.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.controller.api; +package stirling.software.proprietary.security.controller.api; import java.io.IOException; import java.security.Principal; @@ -29,15 +29,15 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import stirling.software.SPDF.config.security.UserService; -import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal; -import stirling.software.SPDF.config.security.session.SessionPersistentRegistry; -import stirling.software.SPDF.model.AuthenticationType; -import stirling.software.SPDF.model.Role; -import stirling.software.SPDF.model.User; -import stirling.software.SPDF.model.api.user.UsernameAndPass; +import stirling.software.proprietary.security.model.AuthenticationType; +import stirling.software.common.model.enumeration.Role; +import stirling.software.proprietary.security.model.User; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.exception.UnsupportedProviderException; +import stirling.software.proprietary.security.model.api.user.UsernameAndPass; +import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal; +import stirling.software.proprietary.security.service.UserService; +import stirling.software.proprietary.security.session.SessionPersistentRegistry; @Controller @Tag(name = "User", description = "User APIs") diff --git a/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java b/proprietary/src/main/java/stirling/software/proprietary/security/controller/web/AccountWebController.java similarity index 97% rename from src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java rename to proprietary/src/main/java/stirling/software/proprietary/security/controller/web/AccountWebController.java index 1962dffb85..311f81a4fa 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/controller/web/AccountWebController.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.controller.web; +package stirling.software.proprietary.security.controller.web; import static stirling.software.common.util.ProviderUtils.validateProvider; @@ -29,13 +29,7 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; -import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal; -import stirling.software.SPDF.config.security.session.SessionPersistentRegistry; -import stirling.software.SPDF.model.Authority; -import stirling.software.SPDF.model.Role; -import stirling.software.SPDF.model.SessionEntity; -import stirling.software.SPDF.model.User; -import stirling.software.SPDF.repository.UserRepository; +import stirling.software.common.model.enumeration.Role; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; @@ -44,6 +38,12 @@ import stirling.software.common.model.ApplicationProperties.Security.SAML2; import stirling.software.common.model.oauth2.GitHubProvider; import stirling.software.common.model.oauth2.GoogleProvider; import stirling.software.common.model.oauth2.KeycloakProvider; +import stirling.software.proprietary.security.database.repository.UserRepository; +import stirling.software.proprietary.security.model.Authority; +import stirling.software.proprietary.security.model.SessionEntity; +import stirling.software.proprietary.security.model.User; +import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal; +import stirling.software.proprietary.security.session.SessionPersistentRegistry; @Controller @Slf4j diff --git a/src/main/java/stirling/software/SPDF/controller/web/DatabaseWebController.java b/proprietary/src/main/java/stirling/software/proprietary/security/controller/web/DatabaseWebController.java similarity index 92% rename from src/main/java/stirling/software/SPDF/controller/web/DatabaseWebController.java rename to proprietary/src/main/java/stirling/software/proprietary/security/controller/web/DatabaseWebController.java index 1291895f3a..940c0c13f4 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/DatabaseWebController.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/controller/web/DatabaseWebController.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.controller.web; +package stirling.software.proprietary.security.controller.web; import java.util.List; @@ -14,8 +14,8 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import stirling.software.SPDF.config.security.database.DatabaseService; import stirling.software.common.model.FileInfo; +import stirling.software.proprietary.security.service.DatabaseService; @Controller @Tag(name = "Database Management", description = "Database management and security APIs") diff --git a/src/main/java/stirling/software/SPDF/controller/api/H2SQLCondition.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/H2SQLCondition.java similarity index 77% rename from src/main/java/stirling/software/SPDF/controller/api/H2SQLCondition.java rename to proprietary/src/main/java/stirling/software/proprietary/security/database/H2SQLCondition.java index ebdb1f0583..4e259e49b3 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/H2SQLCondition.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/H2SQLCondition.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.controller.api; +package stirling.software.proprietary.security.database; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; @@ -12,8 +12,12 @@ public class H2SQLCondition implements Condition { Boolean.parseBoolean( context.getEnvironment() .getProperty("system.datasource.enableCustomDatabase")); + + if (!enableCustomDatabase) { + return false; + } + String dataSourceType = context.getEnvironment().getProperty("system.datasource.type"); - return !enableCustomDatabase - || (enableCustomDatabase && "h2".equalsIgnoreCase(dataSourceType)); + return "h2".equalsIgnoreCase(dataSourceType); } } diff --git a/src/main/java/stirling/software/SPDF/config/security/database/ScheduledTasks.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/ScheduledTasks.java similarity index 71% rename from src/main/java/stirling/software/SPDF/config/security/database/ScheduledTasks.java rename to proprietary/src/main/java/stirling/software/proprietary/security/database/ScheduledTasks.java index 73a33972ab..835dc1917f 100644 --- a/src/main/java/stirling/software/SPDF/config/security/database/ScheduledTasks.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/ScheduledTasks.java @@ -1,23 +1,19 @@ -package stirling.software.SPDF.config.security.database; +package stirling.software.proprietary.security.database; import java.sql.SQLException; - +import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Conditional; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; - -import lombok.RequiredArgsConstructor; - -import stirling.software.SPDF.config.interfaces.DatabaseInterface; -import stirling.software.SPDF.controller.api.H2SQLCondition; import stirling.software.common.model.exception.UnsupportedProviderException; +import stirling.software.proprietary.security.service.DatabaseServiceInterface; @Component @Conditional(H2SQLCondition.class) @RequiredArgsConstructor public class ScheduledTasks { - private final DatabaseInterface databaseService; + private final DatabaseServiceInterface databaseService; @Scheduled(cron = "0 0 0 * * ?") public void performBackup() throws SQLException, UnsupportedProviderException { diff --git a/src/main/java/stirling/software/SPDF/repository/AuthorityRepository.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/AuthorityRepository.java similarity index 74% rename from src/main/java/stirling/software/SPDF/repository/AuthorityRepository.java rename to proprietary/src/main/java/stirling/software/proprietary/security/database/repository/AuthorityRepository.java index 01f23dd91a..a7773d8590 100644 --- a/src/main/java/stirling/software/SPDF/repository/AuthorityRepository.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/AuthorityRepository.java @@ -1,11 +1,10 @@ -package stirling.software.SPDF.repository; +package stirling.software.proprietary.security.database.repository; import java.util.Set; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; - -import stirling.software.SPDF.model.Authority; +import stirling.software.proprietary.security.model.Authority; @Repository public interface AuthorityRepository extends JpaRepository { diff --git a/src/main/java/stirling/software/SPDF/repository/JPATokenRepositoryImpl.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/JPATokenRepositoryImpl.java similarity index 93% rename from src/main/java/stirling/software/SPDF/repository/JPATokenRepositoryImpl.java rename to proprietary/src/main/java/stirling/software/proprietary/security/database/repository/JPATokenRepositoryImpl.java index 98becfd48a..b98a8094f4 100644 --- a/src/main/java/stirling/software/SPDF/repository/JPATokenRepositoryImpl.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/JPATokenRepositoryImpl.java @@ -1,12 +1,11 @@ -package stirling.software.SPDF.repository; +package stirling.software.proprietary.security.database.repository; import java.util.Date; import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken; import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; import org.springframework.transaction.annotation.Transactional; - -import stirling.software.SPDF.model.PersistentLogin; +import stirling.software.proprietary.security.model.PersistentLogin; public class JPATokenRepositoryImpl implements PersistentTokenRepository { diff --git a/src/main/java/stirling/software/SPDF/repository/PersistentLoginRepository.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/PersistentLoginRepository.java similarity index 65% rename from src/main/java/stirling/software/SPDF/repository/PersistentLoginRepository.java rename to proprietary/src/main/java/stirling/software/proprietary/security/database/repository/PersistentLoginRepository.java index e8ef19ce2f..a9ddf8a377 100644 --- a/src/main/java/stirling/software/SPDF/repository/PersistentLoginRepository.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/PersistentLoginRepository.java @@ -1,9 +1,8 @@ -package stirling.software.SPDF.repository; +package stirling.software.proprietary.security.database.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; - -import stirling.software.SPDF.model.PersistentLogin; +import stirling.software.proprietary.security.model.PersistentLogin; @Repository public interface PersistentLoginRepository extends JpaRepository { diff --git a/src/main/java/stirling/software/SPDF/config/security/session/SessionRepository.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/SessionRepository.java similarity index 79% rename from src/main/java/stirling/software/SPDF/config/security/session/SessionRepository.java rename to proprietary/src/main/java/stirling/software/proprietary/security/database/repository/SessionRepository.java index d4f2f4bcce..b7a7d7a844 100644 --- a/src/main/java/stirling/software/SPDF/config/security/session/SessionRepository.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/SessionRepository.java @@ -1,21 +1,16 @@ -package stirling.software.SPDF.config.security.session; +package stirling.software.proprietary.security.database.repository; +import jakarta.transaction.Transactional; import java.util.Date; import java.util.List; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; - -import jakarta.transaction.Transactional; - -import stirling.software.SPDF.model.SessionEntity; +import stirling.software.proprietary.security.model.SessionEntity; @Repository -@ConditionalOnProperty(name = "premium.enabled", havingValue = "true") public interface SessionRepository extends JpaRepository { List findByPrincipalName(String principalName); diff --git a/src/main/java/stirling/software/SPDF/repository/UserRepository.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/UserRepository.java similarity index 86% rename from src/main/java/stirling/software/SPDF/repository/UserRepository.java rename to proprietary/src/main/java/stirling/software/proprietary/security/database/repository/UserRepository.java index e1f53efb83..dcf84ee19b 100644 --- a/src/main/java/stirling/software/SPDF/repository/UserRepository.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/UserRepository.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.repository; +package stirling.software.proprietary.security.database.repository; import java.util.List; import java.util.Optional; @@ -7,8 +7,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; - -import stirling.software.SPDF.model.User; +import stirling.software.proprietary.security.model.User; @Repository public interface UserRepository extends JpaRepository { diff --git a/src/main/java/stirling/software/SPDF/config/EnterpriseEndpointFilter.java b/proprietary/src/main/java/stirling/software/proprietary/security/filter/EnterpriseEndpointFilter.java similarity index 95% rename from src/main/java/stirling/software/SPDF/config/EnterpriseEndpointFilter.java rename to proprietary/src/main/java/stirling/software/proprietary/security/filter/EnterpriseEndpointFilter.java index 040e0e070f..5ee61f8ffc 100644 --- a/src/main/java/stirling/software/SPDF/config/EnterpriseEndpointFilter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/filter/EnterpriseEndpointFilter.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.config; +package stirling.software.proprietary.security.filter; import java.io.IOException; diff --git a/src/main/java/stirling/software/SPDF/config/security/FirstLoginFilter.java b/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java similarity index 94% rename from src/main/java/stirling/software/SPDF/config/security/FirstLoginFilter.java rename to proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java index edada16dd4..a96e6e7691 100644 --- a/src/main/java/stirling/software/SPDF/config/security/FirstLoginFilter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java @@ -1,26 +1,23 @@ -package stirling.software.SPDF.config.security; - -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Optional; - -import org.springframework.context.annotation.Lazy; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; +package stirling.software.proprietary.security.filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; - +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Optional; import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.model.User; +import org.springframework.context.annotation.Lazy; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; import stirling.software.common.util.RequestUriUtils; +import stirling.software.proprietary.security.model.User; +import stirling.software.proprietary.security.service.UserService; @Slf4j @Component diff --git a/src/main/java/stirling/software/SPDF/config/security/IPRateLimitingFilter.java b/proprietary/src/main/java/stirling/software/proprietary/security/filter/IPRateLimitingFilter.java similarity index 90% rename from src/main/java/stirling/software/SPDF/config/security/IPRateLimitingFilter.java rename to proprietary/src/main/java/stirling/software/proprietary/security/filter/IPRateLimitingFilter.java index 5d2c673505..ebc0f949ea 100644 --- a/src/main/java/stirling/software/SPDF/config/security/IPRateLimitingFilter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/filter/IPRateLimitingFilter.java @@ -1,14 +1,15 @@ -package stirling.software.SPDF.config.security; +package stirling.software.proprietary.security.filter; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; - -import jakarta.servlet.*; -import jakarta.servlet.http.HttpServletRequest; - import lombok.RequiredArgsConstructor; - import stirling.software.common.util.RequestUriUtils; @RequiredArgsConstructor diff --git a/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java b/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java similarity index 96% rename from src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java rename to proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java index 5208e8f252..de97ec7858 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java @@ -1,11 +1,14 @@ -package stirling.software.SPDF.config.security; +package stirling.software.proprietary.security.filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; import java.util.Optional; - +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; @@ -17,25 +20,17 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal; -import stirling.software.SPDF.config.security.session.SessionPersistentRegistry; -import stirling.software.SPDF.model.ApiKeyAuthenticationToken; -import stirling.software.SPDF.model.User; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.SAML2; +import stirling.software.proprietary.security.model.ApiKeyAuthenticationToken; +import stirling.software.proprietary.security.model.User; +import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal; +import stirling.software.proprietary.security.service.UserService; +import stirling.software.proprietary.security.session.SessionPersistentRegistry; @Slf4j @Component -@ConditionalOnProperty(name = "premium.enabled", havingValue = "true") public class UserAuthenticationFilter extends OncePerRequestFilter { private final ApplicationProperties.Security securityProp; diff --git a/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java b/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java similarity index 98% rename from src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java rename to proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java index 5ca7df214a..31db979b09 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java @@ -1,10 +1,17 @@ -package stirling.software.SPDF.config.security; +package stirling.software.proprietary.security.filter; +import io.github.bucket4j.Bandwidth; +import io.github.bucket4j.Bucket; +import io.github.bucket4j.ConsumptionProbe; +import io.github.pixee.security.Newlines; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.time.Duration; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; - import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; @@ -13,18 +20,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; - -import io.github.bucket4j.Bandwidth; -import io.github.bucket4j.Bucket; -import io.github.bucket4j.ConsumptionProbe; -import io.github.pixee.security.Newlines; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import stirling.software.SPDF.model.Role; +import stirling.software.common.model.enumeration.Role; @Component public class UserBasedRateLimitingFilter extends OncePerRequestFilter { diff --git a/src/main/java/stirling/software/SPDF/model/ApiKeyAuthenticationToken.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/ApiKeyAuthenticationToken.java similarity index 96% rename from src/main/java/stirling/software/SPDF/model/ApiKeyAuthenticationToken.java rename to proprietary/src/main/java/stirling/software/proprietary/security/model/ApiKeyAuthenticationToken.java index f19fa1e95a..1db14aaafe 100644 --- a/src/main/java/stirling/software/SPDF/model/ApiKeyAuthenticationToken.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/ApiKeyAuthenticationToken.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.model; +package stirling.software.proprietary.security.model; import java.util.Collection; diff --git a/src/main/java/stirling/software/SPDF/model/AttemptCounter.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/AttemptCounter.java similarity index 93% rename from src/main/java/stirling/software/SPDF/model/AttemptCounter.java rename to proprietary/src/main/java/stirling/software/proprietary/security/model/AttemptCounter.java index 8267bddb7f..18ca598aee 100644 --- a/src/main/java/stirling/software/SPDF/model/AttemptCounter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/AttemptCounter.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.model; +package stirling.software.proprietary.security.model; public class AttemptCounter { private int attemptCount; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/model/AuthenticationType.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/AuthenticationType.java new file mode 100644 index 0000000000..ca8140bcab --- /dev/null +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/AuthenticationType.java @@ -0,0 +1,6 @@ +package stirling.software.proprietary.security.model; + +public enum AuthenticationType { + WEB, + SSO +} diff --git a/src/main/java/stirling/software/SPDF/model/Authority.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/Authority.java similarity index 94% rename from src/main/java/stirling/software/SPDF/model/Authority.java rename to proprietary/src/main/java/stirling/software/proprietary/security/model/Authority.java index 4a0ed72558..382d3a71ea 100644 --- a/src/main/java/stirling/software/SPDF/model/Authority.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/Authority.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.model; +package stirling.software.proprietary.security.model; import java.io.Serializable; diff --git a/src/main/java/stirling/software/SPDF/model/PersistentLogin.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/PersistentLogin.java similarity index 91% rename from src/main/java/stirling/software/SPDF/model/PersistentLogin.java rename to proprietary/src/main/java/stirling/software/proprietary/security/model/PersistentLogin.java index c0990199cb..ef096f7fb2 100644 --- a/src/main/java/stirling/software/SPDF/model/PersistentLogin.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/PersistentLogin.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.model; +package stirling.software.proprietary.security.model; import java.util.Date; diff --git a/src/main/java/stirling/software/SPDF/model/SessionEntity.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/SessionEntity.java similarity index 88% rename from src/main/java/stirling/software/SPDF/model/SessionEntity.java rename to proprietary/src/main/java/stirling/software/proprietary/security/model/SessionEntity.java index bba7b33dc3..db94eae6fd 100644 --- a/src/main/java/stirling/software/SPDF/model/SessionEntity.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/SessionEntity.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.model; +package stirling.software.proprietary.security.model; import java.io.Serializable; import java.util.Date; diff --git a/src/main/java/stirling/software/SPDF/model/User.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java similarity index 95% rename from src/main/java/stirling/software/SPDF/model/User.java rename to proprietary/src/main/java/stirling/software/proprietary/security/model/User.java index 1eb9da991e..6dc32a85d3 100644 --- a/src/main/java/stirling/software/SPDF/model/User.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.model; +package stirling.software.proprietary.security.model; import java.io.Serializable; import java.util.HashMap; @@ -14,6 +14,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; +import stirling.software.common.model.enumeration.Role; @Entity @Table(name = "users") diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java new file mode 100644 index 0000000000..8fe3cebe6f --- /dev/null +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java @@ -0,0 +1,39 @@ +package stirling.software.proprietary.security.model.api; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import io.swagger.v3.oas.annotations.media.Schema; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import stirling.software.common.model.api.GeneralFile; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@ConditionalOnProperty(value = "mail.enabled", havingValue = "true", matchIfMissing = false) +public class Email extends GeneralFile { + + @Schema( + description = "The recipient's email address", + requiredMode = Schema.RequiredMode.REQUIRED, + format = "email") + private String to; + + @Schema( + description = "The subject of the email", + defaultValue = "Stirling Software PDF Notification", + requiredMode = Schema.RequiredMode.NOT_REQUIRED) + private String subject; + + @Schema( + description = "The body of the email", + requiredMode = Schema.RequiredMode.NOT_REQUIRED, + defaultValue = + "This message was automatically generated by Stirling-PDF, an innovative" + + " solution from Stirling Software. For more information, visit our website.

Please do" + + " not reply directly to this email.") + private String body; +} diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/UpdateUserDetails.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/UpdateUserDetails.java new file mode 100644 index 0000000000..3f630f61df --- /dev/null +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/UpdateUserDetails.java @@ -0,0 +1,17 @@ +package stirling.software.proprietary.security.model.api.user; + +import io.swagger.v3.oas.annotations.media.Schema; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +public class UpdateUserDetails extends UpdateUserUsername { + + @Schema( + description = "new password for user", + format = "password", + requiredMode = Schema.RequiredMode.REQUIRED) + private String newPassword; +} diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/UpdateUserUsername.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/UpdateUserUsername.java new file mode 100644 index 0000000000..d158e6b32f --- /dev/null +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/UpdateUserUsername.java @@ -0,0 +1,14 @@ +package stirling.software.proprietary.security.model.api.user; + +import io.swagger.v3.oas.annotations.media.Schema; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +public class UpdateUserUsername extends UsernameAndPass { + + @Schema(description = "new username for user") + private String newUsername; +} diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/Username.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/Username.java new file mode 100644 index 0000000000..c5fd081f62 --- /dev/null +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/Username.java @@ -0,0 +1,14 @@ +package stirling.software.proprietary.security.model.api.user; + +import io.swagger.v3.oas.annotations.media.Schema; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode +public class Username { + + @Schema(description = "username of user", requiredMode = Schema.RequiredMode.REQUIRED) + private String username; +} diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/UsernameAndPass.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/UsernameAndPass.java new file mode 100644 index 0000000000..0a21cba875 --- /dev/null +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/user/UsernameAndPass.java @@ -0,0 +1,14 @@ +package stirling.software.proprietary.security.model.api.user; + +import io.swagger.v3.oas.annotations.media.Schema; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +public class UsernameAndPass extends Username { + + @Schema(description = "password of user", format = "password") + private String password; +} diff --git a/src/main/java/stirling/software/SPDF/model/exception/BackupNotFoundException.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/exception/BackupNotFoundException.java similarity index 70% rename from src/main/java/stirling/software/SPDF/model/exception/BackupNotFoundException.java rename to proprietary/src/main/java/stirling/software/proprietary/security/model/exception/BackupNotFoundException.java index 7e0649ce9c..3aeb0096bc 100644 --- a/src/main/java/stirling/software/SPDF/model/exception/BackupNotFoundException.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/exception/BackupNotFoundException.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.model.exception; +package stirling.software.proprietary.security.model.exception; public class BackupNotFoundException extends RuntimeException { public BackupNotFoundException(String message) { diff --git a/src/main/java/stirling/software/SPDF/model/exception/NoProviderFoundException.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/exception/NoProviderFoundException.java similarity index 79% rename from src/main/java/stirling/software/SPDF/model/exception/NoProviderFoundException.java rename to proprietary/src/main/java/stirling/software/proprietary/security/model/exception/NoProviderFoundException.java index 162070f380..3108212533 100644 --- a/src/main/java/stirling/software/SPDF/model/exception/NoProviderFoundException.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/exception/NoProviderFoundException.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.model.exception; +package stirling.software.proprietary.security.model.exception; public class NoProviderFoundException extends Exception { public NoProviderFoundException(String message) { diff --git a/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java similarity index 97% rename from src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java rename to proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java index 9440a6718c..92b053b8ae 100644 --- a/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java @@ -1,7 +1,10 @@ -package stirling.software.SPDF.config.security.oauth2; +package stirling.software.proprietary.security.oauth2; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; - +import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.LockedException; @@ -10,12 +13,6 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import lombok.extern.slf4j.Slf4j; - @Slf4j public class CustomOAuth2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { diff --git a/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java similarity index 94% rename from src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java rename to proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java index 986118466f..1c4d04e55d 100644 --- a/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java @@ -1,29 +1,25 @@ -package stirling.software.SPDF.config.security.oauth2; +package stirling.software.proprietary.security.oauth2; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; import java.io.IOException; import java.sql.SQLException; - +import lombok.RequiredArgsConstructor; import org.springframework.security.authentication.LockedException; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.security.web.savedrequest.SavedRequest; - -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.http.HttpSession; - -import lombok.RequiredArgsConstructor; - -import stirling.software.SPDF.config.security.LoginAttemptService; -import stirling.software.SPDF.config.security.UserService; -import stirling.software.SPDF.model.AuthenticationType; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.util.RequestUriUtils; +import stirling.software.proprietary.security.model.AuthenticationType; +import stirling.software.proprietary.security.service.LoginAttemptService; +import stirling.software.proprietary.security.service.UserService; @RequiredArgsConstructor public class CustomOAuth2AuthenticationSuccessHandler diff --git a/src/main/java/stirling/software/SPDF/config/security/oauth2/OAuth2Configuration.java b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java similarity index 96% rename from src/main/java/stirling/software/SPDF/config/security/oauth2/OAuth2Configuration.java rename to proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java index 98d69113ce..a0f11c5b21 100644 --- a/src/main/java/stirling/software/SPDF/config/security/oauth2/OAuth2Configuration.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java @@ -1,15 +1,12 @@ -package stirling.software.SPDF.config.security.oauth2; - -import static org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE; -import static stirling.software.common.util.ProviderUtils.validateProvider; -import static stirling.software.common.util.ValidationUtils.isStringEmpty; +package stirling.software.proprietary.security.oauth2; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; - +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -22,24 +19,25 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio import org.springframework.security.oauth2.client.registration.ClientRegistrations; import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; import org.springframework.security.oauth2.core.user.OAuth2UserAuthority; - -import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.config.security.UserService; -import stirling.software.SPDF.model.User; -import stirling.software.SPDF.model.exception.NoProviderFoundException; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2.Client; import stirling.software.common.model.enumeration.UsernameAttribute; +import stirling.software.proprietary.security.model.exception.NoProviderFoundException; import stirling.software.common.model.oauth2.GitHubProvider; import stirling.software.common.model.oauth2.GoogleProvider; import stirling.software.common.model.oauth2.KeycloakProvider; import stirling.software.common.model.oauth2.Provider; +import stirling.software.proprietary.security.model.User; +import stirling.software.proprietary.security.service.UserService; +import static org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE; +import static stirling.software.common.util.ProviderUtils.validateProvider; +import static stirling.software.common.util.ValidationUtils.isStringEmpty; @Slf4j @Configuration @ConditionalOnProperty(value = "security.oauth2.enabled", havingValue = "true") +@ConditionalOnExpression("${docker.enable.security:true}") // todo: change this public class OAuth2Configuration { public static final String REDIRECT_URI_PATH = "{baseUrl}/login/oauth2/code/"; diff --git a/src/main/java/stirling/software/SPDF/config/security/saml2/CertificateUtils.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java similarity index 97% rename from src/main/java/stirling/software/SPDF/config/security/saml2/CertificateUtils.java rename to proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java index 354e787509..c2957e2413 100644 --- a/src/main/java/stirling/software/SPDF/config/security/saml2/CertificateUtils.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.config.security.saml2; +package stirling.software.proprietary.security.saml2; import java.io.ByteArrayInputStream; import java.io.InputStreamReader; @@ -6,7 +6,6 @@ import java.nio.charset.StandardCharsets; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; - import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; diff --git a/src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2AuthenticatedPrincipal.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java similarity index 93% rename from src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2AuthenticatedPrincipal.java rename to proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java index fbcdb31b44..055ac8f4e1 100644 --- a/src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2AuthenticatedPrincipal.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java @@ -1,9 +1,8 @@ -package stirling.software.SPDF.config.security.saml2; +package stirling.software.proprietary.security.saml2; import java.io.Serializable; import java.util.List; import java.util.Map; - import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal; diff --git a/src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2AuthenticationFailureHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java similarity index 96% rename from src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2AuthenticationFailureHandler.java rename to proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java index 884c3bd2e8..a7e663aac0 100644 --- a/src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2AuthenticationFailureHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java @@ -1,7 +1,9 @@ -package stirling.software.SPDF.config.security.saml2; +package stirling.software.proprietary.security.saml2; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; - +import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.security.authentication.ProviderNotFoundException; import org.springframework.security.core.AuthenticationException; @@ -9,11 +11,6 @@ import org.springframework.security.saml2.core.Saml2Error; import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import lombok.extern.slf4j.Slf4j; - @Slf4j @ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true") public class CustomSaml2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { diff --git a/src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2AuthenticationSuccessHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java similarity index 95% rename from src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2AuthenticationSuccessHandler.java rename to proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java index 94fddae627..47391e4d05 100644 --- a/src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2AuthenticationSuccessHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java @@ -1,28 +1,24 @@ -package stirling.software.SPDF.config.security.saml2; - -import java.io.IOException; -import java.sql.SQLException; - -import org.springframework.security.authentication.LockedException; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; -import org.springframework.security.web.savedrequest.SavedRequest; +package stirling.software.proprietary.security.saml2; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; - +import java.io.IOException; +import java.sql.SQLException; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.config.security.LoginAttemptService; -import stirling.software.SPDF.config.security.UserService; -import stirling.software.SPDF.model.AuthenticationType; +import org.springframework.security.authentication.LockedException; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.security.web.savedrequest.SavedRequest; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.SAML2; import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.util.RequestUriUtils; +import stirling.software.proprietary.security.model.AuthenticationType; +import stirling.software.proprietary.security.service.LoginAttemptService; +import stirling.software.proprietary.security.service.UserService; @AllArgsConstructor @Slf4j diff --git a/src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2ResponseAuthenticationConverter.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java similarity index 94% rename from src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2ResponseAuthenticationConverter.java rename to proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java index 4a9cdd2843..d1c24b4206 100644 --- a/src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2ResponseAuthenticationConverter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java @@ -1,7 +1,12 @@ -package stirling.software.SPDF.config.security.saml2; - -import java.util.*; +package stirling.software.proprietary.security.saml2; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.opensaml.core.xml.XMLObject; import org.opensaml.saml.saml2.core.Assertion; import org.opensaml.saml.saml2.core.Attribute; @@ -12,12 +17,8 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.ResponseToken; import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.config.security.UserService; -import stirling.software.SPDF.model.User; +import stirling.software.proprietary.security.model.User; +import stirling.software.proprietary.security.service.UserService; @Slf4j @ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true") diff --git a/src/main/java/stirling/software/SPDF/config/security/saml2/SAML2Configuration.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java similarity index 99% rename from src/main/java/stirling/software/SPDF/config/security/saml2/SAML2Configuration.java rename to proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java index 8a6ff10cc5..8482b87538 100644 --- a/src/main/java/stirling/software/SPDF/config/security/saml2/SAML2Configuration.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java @@ -1,9 +1,11 @@ -package stirling.software.SPDF.config.security.saml2; +package stirling.software.proprietary.security.saml2; +import jakarta.servlet.http.HttpServletRequest; import java.security.cert.X509Certificate; import java.util.Collections; import java.util.UUID; - +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.opensaml.saml.saml2.core.AuthnRequest; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; @@ -18,12 +20,6 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; import org.springframework.security.saml2.provider.service.web.HttpSessionSaml2AuthenticationRequestRepository; import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver; - -import jakarta.servlet.http.HttpServletRequest; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.SAML2; diff --git a/src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/AppUpdateAuthService.java similarity index 83% rename from src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java rename to proprietary/src/main/java/stirling/software/proprietary/security/service/AppUpdateAuthService.java index 7139fc686b..5687a3b926 100644 --- a/src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/AppUpdateAuthService.java @@ -1,17 +1,14 @@ -package stirling.software.SPDF.config.security; +package stirling.software.proprietary.security.service; import java.util.Optional; - +import lombok.RequiredArgsConstructor; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; - -import lombok.RequiredArgsConstructor; - -import stirling.software.SPDF.config.interfaces.ShowAdminInterface; -import stirling.software.SPDF.model.User; -import stirling.software.SPDF.repository.UserRepository; +import stirling.software.common.configuration.interfaces.ShowAdminInterface; import stirling.software.common.model.ApplicationProperties; +import stirling.software.proprietary.security.database.repository.UserRepository; +import stirling.software.proprietary.security.model.User; @Service @RequiredArgsConstructor diff --git a/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2UserService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java similarity index 94% rename from src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2UserService.java rename to proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java index 458dd34779..b889a06e58 100644 --- a/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2UserService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java @@ -1,7 +1,7 @@ -package stirling.software.SPDF.config.security.oauth2; +package stirling.software.proprietary.security.service; import java.util.Optional; - +import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.LockedException; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; @@ -10,15 +10,10 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; import org.springframework.security.oauth2.core.oidc.user.OidcUser; - -import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.config.security.LoginAttemptService; -import stirling.software.SPDF.config.security.UserService; -import stirling.software.SPDF.model.User; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.enumeration.UsernameAttribute; +import stirling.software.proprietary.security.model.User; @Slf4j public class CustomOAuth2UserService implements OAuth2UserService { diff --git a/src/main/java/stirling/software/SPDF/config/security/CustomUserDetailsService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java similarity index 89% rename from src/main/java/stirling/software/SPDF/config/security/CustomUserDetailsService.java rename to proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java index 74c3fb9a4d..0146669717 100644 --- a/src/main/java/stirling/software/SPDF/config/security/CustomUserDetailsService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java @@ -1,8 +1,8 @@ -package stirling.software.SPDF.config.security; +package stirling.software.proprietary.security.service; import java.util.Collection; import java.util.Set; - +import lombok.RequiredArgsConstructor; import org.springframework.security.authentication.LockedException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -10,12 +10,9 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; - -import lombok.RequiredArgsConstructor; - -import stirling.software.SPDF.model.Authority; -import stirling.software.SPDF.model.User; -import stirling.software.SPDF.repository.UserRepository; +import stirling.software.proprietary.security.database.repository.UserRepository; +import stirling.software.proprietary.security.model.Authority; +import stirling.software.proprietary.security.model.User; @Service @RequiredArgsConstructor diff --git a/src/main/java/stirling/software/SPDF/config/security/database/DatabaseService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java similarity index 91% rename from src/main/java/stirling/software/SPDF/config/security/database/DatabaseService.java rename to proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java index f973079b64..37de87cf40 100644 --- a/src/main/java/stirling/software/SPDF/config/security/database/DatabaseService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.config.security.database; +package stirling.software.proprietary.security.service; import java.io.IOException; import java.nio.file.DirectoryStream; @@ -18,24 +18,19 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; - import javax.sql.DataSource; - +import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.datasource.init.CannotReadScriptException; import org.springframework.jdbc.datasource.init.ScriptException; import org.springframework.stereotype.Service; - -import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.config.interfaces.DatabaseInterface; -import stirling.software.SPDF.model.exception.BackupNotFoundException; import stirling.software.common.configuration.InstallationPathConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.FileInfo; +import stirling.software.proprietary.security.model.exception.BackupNotFoundException; @Slf4j @Service -public class DatabaseService implements DatabaseInterface { +public class DatabaseService implements DatabaseServiceInterface { public static final String BACKUP_PREFIX = "backup_"; public static final String SQL_SUFFIX = ".sql"; @@ -240,27 +235,27 @@ public class DatabaseService implements DatabaseInterface { private boolean isH2Database() { boolean isTypeH2 = - datasourceProps.getType().equalsIgnoreCase(ApplicationProperties.Driver.H2.name()); + datasourceProps.getType().equalsIgnoreCase(ApplicationProperties.Driver.H2.name()); boolean isDBUrlH2 = - datasourceProps.getCustomDatabaseUrl().contains("h2") - || datasourceProps.getCustomDatabaseUrl().contains("H2"); + datasourceProps.getCustomDatabaseUrl().contains("h2") + || datasourceProps.getCustomDatabaseUrl().contains("H2"); boolean isCustomDatabase = datasourceProps.isEnableCustomDatabase(); if (isCustomDatabase) { if (isTypeH2 && !isDBUrlH2) { log.warn( - "Datasource type is H2, but the URL does not contain 'h2'. " - + "Please check your configuration."); + "Datasource type is H2, but the URL does not contain 'h2'. " + + "Please check your configuration."); throw new IllegalStateException( - "Datasource type is H2, but the URL does not contain 'h2'. Please check" - + " your configuration."); + "Datasource type is H2, but the URL does not contain 'h2'. Please check" + + " your configuration."); } else if (!isTypeH2 && isDBUrlH2) { log.warn( - "Datasource URL contains 'h2', but the type is not H2. " - + "Please check your configuration."); + "Datasource URL contains 'h2', but the type is not H2. " + + "Please check your configuration."); throw new IllegalStateException( - "Datasource URL contains 'h2', but the type is not H2. Please check your" - + " configuration."); + "Datasource URL contains 'h2', but the type is not H2. Please check your" + + " configuration."); } } boolean isH2 = isTypeH2 && isDBUrlH2; diff --git a/src/main/java/stirling/software/SPDF/config/interfaces/DatabaseInterface.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseServiceInterface.java similarity index 77% rename from src/main/java/stirling/software/SPDF/config/interfaces/DatabaseInterface.java rename to proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseServiceInterface.java index ae802fdc5a..613432f0a9 100644 --- a/src/main/java/stirling/software/SPDF/config/interfaces/DatabaseInterface.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseServiceInterface.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.config.interfaces; +package stirling.software.proprietary.security.service; import java.sql.SQLException; import java.util.List; @@ -6,7 +6,7 @@ import java.util.List; import stirling.software.common.model.FileInfo; import stirling.software.common.model.exception.UnsupportedProviderException; -public interface DatabaseInterface { +public interface DatabaseServiceInterface { void exportDatabase() throws SQLException, UnsupportedProviderException; void importDatabase(); diff --git a/src/main/java/stirling/software/SPDF/config/security/mail/EmailService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java similarity index 96% rename from src/main/java/stirling/software/SPDF/config/security/mail/EmailService.java rename to proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java index e27a2b6816..08860a3407 100644 --- a/src/main/java/stirling/software/SPDF/config/security/mail/EmailService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.config.security.mail; +package stirling.software.proprietary.security.service; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.mail.javamail.JavaMailSender; @@ -12,8 +12,8 @@ import jakarta.mail.internet.MimeMessage; import lombok.RequiredArgsConstructor; -import stirling.software.SPDF.model.api.Email; import stirling.software.common.model.ApplicationProperties; +import stirling.software.proprietary.security.model.api.Email; /** * Service class responsible for sending emails, including those with attachments. It uses diff --git a/src/main/java/stirling/software/SPDF/config/security/LoginAttemptService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java similarity index 95% rename from src/main/java/stirling/software/SPDF/config/security/LoginAttemptService.java rename to proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java index 9beba47608..852fc8ab90 100644 --- a/src/main/java/stirling/software/SPDF/config/security/LoginAttemptService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java @@ -1,17 +1,13 @@ -package stirling.software.SPDF.config.security; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -import org.springframework.stereotype.Service; +package stirling.software.proprietary.security.service; import jakarta.annotation.PostConstruct; - +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.model.AttemptCounter; +import org.springframework.stereotype.Service; import stirling.software.common.model.ApplicationProperties; +import stirling.software.proprietary.security.model.AttemptCounter; @Service @Slf4j diff --git a/src/main/java/stirling/software/SPDF/config/security/UserService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java similarity index 95% rename from src/main/java/stirling/software/SPDF/config/security/UserService.java rename to proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java index 068fde1d43..7bf3e2643c 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.config.security; +package stirling.software.proprietary.security.service; import java.io.IOException; import java.sql.SQLException; @@ -9,9 +9,9 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; - +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.MessageSource; -import org.springframework.context.annotation.Lazy; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -25,22 +25,17 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.config.interfaces.DatabaseInterface; -import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal; -import stirling.software.SPDF.config.security.session.SessionPersistentRegistry; -import stirling.software.SPDF.model.AuthenticationType; -import stirling.software.SPDF.model.Authority; -import stirling.software.SPDF.model.Role; -import stirling.software.SPDF.model.User; -import stirling.software.SPDF.repository.AuthorityRepository; -import stirling.software.SPDF.repository.UserRepository; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.service.UserServiceInterface; +import stirling.software.common.model.enumeration.Role; +import stirling.software.proprietary.security.database.repository.AuthorityRepository; +import stirling.software.proprietary.security.database.repository.UserRepository; +import stirling.software.proprietary.security.model.AuthenticationType; +import stirling.software.proprietary.security.model.Authority; +import stirling.software.proprietary.security.model.User; +import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal; +import stirling.software.proprietary.security.session.SessionPersistentRegistry; @Service @Slf4j @@ -57,7 +52,7 @@ public class UserService implements UserServiceInterface { private final SessionPersistentRegistry sessionRegistry; - @Lazy private final DatabaseInterface databaseService; + private final DatabaseServiceInterface databaseService; private final ApplicationProperties.Security.OAUTH2 oAuth2; @@ -307,7 +302,6 @@ public class UserService implements UserServiceInterface { public void changeUsername(User user, String newUsername) throws IllegalArgumentException, - IOException, SQLException, UnsupportedProviderException { if (!isUsernameValid(newUsername)) { @@ -419,7 +413,7 @@ public class UserService implements UserServiceInterface { if (principal instanceof UserDetails detailsUser) { return detailsUser.getUsername(); - } else if (principal instanceof stirling.software.SPDF.model.User domainUser) { + } else if (principal instanceof User domainUser) { return domainUser.getUsername(); } else if (principal instanceof OAuth2User oAuth2User) { return oAuth2User.getAttribute(oAuth2.getUseAsUsername()); diff --git a/src/main/java/stirling/software/SPDF/config/security/session/CustomHttpSessionListener.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/CustomHttpSessionListener.java similarity index 92% rename from src/main/java/stirling/software/SPDF/config/security/session/CustomHttpSessionListener.java rename to proprietary/src/main/java/stirling/software/proprietary/security/session/CustomHttpSessionListener.java index 09868eff94..7ed0f65064 100644 --- a/src/main/java/stirling/software/SPDF/config/security/session/CustomHttpSessionListener.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/CustomHttpSessionListener.java @@ -1,11 +1,9 @@ -package stirling.software.SPDF.config.security.session; - -import org.springframework.stereotype.Component; +package stirling.software.proprietary.security.session; import jakarta.servlet.http.HttpSessionEvent; import jakarta.servlet.http.HttpSessionListener; - import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; @Component @Slf4j diff --git a/src/main/java/stirling/software/SPDF/config/security/session/SessionPersistentRegistry.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionPersistentRegistry.java similarity index 94% rename from src/main/java/stirling/software/SPDF/config/security/session/SessionPersistentRegistry.java rename to proprietary/src/main/java/stirling/software/proprietary/security/session/SessionPersistentRegistry.java index 9e249f3a40..5d482e94d2 100644 --- a/src/main/java/stirling/software/SPDF/config/security/session/SessionPersistentRegistry.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionPersistentRegistry.java @@ -1,21 +1,23 @@ -package stirling.software.SPDF.config.security.session; +package stirling.software.proprietary.security.session; +import jakarta.transaction.Transactional; import java.time.Duration; -import java.util.*; - +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.session.SessionInformation; import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Component; - -import jakarta.transaction.Transactional; - -import lombok.RequiredArgsConstructor; - -import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal; -import stirling.software.SPDF.model.SessionEntity; +import stirling.software.proprietary.security.database.repository.SessionRepository; +import stirling.software.proprietary.security.model.SessionEntity; +import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal; @Component @RequiredArgsConstructor diff --git a/src/main/java/stirling/software/SPDF/config/security/session/SessionRegistryConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java similarity index 57% rename from src/main/java/stirling/software/SPDF/config/security/session/SessionRegistryConfig.java rename to proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java index 18a84279cb..75afbea9b7 100644 --- a/src/main/java/stirling/software/SPDF/config/security/session/SessionRegistryConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java @@ -1,12 +1,11 @@ -package stirling.software.SPDF.config.security.session; +package stirling.software.proprietary.security.session; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.core.session.SessionRegistryImpl; +import stirling.software.proprietary.security.database.repository.SessionRepository; @Configuration -@ConditionalOnProperty(name = "premium.enabled", havingValue = "true") public class SessionRegistryConfig { @Bean @@ -15,8 +14,7 @@ public class SessionRegistryConfig { } @Bean - public SessionPersistentRegistry sessionPersistentRegistry( - SessionRepository sessionRepository) { + public SessionPersistentRegistry sessionPersistentRegistry(SessionRepository sessionRepository) { return new SessionPersistentRegistry(sessionRepository); } } diff --git a/src/main/java/stirling/software/SPDF/config/security/session/SessionScheduled.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java similarity index 95% rename from src/main/java/stirling/software/SPDF/config/security/session/SessionScheduled.java rename to proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java index 46c17a77ec..83403f9f74 100644 --- a/src/main/java/stirling/software/SPDF/config/security/session/SessionScheduled.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java @@ -1,16 +1,14 @@ -package stirling.software.SPDF.config.security.session; +package stirling.software.proprietary.security.session; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.List; - +import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.security.core.session.SessionInformation; import org.springframework.stereotype.Component; -import lombok.RequiredArgsConstructor; - @Component @RequiredArgsConstructor public class SessionScheduled { diff --git a/src/test/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandlerTest.java b/proprietary/src/test/java/stirling/software/proprietary/security/CustomLogoutSuccessHandlerTest.java similarity index 98% rename from src/test/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandlerTest.java rename to proprietary/src/test/java/stirling/software/proprietary/security/CustomLogoutSuccessHandlerTest.java index 79638cafe5..a5abd6be5a 100644 --- a/src/test/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandlerTest.java +++ b/proprietary/src/test/java/stirling/software/proprietary/security/CustomLogoutSuccessHandlerTest.java @@ -1,22 +1,17 @@ -package stirling.software.SPDF.config.security; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +package stirling.software.proprietary.security; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; - import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - import stirling.software.common.model.ApplicationProperties; +import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class CustomLogoutSuccessHandlerTest { diff --git a/src/test/java/stirling/software/SPDF/config/security/database/DatabaseConfigTest.java b/proprietary/src/test/java/stirling/software/proprietary/security/configuration/DatabaseConfigTest.java similarity index 94% rename from src/test/java/stirling/software/SPDF/config/security/database/DatabaseConfigTest.java rename to proprietary/src/test/java/stirling/software/proprietary/security/configuration/DatabaseConfigTest.java index 45bbd28c05..b1dc3a29e7 100644 --- a/src/test/java/stirling/software/SPDF/config/security/database/DatabaseConfigTest.java +++ b/proprietary/src/test/java/stirling/software/proprietary/security/configuration/DatabaseConfigTest.java @@ -1,11 +1,6 @@ -package stirling.software.SPDF.config.security.database; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.when; +package stirling.software.proprietary.security.configuration; import javax.sql.DataSource; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -13,9 +8,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; - import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.exception.UnsupportedProviderException; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class DatabaseConfigTest { diff --git a/src/test/java/stirling/software/SPDF/controller/api/EmailControllerTest.java b/proprietary/src/test/java/stirling/software/proprietary/security/controller/api/EmailControllerTest.java similarity index 94% rename from src/test/java/stirling/software/SPDF/controller/api/EmailControllerTest.java rename to proprietary/src/test/java/stirling/software/proprietary/security/controller/api/EmailControllerTest.java index dfd68e0693..74bf884042 100644 --- a/src/test/java/stirling/software/SPDF/controller/api/EmailControllerTest.java +++ b/proprietary/src/test/java/stirling/software/proprietary/security/controller/api/EmailControllerTest.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.controller.api; +package stirling.software.proprietary.security.controller.api; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; @@ -23,8 +23,8 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import jakarta.mail.MessagingException; -import stirling.software.SPDF.config.security.mail.EmailService; -import stirling.software.SPDF.model.api.Email; +import stirling.software.proprietary.security.model.api.Email; +import stirling.software.proprietary.security.service.EmailService; @ExtendWith(MockitoExtension.class) class EmailControllerTest { diff --git a/src/test/java/stirling/software/SPDF/config/security/mail/EmailServiceTest.java b/proprietary/src/test/java/stirling/software/proprietary/security/service/EmailServiceTest.java similarity index 94% rename from src/test/java/stirling/software/SPDF/config/security/mail/EmailServiceTest.java rename to proprietary/src/test/java/stirling/software/proprietary/security/service/EmailServiceTest.java index 64f02799bc..e953783a88 100644 --- a/src/test/java/stirling/software/SPDF/config/security/mail/EmailServiceTest.java +++ b/proprietary/src/test/java/stirling/software/proprietary/security/service/EmailServiceTest.java @@ -1,9 +1,9 @@ -package stirling.software.SPDF.config.security.mail; +package stirling.software.proprietary.security.service; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; -import static org.mockito.Mockito.*; - +import jakarta.mail.MessagingException; +import jakarta.mail.internet.MimeMessage; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -15,8 +15,11 @@ import org.springframework.web.multipart.MultipartFile; import jakarta.mail.MessagingException; import jakarta.mail.internet.MimeMessage; -import stirling.software.SPDF.model.api.Email; import stirling.software.common.model.ApplicationProperties; +import stirling.software.proprietary.security.model.api.Email; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) public class EmailServiceTest { diff --git a/src/test/java/stirling/software/SPDF/config/security/mail/MailConfigTest.java b/proprietary/src/test/java/stirling/software/proprietary/security/service/MailConfigTest.java similarity index 94% rename from src/test/java/stirling/software/SPDF/config/security/mail/MailConfigTest.java rename to proprietary/src/test/java/stirling/software/proprietary/security/service/MailConfigTest.java index bff1cb5ebc..3db3493f4b 100644 --- a/src/test/java/stirling/software/SPDF/config/security/mail/MailConfigTest.java +++ b/proprietary/src/test/java/stirling/software/proprietary/security/service/MailConfigTest.java @@ -1,4 +1,4 @@ -package stirling.software.SPDF.config.security.mail; +package stirling.software.proprietary.security.service; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -14,6 +14,7 @@ import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSenderImpl; import stirling.software.common.model.ApplicationProperties; +import stirling.software.proprietary.security.configuration.MailConfig; class MailConfigTest { diff --git a/settings.gradle b/settings.gradle index 0dbeab6e72..e4e55768e7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,4 +4,4 @@ plugins { } rootProject.name = 'Stirling-PDF' -include 'common' +include 'common', 'proprietary' diff --git a/src/main/java/stirling/software/SPDF/config/AppUpdateService.java b/src/main/java/stirling/software/SPDF/config/AppUpdateService.java index f89c9aed32..c4c528f77c 100644 --- a/src/main/java/stirling/software/SPDF/config/AppUpdateService.java +++ b/src/main/java/stirling/software/SPDF/config/AppUpdateService.java @@ -5,7 +5,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; -import stirling.software.SPDF.config.interfaces.ShowAdminInterface; +import stirling.software.common.configuration.interfaces.ShowAdminInterface; import stirling.software.common.model.ApplicationProperties; @Configuration diff --git a/src/main/java/stirling/software/SPDF/config/interfaces/ShowAdminInterface.java b/src/main/java/stirling/software/SPDF/config/interfaces/ShowAdminInterface.java deleted file mode 100644 index 1bbebf5a99..0000000000 --- a/src/main/java/stirling/software/SPDF/config/interfaces/ShowAdminInterface.java +++ /dev/null @@ -1,7 +0,0 @@ -package stirling.software.SPDF.config.interfaces; - -public interface ShowAdminInterface { - default boolean getShowUpdateOnlyAdmins() { - return true; - } -} diff --git a/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java b/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java deleted file mode 100644 index f0829e23e0..0000000000 --- a/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java +++ /dev/null @@ -1,319 +0,0 @@ -package stirling.software.SPDF.config.security; - -import java.util.Optional; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.DependsOn; -import org.springframework.context.annotation.Lazy; -import org.springframework.security.authentication.ProviderManager; -import org.springframework.security.authentication.dao.DaoAuthenticationProvider; -import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider; -import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; -import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; -import org.springframework.security.web.csrf.CookieCsrfTokenRepository; -import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; -import org.springframework.security.web.savedrequest.NullRequestCache; -import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; - -import lombok.extern.slf4j.Slf4j; - -import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationFailureHandler; -import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationSuccessHandler; -import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService; -import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticationFailureHandler; -import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticationSuccessHandler; -import stirling.software.SPDF.config.security.saml2.CustomSaml2ResponseAuthenticationConverter; -import stirling.software.SPDF.config.security.session.SessionPersistentRegistry; -import stirling.software.SPDF.model.User; -import stirling.software.SPDF.repository.JPATokenRepositoryImpl; -import stirling.software.SPDF.repository.PersistentLoginRepository; -import stirling.software.common.model.ApplicationProperties; - -@Configuration -@EnableWebSecurity -@EnableMethodSecurity -@Slf4j -@DependsOn("runningProOrHigher") -public class SecurityConfiguration { - - private final CustomUserDetailsService userDetailsService; - private final UserService userService; - private final boolean loginEnabledValue; - private final boolean runningProOrHigher; - - private final ApplicationProperties applicationProperties; - private final UserAuthenticationFilter userAuthenticationFilter; - private final LoginAttemptService loginAttemptService; - private final FirstLoginFilter firstLoginFilter; - private final SessionPersistentRegistry sessionRegistry; - private final PersistentLoginRepository persistentLoginRepository; - private final GrantedAuthoritiesMapper oAuth2userAuthoritiesMapper; - private final RelyingPartyRegistrationRepository saml2RelyingPartyRegistrations; - private final OpenSaml4AuthenticationRequestResolver saml2AuthenticationRequestResolver; - - public SecurityConfiguration( - PersistentLoginRepository persistentLoginRepository, - CustomUserDetailsService userDetailsService, - @Lazy UserService userService, - @Qualifier("loginEnabled") boolean loginEnabledValue, - @Qualifier("runningProOrHigher") boolean runningProOrHigher, - ApplicationProperties applicationProperties, - UserAuthenticationFilter userAuthenticationFilter, - LoginAttemptService loginAttemptService, - FirstLoginFilter firstLoginFilter, - SessionPersistentRegistry sessionRegistry, - @Autowired(required = false) GrantedAuthoritiesMapper oAuth2userAuthoritiesMapper, - @Autowired(required = false) - RelyingPartyRegistrationRepository saml2RelyingPartyRegistrations, - @Autowired(required = false) - OpenSaml4AuthenticationRequestResolver saml2AuthenticationRequestResolver) { - this.userDetailsService = userDetailsService; - this.userService = userService; - this.loginEnabledValue = loginEnabledValue; - this.runningProOrHigher = runningProOrHigher; - this.applicationProperties = applicationProperties; - this.userAuthenticationFilter = userAuthenticationFilter; - this.loginAttemptService = loginAttemptService; - this.firstLoginFilter = firstLoginFilter; - this.sessionRegistry = sessionRegistry; - this.persistentLoginRepository = persistentLoginRepository; - this.oAuth2userAuthoritiesMapper = oAuth2userAuthoritiesMapper; - this.saml2RelyingPartyRegistrations = saml2RelyingPartyRegistrations; - this.saml2AuthenticationRequestResolver = saml2AuthenticationRequestResolver; - } - - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } - - @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - if (applicationProperties.getSecurity().getCsrfDisabled() || !loginEnabledValue) { - http.csrf(csrf -> csrf.disable()); - } - - if (loginEnabledValue) { - http.addFilterBefore( - userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); - if (!applicationProperties.getSecurity().getCsrfDisabled()) { - CookieCsrfTokenRepository cookieRepo = - CookieCsrfTokenRepository.withHttpOnlyFalse(); - CsrfTokenRequestAttributeHandler requestHandler = - new CsrfTokenRequestAttributeHandler(); - requestHandler.setCsrfRequestAttributeName(null); - http.csrf( - csrf -> - csrf.ignoringRequestMatchers( - request -> { - String apiKey = request.getHeader("X-API-KEY"); - // If there's no API key, don't ignore CSRF - // (return false) - if (apiKey == null || apiKey.trim().isEmpty()) { - return false; - } - // Validate API key using existing UserService - try { - Optional user = - userService.getUserByApiKey(apiKey); - // If API key is valid, ignore CSRF (return - // true) - // If API key is invalid, don't ignore CSRF - // (return false) - return user.isPresent(); - } catch (Exception e) { - // If there's any error validating the API - // key, don't ignore CSRF - return false; - } - }) - .csrfTokenRepository(cookieRepo) - .csrfTokenRequestHandler(requestHandler)); - } - http.addFilterBefore(rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class); - http.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class); - http.sessionManagement( - sessionManagement -> - sessionManagement - .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) - .maximumSessions(10) - .maxSessionsPreventsLogin(false) - .sessionRegistry(sessionRegistry) - .expiredUrl("/login?logout=true")); - http.authenticationProvider(daoAuthenticationProvider()); - http.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache())); - http.logout( - logout -> - logout.logoutRequestMatcher( - PathPatternRequestMatcher.withDefaults() - .matcher("/logout")) - .logoutSuccessHandler( - new CustomLogoutSuccessHandler(applicationProperties)) - .clearAuthentication(true) - .invalidateHttpSession(true) - .deleteCookies("JSESSIONID", "remember-me")); - http.rememberMe( - rememberMeConfigurer -> // Use the configurator directly - rememberMeConfigurer - .tokenRepository(persistentTokenRepository()) - .tokenValiditySeconds( // 14 days - 14 * 24 * 60 * 60) - .userDetailsService( // Your existing UserDetailsService - userDetailsService) - .useSecureCookie( // Enable secure cookie - true) - .rememberMeParameter( // Form parameter name - "remember-me") - .rememberMeCookieName( // Cookie name - "remember-me") - .alwaysRemember(false)); - http.authorizeHttpRequests( - authz -> - authz.requestMatchers( - req -> { - String uri = req.getRequestURI(); - String contextPath = req.getContextPath(); - // Remove the context path from the URI - String trimmedUri = - uri.startsWith(contextPath) - ? uri.substring( - contextPath.length()) - : uri; - return trimmedUri.startsWith("/login") - || trimmedUri.startsWith("/oauth") - || trimmedUri.startsWith("/saml2") - || trimmedUri.endsWith(".svg") - || trimmedUri.startsWith("/register") - || trimmedUri.startsWith("/error") - || trimmedUri.startsWith("/images/") - || trimmedUri.startsWith("/public/") - || trimmedUri.startsWith("/css/") - || trimmedUri.startsWith("/fonts/") - || trimmedUri.startsWith("/js/") - || trimmedUri.startsWith( - "/api/v1/info/status"); - }) - .permitAll() - .anyRequest() - .authenticated()); - // Handle User/Password Logins - if (applicationProperties.getSecurity().isUserPass()) { - http.formLogin( - formLogin -> - formLogin - .loginPage("/login") - .successHandler( - new CustomAuthenticationSuccessHandler( - loginAttemptService, userService)) - .failureHandler( - new CustomAuthenticationFailureHandler( - loginAttemptService, userService)) - .defaultSuccessUrl("/") - .permitAll()); - } - // Handle OAUTH2 Logins - if (applicationProperties.getSecurity().isOauth2Active()) { - http.oauth2Login( - oauth2 -> - oauth2.loginPage("/oauth2") - . - /* - This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database. - If user exists, login proceeds as usual. If user does not exist, then it is auto-created but only if 'OAUTH2AutoCreateUser' - is set as true, else login fails with an error message advising the same. - */ - successHandler( - new CustomOAuth2AuthenticationSuccessHandler( - loginAttemptService, - applicationProperties, - userService)) - .failureHandler( - new CustomOAuth2AuthenticationFailureHandler()) - . // Add existing Authorities from the database - userInfoEndpoint( - userInfoEndpoint -> - userInfoEndpoint - .oidcUserService( - new CustomOAuth2UserService( - applicationProperties, - userService, - loginAttemptService)) - .userAuthoritiesMapper( - oAuth2userAuthoritiesMapper)) - .permitAll()); - } - // Handle SAML - if (applicationProperties.getSecurity().isSaml2Active() && runningProOrHigher) { - // Configure the authentication provider - OpenSaml4AuthenticationProvider authenticationProvider = - new OpenSaml4AuthenticationProvider(); - authenticationProvider.setResponseAuthenticationConverter( - new CustomSaml2ResponseAuthenticationConverter(userService)); - http.authenticationProvider(authenticationProvider) - .saml2Login( - saml2 -> { - try { - saml2.loginPage("/saml2") - .relyingPartyRegistrationRepository( - saml2RelyingPartyRegistrations) - .authenticationManager( - new ProviderManager(authenticationProvider)) - .successHandler( - new CustomSaml2AuthenticationSuccessHandler( - loginAttemptService, - applicationProperties, - userService)) - .failureHandler( - new CustomSaml2AuthenticationFailureHandler()) - .authenticationRequestResolver( - saml2AuthenticationRequestResolver); - } catch (Exception e) { - log.error("Error configuring SAML 2 login", e); - throw new RuntimeException(e); - } - }); - } - } else { - log.debug("SAML 2 login is not enabled. Using default."); - http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll()); - } - return http.build(); - } - - public DaoAuthenticationProvider daoAuthenticationProvider() { - DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); - provider.setUserDetailsService(userDetailsService); - provider.setPasswordEncoder(passwordEncoder()); - return provider; - } - - @Bean - public IPRateLimitingFilter rateLimitingFilter() { - // Example limit TODO add config level - int maxRequestsPerIp = 1000000; - return new IPRateLimitingFilter(maxRequestsPerIp, maxRequestsPerIp); - } - - @Bean - public PersistentTokenRepository persistentTokenRepository() { - return new JPATokenRepositoryImpl(persistentLoginRepository); - } - - @Bean - public boolean activeSecurity() { - return true; - } -} diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java index 6716106d51..d81e3843f3 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java @@ -23,8 +23,8 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; -import stirling.software.SPDF.model.api.GeneralFile; import stirling.software.common.configuration.RuntimePathConfig; +import stirling.software.common.model.api.GeneralFile; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ProcessExecutor; import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; diff --git a/src/main/java/stirling/software/SPDF/controller/api/pipeline/ApiDocService.java b/src/main/java/stirling/software/SPDF/controller/api/pipeline/ApiDocService.java index 438ea980a2..2e6e71b1ff 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/pipeline/ApiDocService.java +++ b/src/main/java/stirling/software/SPDF/controller/api/pipeline/ApiDocService.java @@ -24,7 +24,7 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.SPDFApplication; import stirling.software.SPDF.model.ApiEndpoint; -import stirling.software.SPDF.model.Role; +import stirling.software.common.model.enumeration.Role; import stirling.software.common.service.UserServiceInterface; @Service diff --git a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java index 21be0861be..4e052b55ec 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java +++ b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java @@ -35,7 +35,7 @@ import stirling.software.SPDF.SPDFApplication; import stirling.software.SPDF.model.PipelineConfig; import stirling.software.SPDF.model.PipelineOperation; import stirling.software.SPDF.model.PipelineResult; -import stirling.software.SPDF.model.Role; +import stirling.software.common.model.enumeration.Role; import stirling.software.common.service.UserServiceInterface; @Service diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java b/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java index bc0a4ff9d6..47e45c5953 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java @@ -4,9 +4,18 @@ import java.io.IOException; import org.apache.pdfbox.cos.COSDictionary; import org.apache.pdfbox.cos.COSName; -import org.apache.pdfbox.pdmodel.*; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDDocumentCatalog; +import org.apache.pdfbox.pdmodel.PDDocumentInformation; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageTree; +import org.apache.pdfbox.pdmodel.PDResources; import org.apache.pdfbox.pdmodel.common.PDMetadata; -import org.apache.pdfbox.pdmodel.interactive.action.*; +import org.apache.pdfbox.pdmodel.interactive.action.PDAction; +import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript; +import org.apache.pdfbox.pdmodel.interactive.action.PDActionLaunch; +import org.apache.pdfbox.pdmodel.interactive.action.PDActionURI; +import org.apache.pdfbox.pdmodel.interactive.action.PDFormFieldAdditionalActions; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget; diff --git a/src/main/java/stirling/software/SPDF/model/AuthenticationType.java b/src/main/java/stirling/software/SPDF/model/AuthenticationType.java deleted file mode 100644 index 80419cdd24..0000000000 --- a/src/main/java/stirling/software/SPDF/model/AuthenticationType.java +++ /dev/null @@ -1,6 +0,0 @@ -package stirling.software.SPDF.model; - -public enum AuthenticationType { - WEB, - SSO -} diff --git a/src/main/java/stirling/software/SPDF/model/PdfMetadata.java b/src/main/java/stirling/software/SPDF/model/PdfMetadata.java deleted file mode 100644 index 35054bc8c7..0000000000 --- a/src/main/java/stirling/software/SPDF/model/PdfMetadata.java +++ /dev/null @@ -1,19 +0,0 @@ -package stirling.software.SPDF.model; - -import java.util.Calendar; - -import lombok.Builder; -import lombok.Data; - -@Data -@Builder -public class PdfMetadata { - private String author; - private String producer; - private String title; - private String creator; - private String subject; - private String keywords; - private Calendar creationDate; - private Calendar modificationDate; -} diff --git a/src/main/java/stirling/software/SPDF/model/Role.java b/src/main/java/stirling/software/SPDF/model/Role.java deleted file mode 100644 index 7d45e3da37..0000000000 --- a/src/main/java/stirling/software/SPDF/model/Role.java +++ /dev/null @@ -1,66 +0,0 @@ -package stirling.software.SPDF.model; - -import java.util.LinkedHashMap; -import java.util.Map; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public enum Role { - - // Unlimited access - ADMIN("ROLE_ADMIN", Integer.MAX_VALUE, Integer.MAX_VALUE, "adminUserSettings.admin"), - - // Unlimited access - USER("ROLE_USER", Integer.MAX_VALUE, Integer.MAX_VALUE, "adminUserSettings.user"), - - // 40 API calls Per Day, 40 web calls - LIMITED_API_USER("ROLE_LIMITED_API_USER", 40, 40, "adminUserSettings.apiUser"), - - // 20 API calls Per Day, 20 web calls - EXTRA_LIMITED_API_USER("ROLE_EXTRA_LIMITED_API_USER", 20, 20, "adminUserSettings.extraApiUser"), - - // 0 API calls per day and 20 web calls - WEB_ONLY_USER("ROLE_WEB_ONLY_USER", 0, 20, "adminUserSettings.webOnlyUser"), - - INTERNAL_API_USER( - "STIRLING-PDF-BACKEND-API-USER", - Integer.MAX_VALUE, - Integer.MAX_VALUE, - "adminUserSettings.internalApiUser"), - - DEMO_USER("ROLE_DEMO_USER", 100, 100, "adminUserSettings.demoUser"); - - private final String roleId; - private final int apiCallsPerDay; - private final int webCallsPerDay; - private final String roleName; - - public static String getRoleNameByRoleId(String roleId) { - // Using the fromString method to get the Role enum based on the roleId - Role role = fromString(roleId); - // Return the roleName of the found Role enum - return role.getRoleName(); - } - - // Method to retrieve all role IDs and role names - public static Map getAllRoleDetails() { - // Using LinkedHashMap to preserve order - Map roleDetails = new LinkedHashMap<>(); - for (Role role : Role.values()) { - roleDetails.put(role.getRoleId(), role.getRoleName()); - } - return roleDetails; - } - - public static Role fromString(String roleId) { - for (Role role : Role.values()) { - if (role.getRoleId().equalsIgnoreCase(roleId)) { - return role; - } - } - throw new IllegalArgumentException("No Role defined for id: " + roleId); - } -} From 6d8173b0218260b02da3a869efc667d8e7e2c753 Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Tue, 27 May 2025 17:28:11 +0100 Subject: [PATCH 04/15] updating license --- .../gradle/wrapper/gradle-wrapper.properties | 6 ---- proprietary/LICENSE-proprietary | 33 ++++--------------- proprietary/build.gradle | 13 ++++---- .../gradle/wrapper/gradle-wrapper.properties | 6 ---- 4 files changed, 13 insertions(+), 45 deletions(-) delete mode 100644 common/gradle/wrapper/gradle-wrapper.properties delete mode 100644 proprietary/gradle/wrapper/gradle-wrapper.properties diff --git a/common/gradle/wrapper/gradle-wrapper.properties b/common/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index f7664bccf7..0000000000 --- a/common/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/proprietary/LICENSE-proprietary b/proprietary/LICENSE-proprietary index f723a28092..9f8fef545c 100644 --- a/proprietary/LICENSE-proprietary +++ b/proprietary/LICENSE-proprietary @@ -4,33 +4,14 @@ Copyright (c) 2025-present Stirling Tools With regard to the Stirling PDF Software: -This software and associated documentation files (the "Software") may only be -used in production, if you (and any entity that you represent) have agreed to, -and are in compliance with, the Stirling PDF Terms of Service, available -at https://www.stirlingpdf.com/terms-and-conditions (the “EE Terms”), or other -agreement governing the use of the Software, as agreed by you and Stirling PDF, -and otherwise have a valid Stirling PDF Enterprise Edition subscription for the -correct number of user seats. Subject to the foregoing sentence, you are free to -modify this Software and publish patches to the Software. You agree that Stirling PDF -and/or its licensors (as applicable) retain all right, title and interest in and -to all such modifications and/or patches, and all such modifications and/or -patches may only be used, copied, modified, displayed, distributed, or otherwise -exploited with a valid Stirling PDF Enterprise Edition subscription for the correct -number of user seats. Notwithstanding the foregoing, you may copy and modify -the Software for development and testing purposes, without requiring a -subscription. You agree that Stirling PDF and/or its licensors (as applicable) retain -all right, title and interest in and to all such modifications. You are not -granted any other rights beyond what is expressly stated herein. Subject to the -foregoing, it is forbidden to copy, merge, publish, distribute, sublicense, -and/or sell the Software. +Trial and Minimal Use -This EE License applies only to the part of this Software that is not -distributed as part of MIT License. Any part of this Software -distributed as part of MIT License or is served client-side as an image, font, -cascading stylesheet (CSS), file which produces or is compiled, arranged, -augmented, or combined into client-side JavaScript, in whole or in part, is -copyrighted under the MIT Expat license. The full text of this EE License shall -be included in all copies or substantial portions of the Software. +You may use the Software without a subscription for purposes of trial, evaluation, or minimal use, including use by individuals, +organizations, or businesses, provided that: + * The usage is limited in scope (e.g. up to five (5) sessions or uses, or as otherwise defined within the Software); + * You do not modify, distribute, sublicense, or reverse-engineer the Software; + * Any continued use beyond the permitted trial or minimal use scope requires a valid Stirling PDF Enterprise Edition + subscription for the appropriate number of users. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, diff --git a/proprietary/build.gradle b/proprietary/build.gradle index 8f548a785f..5c91d21ba6 100644 --- a/proprietary/build.gradle +++ b/proprietary/build.gradle @@ -19,25 +19,24 @@ configurations.all { dependencyManagement { imports { - mavenBom 'org.springframework.boot:spring-boot-dependencies:3.4.5' + mavenBom 'org.springframework.boot:spring-boot-dependencies:3.5.0' } } dependencies { implementation project(':common') - implementation 'org.springframework:spring-jdbc:6.2.7' - implementation 'org.springframework:spring-webmvc:6.2.7' + implementation 'org.springframework:spring-jdbc' + implementation 'org.springframework:spring-webmvc' + implementation 'org.springframework.session:spring-session-core' + implementation "org.springframework.security:spring-security-core:$springSecuritySamlVersion" + implementation "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion" implementation 'org.springframework.boot:spring-boot-starter-jetty' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' implementation 'org.springframework.boot:spring-boot-starter-mail' - implementation "org.springframework.security:spring-security-core:$springSecuritySamlVersion" - implementation "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion" - implementation 'org.springframework.session:spring-session-core:3.4.3' implementation 'io.swagger.core.v3:swagger-core-jakarta:2.2.30' - implementation 'com.bucket4j:bucket4j_jdk17-core:8.14.0' // https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17 diff --git a/proprietary/gradle/wrapper/gradle-wrapper.properties b/proprietary/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index f7664bccf7..0000000000 --- a/proprietary/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists From 2b9a3924d3aa58db0abcdc8da36527fcf4978d22 Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Tue, 27 May 2025 19:55:15 +0100 Subject: [PATCH 05/15] added proprietary module to base packages for scanning clean up --- Dockerfile.fat | 2 + LICENSE | 2 +- build.gradle | 30 +++------ common/build.gradle | 26 ++++---- proprietary/LICENSE-proprietary | 66 +++++++++++++------ .../configuration/DatabaseConfig.java | 40 +++++------ .../configuration/SecurityConfiguration.java | 6 +- .../software/SPDF/SPDFApplication.java | 6 +- src/main/resources/settings.yml.template | 1 - 9 files changed, 101 insertions(+), 78 deletions(-) diff --git a/Dockerfile.fat b/Dockerfile.fat index 9029fc8eb5..f442e60c87 100644 --- a/Dockerfile.fat +++ b/Dockerfile.fat @@ -5,6 +5,8 @@ COPY build.gradle . COPY settings.gradle . COPY gradlew . COPY gradle gradle/ +COPY common/build.gradle common/. +COPY proprietary/build.gradle proprietary/. RUN ./gradlew build -x spotlessApply -x spotlessCheck -x test -x sonarqube || return 0 # Set the working directory diff --git a/LICENSE b/LICENSE index 0cd290e886..8776631713 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 Stirling Tools +Copyright (c) 2025 Stirling PDF Inc. Portions of this software are licensed as follows: diff --git a/build.gradle b/build.gradle index cf5a3b7287..c6a2e74be6 100644 --- a/build.gradle +++ b/build.gradle @@ -270,8 +270,6 @@ tasks.register('jpackageMacX64') { } } -//jpackage.finalizedBy(jpackageMacX64) - tasks.register('downloadTempJre') { group = 'distribution' description = 'Downloads and extracts a temporary JRE' @@ -421,20 +419,16 @@ dependencies { implementation("io.github.pixee:java-security-toolkit:1.2.1") // Exclude Tomcat and include Jetty - implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion") +// implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion") implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion" - - implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion" +// implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion" implementation 'com.posthog.java:posthog:1.2.0' implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1' - + implementation 'org.snakeyaml:snakeyaml-engine:2.9' if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") { implementation project(':proprietary') } - implementation 'org.snakeyaml:snakeyaml-engine:2.9' - - testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion" // Batik implementation "org.apache.xmlgraphics:batik-all:1.19" @@ -442,10 +436,12 @@ dependencies { // TwelveMonkeys runtimeOnly "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion" runtimeOnly "com.twelvemonkeys.imageio:imageio-bmp:$imageioVersion" + runtimeOnly "com.twelvemonkeys.imageio:imageio-jpeg:$imageioVersion" + runtimeOnly "com.twelvemonkeys.imageio:imageio-tiff:$imageioVersion" + runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion" // runtimeOnly "com.twelvemonkeys.imageio:imageio-hdr:$imageioVersion" // runtimeOnly "com.twelvemonkeys.imageio:imageio-icns:$imageioVersion" // runtimeOnly "com.twelvemonkeys.imageio:imageio-iff:$imageioVersion" - runtimeOnly "com.twelvemonkeys.imageio:imageio-jpeg:$imageioVersion" // runtimeOnly "com.twelvemonkeys.imageio:imageio-pcx:$imageioVersion@ // runtimeOnly "com.twelvemonkeys.imageio:imageio-pict:$imageioVersion" // runtimeOnly "com.twelvemonkeys.imageio:imageio-pnm:$imageioVersion" @@ -453,24 +449,18 @@ dependencies { // runtimeOnly "com.twelvemonkeys.imageio:imageio-sgi:$imageioVersion" // runtimeOnly "com.twelvemonkeys.imageio:imageio-tga:$imageioVersion" // runtimeOnly "com.twelvemonkeys.imageio:imageio-thumbsdb:$imageioVersion" - runtimeOnly "com.twelvemonkeys.imageio:imageio-tiff:$imageioVersion" - runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion" // runtimeOnly "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion" // Image metadata extractor implementation "com.drewnoakes:metadata-extractor:2.19.0" - implementation "commons-io:commons-io:2.19.0" - implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8" - //general PDF +// implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8" + // General PDF // https://mvnrepository.com/artifact/com.opencsv/opencsv implementation ("com.opencsv:opencsv:5.11") - - implementation ("org.apache.pdfbox:pdfbox:$pdfboxVersion") +// implementation ("org.apache.pdfbox:pdfbox:$pdfboxVersion") implementation "org.apache.pdfbox:preflight:$pdfboxVersion" - - implementation ("org.apache.pdfbox:xmpbox:$pdfboxVersion") // https://mvnrepository.com/artifact/technology.tabula/tabula @@ -494,7 +484,6 @@ dependencies { // https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17 implementation "com.bucket4j:bucket4j_jdk17-core:8.14.0" implementation "com.fathzer:javaluator:3.0.6" - implementation 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8' developmentOnly("org.springframework.boot:spring-boot-devtools:$springBootVersion") @@ -504,6 +493,7 @@ dependencies { // Mockito (core) testImplementation 'org.mockito:mockito-core:5.18.0' testRuntimeOnly 'org.mockito:mockito-inline:5.2.0' + testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion" } tasks.withType(JavaCompile).configureEach { diff --git a/common/build.gradle b/common/build.gradle index 9b4c93e0d2..b4c51c2f8b 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -30,19 +30,19 @@ dependencyManagement { } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' - implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1' - implementation 'com.fathzer:javaluator:3.0.6' - implementation 'com.posthog.java:posthog:1.2.0' - implementation 'io.github.pixee:java-security-toolkit:1.2.1' - implementation 'org.apache.commons:commons-lang3:3.17.0' - implementation 'com.drewnoakes:metadata-extractor:2.19.0' // Image metadata extractor - implementation 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8' - implementation "org.apache.pdfbox:pdfbox:$pdfboxVersion" - implementation 'jakarta.servlet:jakarta.servlet-api:6.1.0' - implementation 'org.snakeyaml:snakeyaml-engine:2.9' - implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8" + api 'org.springframework.boot:spring-boot-starter-web' + api 'org.springframework.boot:spring-boot-starter-thymeleaf' + api 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1' + api 'com.fathzer:javaluator:3.0.6' + api 'com.posthog.java:posthog:1.2.0' + api 'io.github.pixee:java-security-toolkit:1.2.1' + api 'org.apache.commons:commons-lang3:3.17.0' + api 'com.drewnoakes:metadata-extractor:2.19.0' // Image metadata extractor + api 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8' + api "org.apache.pdfbox:pdfbox:$pdfboxVersion" + api 'jakarta.servlet:jakarta.servlet-api:6.1.0' + api 'org.snakeyaml:snakeyaml-engine:2.9' + api "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8" compileOnly "org.projectlombok:lombok:$lombokVersion" annotationProcessor "org.projectlombok:lombok:$lombokVersion" diff --git a/proprietary/LICENSE-proprietary b/proprietary/LICENSE-proprietary index 9f8fef545c..df9b7b9745 100644 --- a/proprietary/LICENSE-proprietary +++ b/proprietary/LICENSE-proprietary @@ -1,26 +1,54 @@ -Stirling PDF Enterprise Edition (EE) license (the “EE License”) +Stirling PDF User License -Copyright (c) 2025-present Stirling Tools +Copyright (c) 2025 Stirling PDF Inc. -With regard to the Stirling PDF Software: +License Scope & Usage Rights + +Production use of the Stirling PDF Software is only permitted with a valid Stirling PDF User License. + +For purposes of this license, “the Software” refers to the Stirling PDF application and any associated documentation files +provided by Stirling PDF Inc. You or your organization may not use the Software in production, at scale, or for business-critical +processes unless you have agreed to, and remain in compliance with, the Stirling PDF Subscription Terms of Service +(https://www.stirlingpdf.com/terms) or another valid agreement with Stirling PDF, and hold an active User License subscription +covering the appropriate number of licensed users. Trial and Minimal Use -You may use the Software without a subscription for purposes of trial, evaluation, or minimal use, including use by individuals, -organizations, or businesses, provided that: - * The usage is limited in scope (e.g. up to five (5) sessions or uses, or as otherwise defined within the Software); - * You do not modify, distribute, sublicense, or reverse-engineer the Software; - * Any continued use beyond the permitted trial or minimal use scope requires a valid Stirling PDF Enterprise Edition - subscription for the appropriate number of users. +You may use the Software without a paid subscription for the sole purposes of internal trial, evaluation, or minimal use, +provided that: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +* Use is limited to no more than five (5) named users or sessions; +* Use is strictly non-production, for internal testing or evaluation only; +* You do not copy, distribute, sublicense, reverse-engineer, or use the Software in client-facing or commercial contexts. -For all third party components incorporated into the Stirling PDF Software, those -components are licensed under the original license provided by the owner of the -applicable component. +Continued use beyond this scope requires a valid Stirling PDF User License. + +Modifications and Derivative Works + +You may modify the Software only for development or internal testing purposes. Any such modifications or derivative works: + +* May not be deployed in production environments without a valid User License; +* May not be distributed or sublicensed; +* Remain the intellectual property of Stirling PDF and/or its licensors; +* May only be used, copied, or exploited in accordance with the terms of a valid Stirling PDF User License subscription. + +Prohibited Actions + +Unless explicitly permitted by a paid license or separate agreement, you may not: + +* Use the Software in production environments; +* Copy, merge, distribute, sublicense, or sell the Software; +* Remove or alter any licensing or copyright notices; +* Circumvent access restrictions or licensing requirements. + +Third-Party Components + +The Stirling PDF Software may include components subject to separate open source licenses. Such components remain governed by +their original license terms as provided by their respective owners. + +Disclaimer + +THE SOFTWARE IS PROVIDED “AS IS,” WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java index 8d686e4d77..5507580a44 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java @@ -4,6 +4,7 @@ import javax.sql.DataSource; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.jdbc.DatabaseDriver; @@ -54,14 +55,25 @@ public class DatabaseConfig { public DataSource dataSource() throws UnsupportedProviderException { DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); - if (!runningProOrHigher) { + if (!runningProOrHigher || !datasource.isEnableCustomDatabase()) { return useDefaultDataSource(dataSourceBuilder); } - if (!datasource.isEnableCustomDatabase()) { - return useDefaultDataSource(dataSourceBuilder); - } + return useCustomDataSource(dataSourceBuilder); + } + private DataSource useDefaultDataSource(DataSourceBuilder dataSourceBuilder) { + log.info("Using default H2 database"); + + dataSourceBuilder.url(DATASOURCE_DEFAULT_URL) + .driverClassName(DatabaseDriver.H2.getDriverClassName()) + .username(DEFAULT_USERNAME); + + return dataSourceBuilder.build(); + } + + @ConditionalOnBooleanProperty(name = "premium.enabled") + private DataSource useCustomDataSource(DataSourceBuilder dataSourceBuilder) throws UnsupportedProviderException { log.info("Using custom database configuration"); if (!datasource.getCustomDatabaseUrl().isBlank()) { @@ -73,11 +85,11 @@ public class DatabaseConfig { } else { dataSourceBuilder.driverClassName(getDriverClassName(datasource.getType())); dataSourceBuilder.url( - generateCustomDataSourceUrl( - datasource.getType(), - datasource.getHostName(), - datasource.getPort(), - datasource.getName())); + generateCustomDataSourceUrl( + datasource.getType(), + datasource.getHostName(), + datasource.getPort(), + datasource.getName())); } dataSourceBuilder.username(datasource.getUsername()); dataSourceBuilder.password(datasource.getPassword()); @@ -85,16 +97,6 @@ public class DatabaseConfig { return dataSourceBuilder.build(); } - private DataSource useDefaultDataSource(DataSourceBuilder dataSourceBuilder) { - log.info("Using default H2 database"); - - dataSourceBuilder.url(DATASOURCE_DEFAULT_URL) - .driverClassName(DatabaseDriver.H2.getDriverClassName()) - .username(DEFAULT_USERNAME); - - return dataSourceBuilder.build(); - } - /** * Generate the URL the DataSource will use to connect to the database * diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java index c31d42dde4..cec19214a6 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java @@ -6,7 +6,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.Lazy; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; @@ -26,7 +25,7 @@ import org.springframework.security.web.authentication.rememberme.PersistentToke import org.springframework.security.web.csrf.CookieCsrfTokenRepository; import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; import org.springframework.security.web.savedrequest.NullRequestCache; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import stirling.software.common.configuration.AppConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.proprietary.security.CustomAuthenticationFailureHandler; @@ -53,7 +52,6 @@ import stirling.software.proprietary.security.session.SessionPersistentRegistry; @Configuration @EnableWebSecurity @EnableMethodSecurity -@DependsOn("runningProOrHigher") public class SecurityConfiguration { private final CustomUserDetailsService userDetailsService; @@ -167,7 +165,7 @@ public class SecurityConfiguration { http.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache())); http.logout( logout -> - logout.logoutRequestMatcher(new AntPathRequestMatcher("/logout")) + logout.logoutRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher("/logout")) .logoutSuccessHandler( new CustomLogoutSuccessHandler(applicationProperties, appConfig)) .clearAuthentication(true) diff --git a/src/main/java/stirling/software/SPDF/SPDFApplication.java b/src/main/java/stirling/software/SPDF/SPDFApplication.java index b3f6dd0788..91a5354e4a 100644 --- a/src/main/java/stirling/software/SPDF/SPDFApplication.java +++ b/src/main/java/stirling/software/SPDF/SPDFApplication.java @@ -35,7 +35,11 @@ import stirling.software.common.util.UrlUtils; @Slf4j @EnableScheduling @SpringBootApplication( - scanBasePackages = {"stirling.software.common", "stirling.software.SPDF"}, + scanBasePackages = { + "stirling.software.common", + "stirling.software.SPDF", + "stirling.software.proprietary.security" + }, exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class diff --git a/src/main/resources/settings.yml.template b/src/main/resources/settings.yml.template index 2228b73a78..b22e2ab666 100644 --- a/src/main/resources/settings.yml.template +++ b/src/main/resources/settings.yml.template @@ -64,7 +64,6 @@ premium: key: 00000000-0000-0000-0000-000000000000 enabled: true # Enable license key checks for pro/enterprise features proFeatures: - customDatabase: false # Enable database features todo: use only for custom DB SSOAutoLogin: false CustomMetadata: autoUpdateMetadata: false From 149fe8755d303e3fa1202e95d598f4144be1163b Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Wed, 28 May 2025 16:34:59 +0100 Subject: [PATCH 06/15] DOCKER_ENABLE_SECURITY > ADDITIONAL_FEATURES_OFF --- .../workflows/PR-Demo-Comment-with-react.yml | 9 +- .github/workflows/build.yml | 2 + .github/workflows/multiOSReleases.yml | 7 + .github/workflows/push-docker.yml | 1 + .github/workflows/releaseArtifacts.yml | 6 + .github/workflows/sonarqube.yml | 1 + .github/workflows/testdriver.yml | 2 + DeveloperGuide.md | 5 +- Dockerfile | 1 + Dockerfile.fat | 4 +- Dockerfile.ultra-lite | 1 + build.gradle | 6 +- common/gradlew | 251 ------------------ common/gradlew.bat | 94 ------- ...-compose-latest-fat-endpoints-disabled.yml | 1 + ...r-compose-latest-fat-security-postgres.yml | 1 + .../docker-compose-latest-fat-security.yml | 1 + ...ocker-compose-latest-security-with-sso.yml | 1 + .../docker-compose-latest-security.yml | 1 + ...ker-compose-latest-ultra-lite-security.yml | 1 + .../docker-compose-latest-ultra-lite.yml | 1 + exampleYmlFiles/docker-compose-latest.yml | 1 + exampleYmlFiles/test_cicd.yml | 1 + proprietary/gradlew | 251 ------------------ proprietary/gradlew.bat | 94 ------- .../security/oauth2/OAuth2Configuration.java | 5 +- .../security/saml2/SAML2Configuration.java | 3 +- scripts/download-security-jar.sh | 4 +- testing/test.sh | 58 ++-- 29 files changed, 82 insertions(+), 732 deletions(-) delete mode 100755 common/gradlew delete mode 100644 common/gradlew.bat delete mode 100755 proprietary/gradlew delete mode 100644 proprietary/gradlew.bat diff --git a/.github/workflows/PR-Demo-Comment-with-react.yml b/.github/workflows/PR-Demo-Comment-with-react.yml index 67ed61ef11..406568cffc 100644 --- a/.github/workflows/PR-Demo-Comment-with-react.yml +++ b/.github/workflows/PR-Demo-Comment-with-react.yml @@ -84,7 +84,7 @@ jobs: core.setOutput('repository', repository); core.setOutput('ref', pr.head.ref); - + - name: Check for security/login flag id: check-security-flag env: @@ -157,8 +157,10 @@ jobs: run: | if [ "${{ needs.check-comment.outputs.enable_security }}" == "true" ]; then export DOCKER_ENABLE_SECURITY=true + export ADDITIONAL_FEATURES_OFF=false else export DOCKER_ENABLE_SECURITY=false + export ADDITIONAL_FEATURES_OFF=true fi ./gradlew clean build env: @@ -223,7 +225,8 @@ jobs: - /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/config:/configs:rw - /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "${DOCKER_SECURITY}" + DOCKER_ENABLE_SECURITY: "${DOCKER_SECURITY}" # todo: change DOCKER_SECURITY? + ADDITIONAL_FEATURES_OFF: "${DOCKER_SECURITY}" SECURITY_ENABLELOGIN: "${LOGIN_SECURITY}" SYSTEM_DEFAULTLOCALE: en-GB UI_APPNAME: "Stirling-PDF PR#${{ needs.check-comment.outputs.pr_number }}" @@ -250,7 +253,7 @@ jobs: docker-compose pull docker-compose up -d ENDSSH - + # Set output for use in PR comment echo "security_status=${SECURITY_STATUS}" >> $GITHUB_ENV diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 322d52af1c..198a8d4118 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,11 +41,13 @@ jobs: run: ./gradlew clean build env: DOCKER_ENABLE_SECURITY: false + ADDITIONAL_FEATURES_OFF: true - name: Build with Gradle and with spring security run: ./gradlew clean build env: DOCKER_ENABLE_SECURITY: true + ADDITIONAL_FEATURES_OFF: false - name: Upload Test Reports if: always() diff --git a/.github/workflows/multiOSReleases.yml b/.github/workflows/multiOSReleases.yml index dd8f54a9b1..8e0ef38374 100644 --- a/.github/workflows/multiOSReleases.yml +++ b/.github/workflows/multiOSReleases.yml @@ -49,11 +49,16 @@ jobs: strategy: matrix: enable_security: [true, false] + disable_security: [true, false] include: - enable_security: true file_suffix: "-with-login" - enable_security: false file_suffix: "" + - disable_security: true + file_suffix: "" + - disable_security: false + file_suffix: "-with-login" steps: - name: Harden Runner uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 @@ -76,6 +81,7 @@ jobs: run: ./gradlew clean createExe env: DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }} + ADDITIONAL_FEATURES_OFF: ${{ matrix.disable_security }} STIRLING_PDF_DESKTOP_UI: false - name: Rename binaries @@ -172,6 +178,7 @@ jobs: run: ./gradlew build jpackage -x test --info env: DOCKER_ENABLE_SECURITY: false + ADDITIONAL_FEATURES_OFF: true STIRLING_PDF_DESKTOP_UI: true BROWSER_OPEN: true diff --git a/.github/workflows/push-docker.yml b/.github/workflows/push-docker.yml index 7fa1b9afbf..7e9f483f0f 100644 --- a/.github/workflows/push-docker.yml +++ b/.github/workflows/push-docker.yml @@ -38,6 +38,7 @@ jobs: run: ./gradlew clean build env: DOCKER_ENABLE_SECURITY: false + ADDITIONAL_FEATURES_OFF: true STIRLING_PDF_DESKTOP_UI: false - name: Install cosign diff --git a/.github/workflows/releaseArtifacts.yml b/.github/workflows/releaseArtifacts.yml index 71be7b03a0..476ae8a9ca 100644 --- a/.github/workflows/releaseArtifacts.yml +++ b/.github/workflows/releaseArtifacts.yml @@ -14,11 +14,16 @@ jobs: strategy: matrix: enable_security: [true, false] + disable_security: [true, false] include: - enable_security: true file_suffix: "-with-login" - enable_security: false file_suffix: "" + - disable_security: true + file_suffix: "" + - disable_security: false + file_suffix: "-with-login" outputs: version: ${{ steps.versionNumber.outputs.versionNumber }} steps: @@ -43,6 +48,7 @@ jobs: run: ./gradlew clean createExe env: DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }} + ADDITIONAL_FEATURES_OFF: ${{ matrix.disable_security }} STIRLING_PDF_DESKTOP_UI: false - name: Get version number diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml index f9ab27ecc6..4c12b819af 100644 --- a/.github/workflows/sonarqube.yml +++ b/.github/workflows/sonarqube.yml @@ -34,6 +34,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} DOCKER_ENABLE_SECURITY: true + ADDITIONAL_FEATURES_OFF: false STIRLING_PDF_DESKTOP_UI: true run: | ./gradlew clean build sonar \ diff --git a/.github/workflows/testdriver.yml b/.github/workflows/testdriver.yml index 44c2fbe11f..a71293e3ec 100644 --- a/.github/workflows/testdriver.yml +++ b/.github/workflows/testdriver.yml @@ -29,6 +29,7 @@ jobs: run: ./gradlew clean build env: DOCKER_ENABLE_SECURITY: false + ADDITIONAL_FEATURES_OFF: true - name: Set up Docker Buildx uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 @@ -77,6 +78,7 @@ jobs: - /stirling/test-${{ github.sha }}/logs:/logs:rw environment: DOCKER_ENABLE_SECURITY: "false" + ADDITIONAL_FEATURES_OFF: "true" SECURITY_ENABLELOGIN: "false" SYSTEM_DEFAULTLOCALE: en-GB UI_APPNAME: "Stirling-PDF Test" diff --git a/DeveloperGuide.md b/DeveloperGuide.md index 32d480f5c5..675e5b4db2 100644 --- a/DeveloperGuide.md +++ b/DeveloperGuide.md @@ -55,7 +55,7 @@ Stirling-PDF uses Lombok to reduce boilerplate code. Some IDEs, like Eclipse, do Visit the [Lombok website](https://projectlombok.org/setup/) for installation instructions specific to your IDE. 5. Add environment variable -For local testing, you should generally be testing the full 'Security' version of Stirling-PDF. To do this, you must add the environment flag DOCKER_ENABLE_SECURITY=true to your system and/or IDE build/run step. +For local testing, you should generally be testing the full 'Security' version of Stirling-PDF. To do this, you must add the environment flag DOCKER_ENABLE_SECURITY=true or ADDITIONAL_FEATURES_OFF=false to your system and/or IDE build/run step. ## 4. Project Structure @@ -142,6 +142,7 @@ services: - /stirling/latest/logs:/logs:rw environment: DOCKER_ENABLE_SECURITY: "true" + ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" PUID: 1002 PGID: 1002 @@ -171,6 +172,7 @@ Stirling-PDF uses different Docker images for various configurations. The build ```bash export DOCKER_ENABLE_SECURITY=false # or true for security-enabled builds + export ADDITIONAL_FEATURES_OFF=true # or false for security-enabled builds ``` 2. Build the project with Gradle: @@ -197,6 +199,7 @@ Stirling-PDF uses different Docker images for various configurations. The build ```bash export DOCKER_ENABLE_SECURITY=true + export ADDITIONAL_FEATURES_OFF=false docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-fat -f ./Dockerfile.fat . ``` diff --git a/Dockerfile b/Dockerfile index f078e78acb..bf302116bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,6 +24,7 @@ LABEL org.opencontainers.image.keywords="PDF, manipulation, merge, split, conver # Set Environment Variables ENV DOCKER_ENABLE_SECURITY=false \ + ADDITIONAL_FEATURES_OFF=true \ VERSION_TAG=$VERSION_TAG \ JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \ JAVA_CUSTOM_OPTS="" \ diff --git a/Dockerfile.fat b/Dockerfile.fat index f442e60c87..203af02da6 100644 --- a/Dockerfile.fat +++ b/Dockerfile.fat @@ -15,8 +15,9 @@ WORKDIR /app # Copy the entire project to the working directory COPY . . -# Build the application with DOCKER_ENABLE_SECURITY=false +# Build the application with DOCKER_ENABLE_SECURITY=true/ADDITIONAL_FEATURES_OFF=false RUN DOCKER_ENABLE_SECURITY=true \ + ADDITIONAL_FEATURES_OFF=false \ STIRLING_PDF_DESKTOP_UI=false \ ./gradlew clean build -x spotlessApply -x spotlessCheck -x test -x sonarqube @@ -33,6 +34,7 @@ ARG VERSION_TAG # Set Environment Variables ENV DOCKER_ENABLE_SECURITY=false \ + ADDITIONAL_FEATURES_OFF=true \ VERSION_TAG=$VERSION_TAG \ JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \ JAVA_CUSTOM_OPTS="" \ diff --git a/Dockerfile.ultra-lite b/Dockerfile.ultra-lite index ec0ab55aad..a30c45d481 100644 --- a/Dockerfile.ultra-lite +++ b/Dockerfile.ultra-lite @@ -5,6 +5,7 @@ ARG VERSION_TAG # Set Environment Variables ENV DOCKER_ENABLE_SECURITY=false \ + ADDITIONAL_FEATURES_OFF=true \ HOME=/home/stirlingpdfuser \ VERSION_TAG=$VERSION_TAG \ JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \ diff --git a/build.gradle b/build.gradle index c6a2e74be6..832a0f4a5e 100644 --- a/build.gradle +++ b/build.gradle @@ -51,7 +51,7 @@ licenseReport { sourceSets { main { java { - if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") { + if (System.getenv("DOCKER_ENABLE_SECURITY") == "false" || System.getenv("ADDITIONAL_FEATURES_OFF") == "true") { exclude "stirling/software/proprietary/security/**" } @@ -64,7 +64,7 @@ sourceSets { test { java { - if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") { + if (System.getenv("DOCKER_ENABLE_SECURITY") == "false" || System.getenv("ADDITIONAL_FEATURES_OFF") == "true") { exclude "stirling/software/proprietary/security/**" } @@ -426,7 +426,7 @@ dependencies { implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1' implementation 'org.snakeyaml:snakeyaml-engine:2.9' - if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") { + if (System.getenv("DOCKER_ENABLE_SECURITY") != "false" || System.getenv("ADDITIONAL_FEATURES_OFF") == "false") { implementation project(':proprietary') } diff --git a/common/gradlew b/common/gradlew deleted file mode 100755 index 23d15a9367..0000000000 --- a/common/gradlew +++ /dev/null @@ -1,251 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH="\\\"\\\"" - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/common/gradlew.bat b/common/gradlew.bat deleted file mode 100644 index db3a6ac207..0000000000 --- a/common/gradlew.bat +++ /dev/null @@ -1,94 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH= - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml b/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml index f36cd5bc74..63b0a7467b 100644 --- a/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml +++ b/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml @@ -21,6 +21,7 @@ services: - ../testing/allEndpointsRemovedSettings.yml:/configs/settings.yml:rw environment: DOCKER_ENABLE_SECURITY: "true" + ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "false" PUID: 1002 PGID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml b/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml index c04da19123..318065e055 100644 --- a/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml +++ b/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml @@ -21,6 +21,7 @@ services: - ./stirling/latest/logs:/logs:rw environment: DOCKER_ENABLE_SECURITY: "true" + ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "false" PUID: 1002 PGID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-fat-security.yml b/exampleYmlFiles/docker-compose-latest-fat-security.yml index d9e4fa5a93..8d9ebeff49 100644 --- a/exampleYmlFiles/docker-compose-latest-fat-security.yml +++ b/exampleYmlFiles/docker-compose-latest-fat-security.yml @@ -19,6 +19,7 @@ services: - ./stirling/latest/logs:/logs:rw environment: DOCKER_ENABLE_SECURITY: "true" + ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "false" PUID: 1002 PGID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-security-with-sso.yml b/exampleYmlFiles/docker-compose-latest-security-with-sso.yml index 1514dd7d8e..36cbfe868a 100644 --- a/exampleYmlFiles/docker-compose-latest-security-with-sso.yml +++ b/exampleYmlFiles/docker-compose-latest-security-with-sso.yml @@ -19,6 +19,7 @@ services: - /stirling/latest/logs:/logs:rw environment: DOCKER_ENABLE_SECURITY: "true" + ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" SECURITY_OAUTH2_ENABLED: "true" SECURITY_OAUTH2_AUTOCREATEUSER: "true" # This is set to true to allow auto-creation of non-existing users in Stirling-PDF diff --git a/exampleYmlFiles/docker-compose-latest-security.yml b/exampleYmlFiles/docker-compose-latest-security.yml index ccd3a41c6a..d6d90bf0ae 100644 --- a/exampleYmlFiles/docker-compose-latest-security.yml +++ b/exampleYmlFiles/docker-compose-latest-security.yml @@ -19,6 +19,7 @@ services: - ./stirling/latest/logs:/logs:rw environment: DOCKER_ENABLE_SECURITY: "true" + ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" PUID: 1002 PGID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml b/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml index c59713b716..b3cb57cd10 100644 --- a/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml +++ b/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml @@ -19,6 +19,7 @@ services: - /stirling/latest/logs:/logs:rw environment: DOCKER_ENABLE_SECURITY: "true" + ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" SYSTEM_DEFAULTLOCALE: en-US UI_APPNAME: Stirling-PDF-Lite diff --git a/exampleYmlFiles/docker-compose-latest-ultra-lite.yml b/exampleYmlFiles/docker-compose-latest-ultra-lite.yml index 6148f7251a..f6c1b703a4 100644 --- a/exampleYmlFiles/docker-compose-latest-ultra-lite.yml +++ b/exampleYmlFiles/docker-compose-latest-ultra-lite.yml @@ -18,6 +18,7 @@ services: - /stirling/latest/logs:/logs:rw environment: DOCKER_ENABLE_SECURITY: "false" + ADDITIONAL_FEATURES_OFF: "true" SECURITY_ENABLELOGIN: "false" SYSTEM_DEFAULTLOCALE: en-US UI_APPNAME: Stirling-PDF-Ultra-lite diff --git a/exampleYmlFiles/docker-compose-latest.yml b/exampleYmlFiles/docker-compose-latest.yml index 51266ee8bc..3a296b84ab 100644 --- a/exampleYmlFiles/docker-compose-latest.yml +++ b/exampleYmlFiles/docker-compose-latest.yml @@ -19,6 +19,7 @@ services: - /stirling/latest/logs:/logs:rw environment: DOCKER_ENABLE_SECURITY: "false" + ADDITIONAL_FEATURES_OFF: "true" SECURITY_ENABLELOGIN: "false" LANGS: "en_GB,en_US,ar_AR,de_DE,fr_FR,es_ES,zh_CN,zh_TW,ca_CA,it_IT,sv_SE,pl_PL,ro_RO,ko_KR,pt_BR,ru_RU,el_GR,hi_IN,hu_HU,tr_TR,id_ID" SYSTEM_DEFAULTLOCALE: en-US diff --git a/exampleYmlFiles/test_cicd.yml b/exampleYmlFiles/test_cicd.yml index eebb50f2a8..f92c80d8fa 100644 --- a/exampleYmlFiles/test_cicd.yml +++ b/exampleYmlFiles/test_cicd.yml @@ -19,6 +19,7 @@ services: - /stirling/latest/logs:/logs:rw environment: DOCKER_ENABLE_SECURITY: "true" + ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" PUID: 1002 PGID: 1002 diff --git a/proprietary/gradlew b/proprietary/gradlew deleted file mode 100755 index 23d15a9367..0000000000 --- a/proprietary/gradlew +++ /dev/null @@ -1,251 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH="\\\"\\\"" - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/proprietary/gradlew.bat b/proprietary/gradlew.bat deleted file mode 100644 index db3a6ac207..0000000000 --- a/proprietary/gradlew.bat +++ /dev/null @@ -1,94 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH= - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java index a0f11c5b21..cb2771cc07 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; @@ -36,8 +37,7 @@ import static stirling.software.common.util.ValidationUtils.isStringEmpty; @Slf4j @Configuration -@ConditionalOnProperty(value = "security.oauth2.enabled", havingValue = "true") -@ConditionalOnExpression("${docker.enable.security:true}") // todo: change this +@ConditionalOnBooleanProperty("security.oauth2.enabled") public class OAuth2Configuration { public static final String REDIRECT_URI_PATH = "{baseUrl}/login/oauth2/code/"; @@ -52,7 +52,6 @@ public class OAuth2Configuration { } @Bean - @ConditionalOnProperty(value = "security.oauth2.enabled", havingValue = "true") public ClientRegistrationRepository clientRegistrationRepository() throws NoProviderFoundException { List registrations = new ArrayList<>(); diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java index 8482b87538..836419ea0f 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java @@ -7,6 +7,7 @@ import java.util.UUID; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.opensaml.saml.saml2.core.AuthnRequest; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -25,8 +26,8 @@ import stirling.software.common.model.ApplicationProperties.Security.SAML2; @Configuration @Slf4j -@ConditionalOnProperty(value = "security.saml2.enabled", havingValue = "true") @RequiredArgsConstructor +@ConditionalOnBooleanProperty("security.saml2.enabled") public class SAML2Configuration { private final ApplicationProperties applicationProperties; diff --git a/scripts/download-security-jar.sh b/scripts/download-security-jar.sh index df03bf1d0a..8216179fa0 100644 --- a/scripts/download-security-jar.sh +++ b/scripts/download-security-jar.sh @@ -1,6 +1,6 @@ -echo "Running Stirling PDF with DOCKER_ENABLE_SECURITY=${DOCKER_ENABLE_SECURITY} and VERSION_TAG=${VERSION_TAG}" +echo "Running Stirling PDF with ADDITIONAL_FEATURES_OFF=${ADDITIONAL_FEATURES_OFF} and VERSION_TAG=${VERSION_TAG}" # Check for DOCKER_ENABLE_SECURITY and download the appropriate JAR if required -if [ "$DOCKER_ENABLE_SECURITY" = "true" ] && [ "$VERSION_TAG" != "alpha" ]; then +if [ "$DOCKER_ENABLE_SECURITY" = "true" ] || [ "$ADDITIONAL_FEATURES_OFF" = "false" ] && [ "$VERSION_TAG" != "alpha" ]; then if [ ! -f app-security.jar ]; then echo "Trying to download from: https://files.stirlingpdf.com/v$VERSION_TAG/Stirling-PDF-with-login.jar" curl -L -o app-security.jar https://files.stirlingpdf.com/v$VERSION_TAG/Stirling-PDF-with-login.jar diff --git a/testing/test.sh b/testing/test.sh index 5c4455dc21..f1169ec170 100644 --- a/testing/test.sh +++ b/testing/test.sh @@ -43,7 +43,7 @@ check_health() { capture_file_list() { local container_name=$1 local output_file=$2 - + echo "Capturing file list from $container_name..." # Get all files in one command, output directly from Docker to avoid path issues # Skip proc, sys, dev, and the specified LibreOffice config directory @@ -60,12 +60,12 @@ capture_file_list() { -not -path '*/tmp/lu*' \ -not -path '*/tmp/tmp*' \ 2>/dev/null | xargs -I{} sh -c 'stat -c \"%n %s %Y\" \"{}\" 2>/dev/null || true' | sort" > "$output_file" - + # Check if the output file has content if [ ! -s "$output_file" ]; then echo "WARNING: Failed to capture file list or container returned empty list" echo "Trying alternative approach..." - + # Alternative simpler approach - just get paths as a fallback docker exec $container_name sh -c "find / -type f \ -not -path '*/proc/*' \ @@ -79,14 +79,14 @@ capture_file_list() { -not -path '*/tmp/lu*' \ -not -path '*/tmp/tmp*' \ 2>/dev/null | sort" > "$output_file" - + if [ ! -s "$output_file" ]; then echo "ERROR: All attempts to capture file list failed" # Create a dummy entry to prevent diff errors echo "NO_FILES_FOUND 0 0" > "$output_file" fi fi - + echo "File list captured to $output_file" } @@ -96,24 +96,24 @@ compare_file_lists() { local after_file=$2 local diff_file=$3 local container_name=$4 # Added container_name parameter - + echo "Comparing file lists..." - + # Check if files exist and have content if [ ! -s "$before_file" ] || [ ! -s "$after_file" ]; then echo "WARNING: One or both file lists are empty." - + if [ ! -s "$before_file" ]; then echo "Before file is empty: $before_file" fi - + if [ ! -s "$after_file" ]; then echo "After file is empty: $after_file" fi - + # Create empty diff file > "$diff_file" - + # Check if we at least have the after file to look for temp files if [ -s "$after_file" ]; then echo "Checking for temp files in the after snapshot..." @@ -128,23 +128,23 @@ compare_file_lists() { echo "No temporary files found in the after snapshot." fi fi - + return 0 fi - + # Both files exist and have content, proceed with diff diff "$before_file" "$after_file" > "$diff_file" - + if [ -s "$diff_file" ]; then echo "Detected changes in files:" cat "$diff_file" - + # Extract only added files (lines starting with ">") grep "^>" "$diff_file" > "${diff_file}.added" || true if [ -s "${diff_file}.added" ]; then echo "New files created during test:" cat "${diff_file}.added" | sed 's/^> //' - + # Check for tmp files grep -i "tmp\|temp" "${diff_file}.added" > "${diff_file}.tmp" || true if [ -s "${diff_file}.tmp" ]; then @@ -155,7 +155,7 @@ compare_file_lists() { return 1 fi fi - + # Extract only removed files (lines starting with "<") grep "^<" "$diff_file" > "${diff_file}.removed" || true if [ -s "${diff_file}.removed" ]; then @@ -165,7 +165,7 @@ compare_file_lists() { else echo "No file changes detected during test." fi - + return 0 } @@ -215,6 +215,7 @@ main() { export DOCKER_CLI_EXPERIMENTAL=enabled export COMPOSE_DOCKER_CLI_BUILD=0 export DOCKER_ENABLE_SECURITY=false + export ADDITIONAL_FEATURES_OFF=true # Run the gradlew build command and check if it fails if ! ./gradlew clean build; then echo "Gradle build failed with security disabled, exiting script." @@ -243,6 +244,7 @@ main() { # docker-compose -f "./exampleYmlFiles/docker-compose-latest.yml" down export DOCKER_ENABLE_SECURITY=true + export ADDITIONAL_FEATURES_OFF=false # Run the gradlew build command and check if it fails if ! ./gradlew clean build; then echo "Gradle build failed with security enabled, exiting script." @@ -282,27 +284,27 @@ main() { # Create directory for file snapshots if it doesn't exist SNAPSHOT_DIR="$PROJECT_ROOT/testing/file_snapshots" mkdir -p "$SNAPSHOT_DIR" - + # Capture file list before running behave tests BEFORE_FILE="$SNAPSHOT_DIR/files_before_behave.txt" AFTER_FILE="$SNAPSHOT_DIR/files_after_behave.txt" DIFF_FILE="$SNAPSHOT_DIR/files_diff.txt" - + # Define container name variable for consistency CONTAINER_NAME="Stirling-PDF-Security-Fat-with-login" - + capture_file_list "$CONTAINER_NAME" "$BEFORE_FILE" - + cd "testing/cucumber" if python -m behave; then # Wait 10 seconds before capturing the file list after tests echo "Waiting 5 seconds for any file operations to complete..." sleep 5 - + # Capture file list after running behave tests cd "$PROJECT_ROOT" capture_file_list "$CONTAINER_NAME" "$AFTER_FILE" - + # Compare file lists if compare_file_lists "$BEFORE_FILE" "$AFTER_FILE" "$DIFF_FILE" "$CONTAINER_NAME"; then echo "No unexpected temporary files found." @@ -311,19 +313,19 @@ main() { echo "WARNING: Unexpected temporary files detected after behave tests!" failed_tests+=("Stirling-PDF-Regression-Temp-Files") fi - + passed_tests+=("Stirling-PDF-Regression") else failed_tests+=("Stirling-PDF-Regression") echo "Printing docker logs of failed regression" docker logs "$CONTAINER_NAME" echo "Printed docker logs of failed regression" - + # Still capture file list after failure for analysis # Wait 10 seconds before capturing the file list echo "Waiting 5 seconds before capturing file list..." sleep 10 - + cd "$PROJECT_ROOT" capture_file_list "$CONTAINER_NAME" "$AFTER_FILE" compare_file_lists "$BEFORE_FILE" "$AFTER_FILE" "$DIFF_FILE" "$CONTAINER_NAME" @@ -372,4 +374,4 @@ main() { fi } -main \ No newline at end of file +main From 275039015df18092378d2fd35d5ea114ed1a990f Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Fri, 30 May 2025 18:09:02 +0100 Subject: [PATCH 07/15] updating LICENSE-proprietary --- proprietary/LICENSE-proprietary | 7 ++----- .../software/SPDF/EE/KeygenLicenseVerifier.java | 10 +++++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/proprietary/LICENSE-proprietary b/proprietary/LICENSE-proprietary index df9b7b9745..d268556808 100644 --- a/proprietary/LICENSE-proprietary +++ b/proprietary/LICENSE-proprietary @@ -14,11 +14,8 @@ covering the appropriate number of licensed users. Trial and Minimal Use -You may use the Software without a paid subscription for the sole purposes of internal trial, evaluation, or minimal use, -provided that: - -* Use is limited to no more than five (5) named users or sessions; -* Use is strictly non-production, for internal testing or evaluation only; +You may use the Software without a paid subscription for the sole purposes of internal trial, evaluation, or minimal use, provided that: +* Use is limited to the capabilities and restrictions defined by the Software itself; * You do not copy, distribute, sublicense, reverse-engineer, or use the Software in client-facing or commercial contexts. Continued use beyond this scope requires a valid Stirling PDF User License. diff --git a/src/main/java/stirling/software/SPDF/EE/KeygenLicenseVerifier.java b/src/main/java/stirling/software/SPDF/EE/KeygenLicenseVerifier.java index c760a83c9c..e92e048e97 100644 --- a/src/main/java/stirling/software/SPDF/EE/KeygenLicenseVerifier.java +++ b/src/main/java/stirling/software/SPDF/EE/KeygenLicenseVerifier.java @@ -520,7 +520,7 @@ public class KeygenLicenseVerifier { HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - log.info("ValidateLicenseResponse body: {}", response.body()); + log.debug("ValidateLicenseResponse body: {}", response.body()); JsonNode jsonResponse = objectMapper.readTree(response.body()); if (response.statusCode() == 200) { JsonNode metaNode = jsonResponse.path("meta"); @@ -529,9 +529,9 @@ public class KeygenLicenseVerifier { String detail = metaNode.path("detail").asText(); String code = metaNode.path("code").asText(); - log.info("License validity: " + isValid); - log.info("Validation detail: " + detail); - log.info("Validation code: " + code); + log.info("License validity: {}", isValid); + log.info("Validation detail: {}", detail); + log.info("Validation code: {}", code); // Check if the license itself has floating attribute JsonNode licenseAttrs = jsonResponse.path("data").path("attributes"); @@ -595,7 +595,7 @@ public class KeygenLicenseVerifier { .path("isEnterprise") .asBoolean(false); - log.info(applicationProperties.toString()); + log.debug(applicationProperties.toString()); } else { log.error("Error validating license. Status code: {}", response.statusCode()); From 392a10a8c1ce093a1b65478cfad65ad71686d57c Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Mon, 2 Jun 2025 14:39:55 +0100 Subject: [PATCH 08/15] added back activeSecurity bean --- .../software/common/configuration/AppConfig.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/stirling/software/common/configuration/AppConfig.java b/common/src/main/java/stirling/software/common/configuration/AppConfig.java index 732a3b174a..f6b8b2d454 100644 --- a/common/src/main/java/stirling/software/common/configuration/AppConfig.java +++ b/common/src/main/java/stirling/software/common/configuration/AppConfig.java @@ -10,6 +10,7 @@ import java.util.Properties; import java.util.function.Predicate; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; @@ -146,8 +147,16 @@ public class AppConfig { } } - @ConditionalOnMissingClass("stirling.software.SPDF.config.security.SecurityConfiguration") @Bean(name = "activeSecurity") + @ConditionalOnClass( + name = "stirling.software.proprietary.security.configuration.SecurityConfiguration") + public boolean activeSecurity() { + return true; + } + + @Bean(name = "missingActiveSecurity") + @ConditionalOnMissingClass( + "stirling.software.proprietary.security.configuration.SecurityConfiguration") public boolean missingActiveSecurity() { return false; } From 5a50947e5eadbfe671f2683d1a4562634754d580 Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Mon, 2 Jun 2025 15:04:27 +0100 Subject: [PATCH 09/15] updated build.gradle --- .vscode/settings.json | 3 +++ build.gradle | 1 + proprietary/build.gradle | 24 ++++++++++++------------ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index e45bc4dd98..f759730f26 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -50,8 +50,10 @@ ".vscode/", "bin/", "common/bin/", + "proprietary/bin/", "build/", "common/build/", + "proprietary/build/", "configs/", "customFiles/", "docs/", @@ -66,6 +68,7 @@ ".gitattributes", ".gitignore", "common/.gitignore", + "proprietary/.gitignore", ".pre-commit-config.yaml", ], // Enables signature help in Java. diff --git a/build.gradle b/build.gradle index 832a0f4a5e..87c603617d 100644 --- a/build.gradle +++ b/build.gradle @@ -354,6 +354,7 @@ spotless { java { target sourceSets.main.allJava target project(':common').sourceSets.main.allJava + target project(':proprietary').sourceSets.main.allJava googleJavaFormat("1.27.0").aosp().reorderImports(false) diff --git a/proprietary/build.gradle b/proprietary/build.gradle index 5c91d21ba6..331476f570 100644 --- a/proprietary/build.gradle +++ b/proprietary/build.gradle @@ -26,17 +26,17 @@ dependencyManagement { dependencies { implementation project(':common') - implementation 'org.springframework:spring-jdbc' - implementation 'org.springframework:spring-webmvc' - implementation 'org.springframework.session:spring-session-core' - implementation "org.springframework.security:spring-security-core:$springSecuritySamlVersion" - implementation "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion" - implementation 'org.springframework.boot:spring-boot-starter-jetty' - implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' - implementation 'org.springframework.boot:spring-boot-starter-mail' - implementation 'io.swagger.core.v3:swagger-core-jakarta:2.2.30' + api 'org.springframework:spring-jdbc' + api 'org.springframework:spring-webmvc' + api 'org.springframework.session:spring-session-core' + api "org.springframework.security:spring-security-core:$springSecuritySamlVersion" + api "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion" + api 'org.springframework.boot:spring-boot-starter-jetty' + api 'org.springframework.boot:spring-boot-starter-security' + api 'org.springframework.boot:spring-boot-starter-data-jpa' + api 'org.springframework.boot:spring-boot-starter-oauth2-client' + api 'org.springframework.boot:spring-boot-starter-mail' + api 'io.swagger.core.v3:swagger-core-jakarta:2.2.30' implementation 'com.bucket4j:bucket4j_jdk17-core:8.14.0' // https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17 @@ -44,7 +44,7 @@ dependencies { implementation 'io.github.pixee:java-security-toolkit:1.2.1' implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.3.RELEASE' - implementation 'io.micrometer:micrometer-registry-prometheus' + api 'io.micrometer:micrometer-registry-prometheus' implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5' runtimeOnly 'com.h2database:h2:2.3.232' // Don't upgrade h2database runtimeOnly 'org.postgresql:postgresql:42.7.5' From 41cd7d8f47172d9924c9a746a8df95780710877c Mon Sep 17 00:00:00 2001 From: DarioGii Date: Mon, 2 Jun 2025 22:45:59 +0100 Subject: [PATCH 10/15] removing DOCKER_ENABLE_SECURITY flag --- .../workflows/PR-Demo-Comment-with-react.yml | 3 - .github/workflows/build.yml | 2 - .github/workflows/multiOSReleases.yml | 2 - .github/workflows/push-docker.yml | 1 - .github/workflows/releaseArtifacts.yml | 1 - .github/workflows/sonarqube.yml | 1 - .github/workflows/testdriver.yml | 2 - DeveloperGuide.md | 5 +- Dockerfile | 3 +- Dockerfile.fat | 8 +- Dockerfile.ultra-lite | 3 +- build.gradle | 20 +- ...-compose-latest-fat-endpoints-disabled.yml | 1 - ...r-compose-latest-fat-security-postgres.yml | 1 - .../docker-compose-latest-fat-security.yml | 1 - ...ocker-compose-latest-security-with-sso.yml | 1 - .../docker-compose-latest-security.yml | 1 - ...ker-compose-latest-ultra-lite-security.yml | 1 - .../docker-compose-latest-ultra-lite.yml | 1 - exampleYmlFiles/docker-compose-latest.yml | 1 - exampleYmlFiles/test_cicd.yml | 1 - .../CustomAuthenticationFailureHandler.java | 12 +- .../CustomAuthenticationSuccessHandler.java | 12 +- .../security/CustomLogoutSuccessHandler.java | 20 +- .../security/InitialSecuritySetup.java | 10 +- .../security/RateLimitResetScheduler.java | 4 +- .../configuration/DatabaseConfig.java | 27 +- .../security/configuration/MailConfig.java | 1 + .../configuration/SecurityConfiguration.java | 330 +++++++++--------- .../controller/api/DatabaseController.java | 1 + .../controller/api/UserController.java | 6 +- .../controller/web/AccountWebController.java | 2 +- .../security/database/ScheduledTasks.java | 5 +- .../repository/AuthorityRepository.java | 1 + .../repository/JPATokenRepositoryImpl.java | 1 + .../repository/PersistentLoginRepository.java | 1 + .../repository/SessionRepository.java | 5 +- .../database/repository/UserRepository.java | 1 + .../security/filter/FirstLoginFilter.java | 22 +- .../security/filter/IPRateLimitingFilter.java | 9 +- .../filter/UserAuthenticationFilter.java | 14 +- .../filter/UserBasedRateLimitingFilter.java | 20 +- .../proprietary/security/model/User.java | 1 + .../proprietary/security/model/api/Email.java | 1 + ...tomOAuth2AuthenticationFailureHandler.java | 11 +- ...tomOAuth2AuthenticationSuccessHandler.java | 14 +- .../security/oauth2/OAuth2Configuration.java | 15 +- .../security/saml2/CertificateUtils.java | 1 + .../CustomSaml2AuthenticatedPrincipal.java | 1 + ...stomSaml2AuthenticationFailureHandler.java | 9 +- ...stomSaml2AuthenticationSuccessHandler.java | 16 +- ...mSaml2ResponseAuthenticationConverter.java | 7 +- .../security/saml2/SAML2Configuration.java | 10 +- .../service/AppUpdateAuthService.java | 5 +- .../service/CustomOAuth2UserService.java | 5 +- .../service/CustomUserDetailsService.java | 5 +- .../security/service/DatabaseService.java | 28 +- .../security/service/LoginAttemptService.java | 8 +- .../security/service/UserService.java | 16 +- .../session/CustomHttpSessionListener.java | 6 +- .../session/SessionPersistentRegistry.java | 8 +- .../session/SessionRegistryConfig.java | 4 +- .../security/session/SessionScheduled.java | 4 +- scripts/download-security-jar.sh | 4 +- testing/test.sh | 2 - 65 files changed, 415 insertions(+), 330 deletions(-) diff --git a/.github/workflows/PR-Demo-Comment-with-react.yml b/.github/workflows/PR-Demo-Comment-with-react.yml index 406568cffc..7863163656 100644 --- a/.github/workflows/PR-Demo-Comment-with-react.yml +++ b/.github/workflows/PR-Demo-Comment-with-react.yml @@ -156,10 +156,8 @@ jobs: - name: Run Gradle Command run: | if [ "${{ needs.check-comment.outputs.enable_security }}" == "true" ]; then - export DOCKER_ENABLE_SECURITY=true export ADDITIONAL_FEATURES_OFF=false else - export DOCKER_ENABLE_SECURITY=false export ADDITIONAL_FEATURES_OFF=true fi ./gradlew clean build @@ -225,7 +223,6 @@ jobs: - /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/config:/configs:rw - /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "${DOCKER_SECURITY}" # todo: change DOCKER_SECURITY? ADDITIONAL_FEATURES_OFF: "${DOCKER_SECURITY}" SECURITY_ENABLELOGIN: "${LOGIN_SECURITY}" SYSTEM_DEFAULTLOCALE: en-GB diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 198a8d4118..797a1bca0c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,13 +40,11 @@ jobs: - name: Build with Gradle and no spring security run: ./gradlew clean build env: - DOCKER_ENABLE_SECURITY: false ADDITIONAL_FEATURES_OFF: true - name: Build with Gradle and with spring security run: ./gradlew clean build env: - DOCKER_ENABLE_SECURITY: true ADDITIONAL_FEATURES_OFF: false - name: Upload Test Reports diff --git a/.github/workflows/multiOSReleases.yml b/.github/workflows/multiOSReleases.yml index 8e0ef38374..d10d8e8b69 100644 --- a/.github/workflows/multiOSReleases.yml +++ b/.github/workflows/multiOSReleases.yml @@ -80,7 +80,6 @@ jobs: - name: Generate jar (With Security=${{ matrix.enable_security }}) run: ./gradlew clean createExe env: - DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }} ADDITIONAL_FEATURES_OFF: ${{ matrix.disable_security }} STIRLING_PDF_DESKTOP_UI: false @@ -177,7 +176,6 @@ jobs: - name: Build Installer run: ./gradlew build jpackage -x test --info env: - DOCKER_ENABLE_SECURITY: false ADDITIONAL_FEATURES_OFF: true STIRLING_PDF_DESKTOP_UI: true BROWSER_OPEN: true diff --git a/.github/workflows/push-docker.yml b/.github/workflows/push-docker.yml index 7e9f483f0f..210007c728 100644 --- a/.github/workflows/push-docker.yml +++ b/.github/workflows/push-docker.yml @@ -37,7 +37,6 @@ jobs: - name: Run Gradle Command run: ./gradlew clean build env: - DOCKER_ENABLE_SECURITY: false ADDITIONAL_FEATURES_OFF: true STIRLING_PDF_DESKTOP_UI: false diff --git a/.github/workflows/releaseArtifacts.yml b/.github/workflows/releaseArtifacts.yml index 476ae8a9ca..09ad89312c 100644 --- a/.github/workflows/releaseArtifacts.yml +++ b/.github/workflows/releaseArtifacts.yml @@ -47,7 +47,6 @@ jobs: - name: Generate jar (With Security=${{ matrix.enable_security }}) run: ./gradlew clean createExe env: - DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }} ADDITIONAL_FEATURES_OFF: ${{ matrix.disable_security }} STIRLING_PDF_DESKTOP_UI: false diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml index 4c12b819af..5509d74bc0 100644 --- a/.github/workflows/sonarqube.yml +++ b/.github/workflows/sonarqube.yml @@ -33,7 +33,6 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - DOCKER_ENABLE_SECURITY: true ADDITIONAL_FEATURES_OFF: false STIRLING_PDF_DESKTOP_UI: true run: | diff --git a/.github/workflows/testdriver.yml b/.github/workflows/testdriver.yml index a71293e3ec..27a8255a48 100644 --- a/.github/workflows/testdriver.yml +++ b/.github/workflows/testdriver.yml @@ -28,7 +28,6 @@ jobs: - name: Build with Gradle run: ./gradlew clean build env: - DOCKER_ENABLE_SECURITY: false ADDITIONAL_FEATURES_OFF: true - name: Set up Docker Buildx @@ -77,7 +76,6 @@ jobs: - /stirling/test-${{ github.sha }}/config:/configs:rw - /stirling/test-${{ github.sha }}/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "false" ADDITIONAL_FEATURES_OFF: "true" SECURITY_ENABLELOGIN: "false" SYSTEM_DEFAULTLOCALE: en-GB diff --git a/DeveloperGuide.md b/DeveloperGuide.md index 675e5b4db2..cb4c4827aa 100644 --- a/DeveloperGuide.md +++ b/DeveloperGuide.md @@ -55,7 +55,7 @@ Stirling-PDF uses Lombok to reduce boilerplate code. Some IDEs, like Eclipse, do Visit the [Lombok website](https://projectlombok.org/setup/) for installation instructions specific to your IDE. 5. Add environment variable -For local testing, you should generally be testing the full 'Security' version of Stirling-PDF. To do this, you must add the environment flag DOCKER_ENABLE_SECURITY=true or ADDITIONAL_FEATURES_OFF=false to your system and/or IDE build/run step. +For local testing, you should generally be testing the full 'Security' version of Stirling-PDF. To do this, you must add the environment flag ADDITIONAL_FEATURES_OFF=false to your system and/or IDE build/run step. ## 4. Project Structure @@ -141,7 +141,6 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" PUID: 1002 @@ -171,7 +170,6 @@ Stirling-PDF uses different Docker images for various configurations. The build 1. Set the security environment variable: ```bash - export DOCKER_ENABLE_SECURITY=false # or true for security-enabled builds export ADDITIONAL_FEATURES_OFF=true # or false for security-enabled builds ``` @@ -198,7 +196,6 @@ Stirling-PDF uses different Docker images for various configurations. The build For the fat version (with security enabled): ```bash - export DOCKER_ENABLE_SECURITY=true export ADDITIONAL_FEATURES_OFF=false docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-fat -f ./Dockerfile.fat . ``` diff --git a/Dockerfile b/Dockerfile index bf302116bf..ad8f7c5903 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,8 +23,7 @@ LABEL org.opencontainers.image.version="${VERSION_TAG}" LABEL org.opencontainers.image.keywords="PDF, manipulation, merge, split, convert, OCR, watermark" # Set Environment Variables -ENV DOCKER_ENABLE_SECURITY=false \ - ADDITIONAL_FEATURES_OFF=true \ +ENV ADDITIONAL_FEATURES_OFF=true \ VERSION_TAG=$VERSION_TAG \ JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \ JAVA_CUSTOM_OPTS="" \ diff --git a/Dockerfile.fat b/Dockerfile.fat index 203af02da6..e742dd43b8 100644 --- a/Dockerfile.fat +++ b/Dockerfile.fat @@ -15,9 +15,8 @@ WORKDIR /app # Copy the entire project to the working directory COPY . . -# Build the application with DOCKER_ENABLE_SECURITY=true/ADDITIONAL_FEATURES_OFF=false -RUN DOCKER_ENABLE_SECURITY=true \ - ADDITIONAL_FEATURES_OFF=false \ +# Build the application with ADDITIONAL_FEATURES_OFF=false +RUN ADDITIONAL_FEATURES_OFF=false \ STIRLING_PDF_DESKTOP_UI=false \ ./gradlew clean build -x spotlessApply -x spotlessCheck -x test -x sonarqube @@ -33,8 +32,7 @@ COPY --from=build /app/build/libs/*.jar app.jar ARG VERSION_TAG # Set Environment Variables -ENV DOCKER_ENABLE_SECURITY=false \ - ADDITIONAL_FEATURES_OFF=true \ +ENV ADDITIONAL_FEATURES_OFF=true \ VERSION_TAG=$VERSION_TAG \ JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \ JAVA_CUSTOM_OPTS="" \ diff --git a/Dockerfile.ultra-lite b/Dockerfile.ultra-lite index a30c45d481..3b54091b1a 100644 --- a/Dockerfile.ultra-lite +++ b/Dockerfile.ultra-lite @@ -4,8 +4,7 @@ FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be02 ARG VERSION_TAG # Set Environment Variables -ENV DOCKER_ENABLE_SECURITY=false \ - ADDITIONAL_FEATURES_OFF=true \ +ENV ADDITIONAL_FEATURES_OFF=true \ HOME=/home/stirlingpdfuser \ VERSION_TAG=$VERSION_TAG \ JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \ diff --git a/build.gradle b/build.gradle index 87c603617d..987b4b14fb 100644 --- a/build.gradle +++ b/build.gradle @@ -51,12 +51,14 @@ licenseReport { sourceSets { main { java { - if (System.getenv("DOCKER_ENABLE_SECURITY") == "false" || System.getenv("ADDITIONAL_FEATURES_OFF") == "true") { - exclude "stirling/software/proprietary/security/**" + if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('ADDITIONAL_FEATURES_OFF') == 'false' + || (project.hasProperty('ADDITIONAL_FEATURES_OFF') + && System.getProperty('ADDITIONAL_FEATURES_OFF'))) { + exclude 'stirling/software/proprietary/security/**' } - if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") { - exclude "stirling/software/SPDF/UI/impl/**" + if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') { + exclude 'stirling/software/SPDF/UI/impl/**' } } @@ -64,12 +66,14 @@ sourceSets { test { java { - if (System.getenv("DOCKER_ENABLE_SECURITY") == "false" || System.getenv("ADDITIONAL_FEATURES_OFF") == "true") { - exclude "stirling/software/proprietary/security/**" + if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('ADDITIONAL_FEATURES_OFF') == 'false' + || (project.hasProperty('ADDITIONAL_FEATURES_OFF') + && System.getProperty('ADDITIONAL_FEATURES_OFF'))) { + exclude 'stirling/software/proprietary/security/**' } - if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") { - exclude "stirling/software/SPDF/UI/impl/**" + if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') { + exclude 'stirling/software/SPDF/UI/impl/**' } } } diff --git a/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml b/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml index 63b0a7467b..4f3b25948d 100644 --- a/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml +++ b/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml @@ -20,7 +20,6 @@ services: - ./stirling/latest/logs:/logs:rw - ../testing/allEndpointsRemovedSettings.yml:/configs/settings.yml:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "false" PUID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml b/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml index 318065e055..f38ed84e21 100644 --- a/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml +++ b/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml @@ -20,7 +20,6 @@ services: - ./stirling/latest/config:/configs:rw - ./stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "false" PUID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-fat-security.yml b/exampleYmlFiles/docker-compose-latest-fat-security.yml index 8d9ebeff49..88441ee9ac 100644 --- a/exampleYmlFiles/docker-compose-latest-fat-security.yml +++ b/exampleYmlFiles/docker-compose-latest-fat-security.yml @@ -18,7 +18,6 @@ services: - ./stirling/latest/config:/configs:rw - ./stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "false" PUID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-security-with-sso.yml b/exampleYmlFiles/docker-compose-latest-security-with-sso.yml index 36cbfe868a..947ddc4479 100644 --- a/exampleYmlFiles/docker-compose-latest-security-with-sso.yml +++ b/exampleYmlFiles/docker-compose-latest-security-with-sso.yml @@ -18,7 +18,6 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" SECURITY_OAUTH2_ENABLED: "true" diff --git a/exampleYmlFiles/docker-compose-latest-security.yml b/exampleYmlFiles/docker-compose-latest-security.yml index d6d90bf0ae..fa8d768889 100644 --- a/exampleYmlFiles/docker-compose-latest-security.yml +++ b/exampleYmlFiles/docker-compose-latest-security.yml @@ -18,7 +18,6 @@ services: - ./stirling/latest/config:/configs:rw - ./stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" PUID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml b/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml index b3cb57cd10..434bbcd613 100644 --- a/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml +++ b/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml @@ -18,7 +18,6 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" SYSTEM_DEFAULTLOCALE: en-US diff --git a/exampleYmlFiles/docker-compose-latest-ultra-lite.yml b/exampleYmlFiles/docker-compose-latest-ultra-lite.yml index f6c1b703a4..484acf2698 100644 --- a/exampleYmlFiles/docker-compose-latest-ultra-lite.yml +++ b/exampleYmlFiles/docker-compose-latest-ultra-lite.yml @@ -17,7 +17,6 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "false" ADDITIONAL_FEATURES_OFF: "true" SECURITY_ENABLELOGIN: "false" SYSTEM_DEFAULTLOCALE: en-US diff --git a/exampleYmlFiles/docker-compose-latest.yml b/exampleYmlFiles/docker-compose-latest.yml index 3a296b84ab..46cfe35536 100644 --- a/exampleYmlFiles/docker-compose-latest.yml +++ b/exampleYmlFiles/docker-compose-latest.yml @@ -18,7 +18,6 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "false" ADDITIONAL_FEATURES_OFF: "true" SECURITY_ENABLELOGIN: "false" LANGS: "en_GB,en_US,ar_AR,de_DE,fr_FR,es_ES,zh_CN,zh_TW,ca_CA,it_IT,sv_SE,pl_PL,ro_RO,ko_KR,pt_BR,ru_RU,el_GR,hi_IN,hu_HU,tr_TR,id_ID" diff --git a/exampleYmlFiles/test_cicd.yml b/exampleYmlFiles/test_cicd.yml index f92c80d8fa..c76471bd84 100644 --- a/exampleYmlFiles/test_cicd.yml +++ b/exampleYmlFiles/test_cicd.yml @@ -18,7 +18,6 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" PUID: 1002 diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java index ee726b9fb5..47ad7671c4 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java @@ -1,11 +1,8 @@ package stirling.software.proprietary.security; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Optional; -import lombok.extern.slf4j.Slf4j; + import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.InternalAuthenticationServiceException; @@ -13,6 +10,13 @@ import org.springframework.security.authentication.LockedException; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + import stirling.software.proprietary.security.model.User; import stirling.software.proprietary.security.service.LoginAttemptService; import stirling.software.proprietary.security.service.UserService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java index b9379ec748..8b6ea1decf 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java @@ -1,14 +1,18 @@ package stirling.software.proprietary.security; +import java.io.IOException; + +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.security.web.savedrequest.SavedRequest; + import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; -import java.io.IOException; + import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; -import org.springframework.security.web.savedrequest.SavedRequest; + import stirling.software.common.util.RequestUriUtils; import stirling.software.proprietary.security.service.LoginAttemptService; import stirling.software.proprietary.security.service.UserService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/CustomLogoutSuccessHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/CustomLogoutSuccessHandler.java index 244e16da03..44046eb719 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/CustomLogoutSuccessHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/CustomLogoutSuccessHandler.java @@ -1,22 +1,27 @@ package stirling.software.proprietary.security; -import com.coveo.saml.SamlClient; -import com.coveo.saml.SamlException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.util.ArrayList; import java.util.List; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; + import org.springframework.core.io.Resource; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler; + +import com.coveo.saml.SamlClient; +import com.coveo.saml.SamlException; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.configuration.AppConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; @@ -171,8 +176,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler { private SamlClient getSamlClient( String registrationId, SAML2 samlConf, List certificates) throws SamlException { - String serverUrl = - appConfig.getBaseUrl() + ":" + appConfig.getServerPort(); + String serverUrl = appConfig.getBaseUrl() + ":" + appConfig.getServerPort(); String relyingPartyIdentifier = serverUrl + "/saml2/service-provider-metadata/" + registrationId; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/InitialSecuritySetup.java b/proprietary/src/main/java/stirling/software/proprietary/security/InitialSecuritySetup.java index 1353f21518..6568ac3b0c 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/InitialSecuritySetup.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/InitialSecuritySetup.java @@ -1,14 +1,18 @@ package stirling.software.proprietary.security; -import jakarta.annotation.PostConstruct; import java.sql.SQLException; import java.util.UUID; + +import org.springframework.stereotype.Component; + +import jakarta.annotation.PostConstruct; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; + import stirling.software.common.model.ApplicationProperties; -import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.model.enumeration.Role; +import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.proprietary.security.service.DatabaseServiceInterface; import stirling.software.proprietary.security.service.UserService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/RateLimitResetScheduler.java b/proprietary/src/main/java/stirling/software/proprietary/security/RateLimitResetScheduler.java index 4faeb90412..25b3c50967 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/RateLimitResetScheduler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/RateLimitResetScheduler.java @@ -1,8 +1,10 @@ package stirling.software.proprietary.security; -import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; + +import lombok.RequiredArgsConstructor; + import stirling.software.proprietary.security.filter.IPRateLimitingFilter; @Component diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java index 5507580a44..2feab9a46f 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java @@ -1,8 +1,7 @@ package stirling.software.proprietary.security.configuration; import javax.sql.DataSource; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; + import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.domain.EntityScan; @@ -11,6 +10,10 @@ import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.configuration.InstallationPathConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.exception.UnsupportedProviderException; @@ -65,15 +68,17 @@ public class DatabaseConfig { private DataSource useDefaultDataSource(DataSourceBuilder dataSourceBuilder) { log.info("Using default H2 database"); - dataSourceBuilder.url(DATASOURCE_DEFAULT_URL) - .driverClassName(DatabaseDriver.H2.getDriverClassName()) - .username(DEFAULT_USERNAME); + dataSourceBuilder + .url(DATASOURCE_DEFAULT_URL) + .driverClassName(DatabaseDriver.H2.getDriverClassName()) + .username(DEFAULT_USERNAME); return dataSourceBuilder.build(); } @ConditionalOnBooleanProperty(name = "premium.enabled") - private DataSource useCustomDataSource(DataSourceBuilder dataSourceBuilder) throws UnsupportedProviderException { + private DataSource useCustomDataSource(DataSourceBuilder dataSourceBuilder) + throws UnsupportedProviderException { log.info("Using custom database configuration"); if (!datasource.getCustomDatabaseUrl().isBlank()) { @@ -85,11 +90,11 @@ public class DatabaseConfig { } else { dataSourceBuilder.driverClassName(getDriverClassName(datasource.getType())); dataSourceBuilder.url( - generateCustomDataSourceUrl( - datasource.getType(), - datasource.getHostName(), - datasource.getPort(), - datasource.getName())); + generateCustomDataSourceUrl( + datasource.getType(), + datasource.getHostName(), + datasource.getPort(), + datasource.getName())); } dataSourceBuilder.username(datasource.getUsername()); dataSourceBuilder.password(datasource.getPassword()); diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java index 82d794d6ea..c9b6e9d77d 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java @@ -10,6 +10,7 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; /** diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java index cec19214a6..b49e19c08d 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java @@ -1,7 +1,7 @@ package stirling.software.proprietary.security.configuration; import java.util.Optional; -import lombok.extern.slf4j.Slf4j; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; @@ -26,6 +26,9 @@ import org.springframework.security.web.csrf.CookieCsrfTokenRepository; import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; import org.springframework.security.web.savedrequest.NullRequestCache; import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; + +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.configuration.AppConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.proprietary.security.CustomAuthenticationFailureHandler; @@ -71,22 +74,22 @@ public class SecurityConfiguration { private final OpenSaml4AuthenticationRequestResolver saml2AuthenticationRequestResolver; public SecurityConfiguration( - PersistentLoginRepository persistentLoginRepository, - CustomUserDetailsService userDetailsService, - @Lazy UserService userService, - @Qualifier("loginEnabled") boolean loginEnabledValue, - @Qualifier("runningProOrHigher") boolean runningProOrHigher, - AppConfig appConfig, - ApplicationProperties applicationProperties, - UserAuthenticationFilter userAuthenticationFilter, - LoginAttemptService loginAttemptService, - FirstLoginFilter firstLoginFilter, - SessionPersistentRegistry sessionRegistry, - @Autowired(required = false) GrantedAuthoritiesMapper oAuth2userAuthoritiesMapper, - @Autowired(required = false) - RelyingPartyRegistrationRepository saml2RelyingPartyRegistrations, - @Autowired(required = false) - OpenSaml4AuthenticationRequestResolver saml2AuthenticationRequestResolver) { + PersistentLoginRepository persistentLoginRepository, + CustomUserDetailsService userDetailsService, + @Lazy UserService userService, + @Qualifier("loginEnabled") boolean loginEnabledValue, + @Qualifier("runningProOrHigher") boolean runningProOrHigher, + AppConfig appConfig, + ApplicationProperties applicationProperties, + UserAuthenticationFilter userAuthenticationFilter, + LoginAttemptService loginAttemptService, + FirstLoginFilter firstLoginFilter, + SessionPersistentRegistry sessionRegistry, + @Autowired(required = false) GrantedAuthoritiesMapper oAuth2userAuthoritiesMapper, + @Autowired(required = false) + RelyingPartyRegistrationRepository saml2RelyingPartyRegistrations, + @Autowired(required = false) + OpenSaml4AuthenticationRequestResolver saml2AuthenticationRequestResolver) { this.userDetailsService = userDetailsService; this.userService = userService; this.loginEnabledValue = loginEnabledValue; @@ -116,180 +119,183 @@ public class SecurityConfiguration { if (loginEnabledValue) { http.addFilterBefore( - userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); + userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); if (!applicationProperties.getSecurity().getCsrfDisabled()) { CookieCsrfTokenRepository cookieRepo = - CookieCsrfTokenRepository.withHttpOnlyFalse(); + CookieCsrfTokenRepository.withHttpOnlyFalse(); CsrfTokenRequestAttributeHandler requestHandler = - new CsrfTokenRequestAttributeHandler(); + new CsrfTokenRequestAttributeHandler(); requestHandler.setCsrfRequestAttributeName(null); http.csrf( - csrf -> - csrf.ignoringRequestMatchers( - request -> { - String apiKey = request.getHeader("X-API-KEY"); - // If there's no API key, don't ignore CSRF - // (return false) - if (apiKey == null || apiKey.trim().isEmpty()) { - return false; - } - // Validate API key using existing UserService - try { - Optional user = - userService.getUserByApiKey(apiKey); - // If API key is valid, ignore CSRF (return - // true) - // If API key is invalid, don't ignore CSRF - // (return false) - return user.isPresent(); - } catch (Exception e) { - // If there's any error validating the API - // key, don't ignore CSRF - return false; - } - }) - .csrfTokenRepository(cookieRepo) - .csrfTokenRequestHandler(requestHandler)); + csrf -> + csrf.ignoringRequestMatchers( + request -> { + String apiKey = request.getHeader("X-API-KEY"); + // If there's no API key, don't ignore CSRF + // (return false) + if (apiKey == null || apiKey.trim().isEmpty()) { + return false; + } + // Validate API key using existing UserService + try { + Optional user = + userService.getUserByApiKey(apiKey); + // If API key is valid, ignore CSRF (return + // true) + // If API key is invalid, don't ignore CSRF + // (return false) + return user.isPresent(); + } catch (Exception e) { + // If there's any error validating the API + // key, don't ignore CSRF + return false; + } + }) + .csrfTokenRepository(cookieRepo) + .csrfTokenRequestHandler(requestHandler)); } http.addFilterBefore(rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class); http.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class); http.sessionManagement( - sessionManagement -> - sessionManagement - .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) - .maximumSessions(10) - .maxSessionsPreventsLogin(false) - .sessionRegistry(sessionRegistry) - .expiredUrl("/login?logout=true")); + sessionManagement -> + sessionManagement + .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) + .maximumSessions(10) + .maxSessionsPreventsLogin(false) + .sessionRegistry(sessionRegistry) + .expiredUrl("/login?logout=true")); http.authenticationProvider(daoAuthenticationProvider()); http.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache())); http.logout( - logout -> - logout.logoutRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher("/logout")) - .logoutSuccessHandler( - new CustomLogoutSuccessHandler(applicationProperties, appConfig)) - .clearAuthentication(true) - .invalidateHttpSession(true) - .deleteCookies("JSESSIONID", "remember-me")); + logout -> + logout.logoutRequestMatcher( + PathPatternRequestMatcher.withDefaults() + .matcher("/logout")) + .logoutSuccessHandler( + new CustomLogoutSuccessHandler( + applicationProperties, appConfig)) + .clearAuthentication(true) + .invalidateHttpSession(true) + .deleteCookies("JSESSIONID", "remember-me")); http.rememberMe( - rememberMeConfigurer -> // Use the configurator directly + rememberMeConfigurer -> // Use the configurator directly rememberMeConfigurer - .tokenRepository(persistentTokenRepository()) - .tokenValiditySeconds( // 14 days - 14 * 24 * 60 * 60) - .userDetailsService( // Your existing UserDetailsService - userDetailsService) - .useSecureCookie( // Enable secure cookie - true) - .rememberMeParameter( // Form parameter name - "remember-me") - .rememberMeCookieName( // Cookie name - "remember-me") - .alwaysRemember(false)); + .tokenRepository(persistentTokenRepository()) + .tokenValiditySeconds( // 14 days + 14 * 24 * 60 * 60) + .userDetailsService( // Your existing UserDetailsService + userDetailsService) + .useSecureCookie( // Enable secure cookie + true) + .rememberMeParameter( // Form parameter name + "remember-me") + .rememberMeCookieName( // Cookie name + "remember-me") + .alwaysRemember(false)); http.authorizeHttpRequests( - authz -> - authz.requestMatchers( - req -> { - String uri = req.getRequestURI(); - String contextPath = req.getContextPath(); - // Remove the context path from the URI - String trimmedUri = - uri.startsWith(contextPath) - ? uri.substring( - contextPath.length()) - : uri; - return trimmedUri.startsWith("/login") - || trimmedUri.startsWith("/oauth") - || trimmedUri.startsWith("/saml2") - || trimmedUri.endsWith(".svg") - || trimmedUri.startsWith("/register") - || trimmedUri.startsWith("/error") - || trimmedUri.startsWith("/images/") - || trimmedUri.startsWith("/public/") - || trimmedUri.startsWith("/css/") - || trimmedUri.startsWith("/fonts/") - || trimmedUri.startsWith("/js/") - || trimmedUri.startsWith( - "/api/v1/info/status"); - }) - .permitAll() - .anyRequest() - .authenticated()); + authz -> + authz.requestMatchers( + req -> { + String uri = req.getRequestURI(); + String contextPath = req.getContextPath(); + // Remove the context path from the URI + String trimmedUri = + uri.startsWith(contextPath) + ? uri.substring( + contextPath.length()) + : uri; + return trimmedUri.startsWith("/login") + || trimmedUri.startsWith("/oauth") + || trimmedUri.startsWith("/saml2") + || trimmedUri.endsWith(".svg") + || trimmedUri.startsWith("/register") + || trimmedUri.startsWith("/error") + || trimmedUri.startsWith("/images/") + || trimmedUri.startsWith("/public/") + || trimmedUri.startsWith("/css/") + || trimmedUri.startsWith("/fonts/") + || trimmedUri.startsWith("/js/") + || trimmedUri.startsWith( + "/api/v1/info/status"); + }) + .permitAll() + .anyRequest() + .authenticated()); // Handle User/Password Logins if (applicationProperties.getSecurity().isUserPass()) { http.formLogin( - formLogin -> - formLogin - .loginPage("/login") - .successHandler( - new CustomAuthenticationSuccessHandler( - loginAttemptService, userService)) - .failureHandler( - new CustomAuthenticationFailureHandler( - loginAttemptService, userService)) - .defaultSuccessUrl("/") - .permitAll()); + formLogin -> + formLogin + .loginPage("/login") + .successHandler( + new CustomAuthenticationSuccessHandler( + loginAttemptService, userService)) + .failureHandler( + new CustomAuthenticationFailureHandler( + loginAttemptService, userService)) + .defaultSuccessUrl("/") + .permitAll()); } // Handle OAUTH2 Logins if (applicationProperties.getSecurity().isOauth2Active()) { http.oauth2Login( - oauth2 -> - oauth2.loginPage("/oauth2") - /* - This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database. - If user exists, login proceeds as usual. If user does not exist, then it is auto-created but only if 'OAUTH2AutoCreateUser' - is set as true, else login fails with an error message advising the same. - */ - .successHandler( - new CustomOAuth2AuthenticationSuccessHandler( - loginAttemptService, - applicationProperties, - userService)) - .failureHandler( - new CustomOAuth2AuthenticationFailureHandler()) - . // Add existing Authorities from the database - userInfoEndpoint( - userInfoEndpoint -> - userInfoEndpoint - .oidcUserService( - new CustomOAuth2UserService( - applicationProperties, - userService, - loginAttemptService)) - .userAuthoritiesMapper( - oAuth2userAuthoritiesMapper)) - .permitAll()); + oauth2 -> + oauth2.loginPage("/oauth2") + /* + This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database. + If user exists, login proceeds as usual. If user does not exist, then it is auto-created but only if 'OAUTH2AutoCreateUser' + is set as true, else login fails with an error message advising the same. + */ + .successHandler( + new CustomOAuth2AuthenticationSuccessHandler( + loginAttemptService, + applicationProperties, + userService)) + .failureHandler( + new CustomOAuth2AuthenticationFailureHandler()) + . // Add existing Authorities from the database + userInfoEndpoint( + userInfoEndpoint -> + userInfoEndpoint + .oidcUserService( + new CustomOAuth2UserService( + applicationProperties, + userService, + loginAttemptService)) + .userAuthoritiesMapper( + oAuth2userAuthoritiesMapper)) + .permitAll()); } // Handle SAML if (applicationProperties.getSecurity().isSaml2Active() && runningProOrHigher) { // Configure the authentication provider OpenSaml4AuthenticationProvider authenticationProvider = - new OpenSaml4AuthenticationProvider(); + new OpenSaml4AuthenticationProvider(); authenticationProvider.setResponseAuthenticationConverter( - new CustomSaml2ResponseAuthenticationConverter(userService)); + new CustomSaml2ResponseAuthenticationConverter(userService)); http.authenticationProvider(authenticationProvider) - .saml2Login( - saml2 -> { - try { - saml2.loginPage("/saml2") - .relyingPartyRegistrationRepository( - saml2RelyingPartyRegistrations) - .authenticationManager( - new ProviderManager(authenticationProvider)) - .successHandler( - new CustomSaml2AuthenticationSuccessHandler( - loginAttemptService, - applicationProperties, - userService)) - .failureHandler( - new CustomSaml2AuthenticationFailureHandler()) - .authenticationRequestResolver( - saml2AuthenticationRequestResolver); - } catch (Exception e) { - log.error("Error configuring SAML 2 login", e); - throw new RuntimeException(e); - } - }); + .saml2Login( + saml2 -> { + try { + saml2.loginPage("/saml2") + .relyingPartyRegistrationRepository( + saml2RelyingPartyRegistrations) + .authenticationManager( + new ProviderManager(authenticationProvider)) + .successHandler( + new CustomSaml2AuthenticationSuccessHandler( + loginAttemptService, + applicationProperties, + userService)) + .failureHandler( + new CustomSaml2AuthenticationFailureHandler()) + .authenticationRequestResolver( + saml2AuthenticationRequestResolver); + } catch (Exception e) { + log.error("Error configuring SAML 2 login", e); + throw new RuntimeException(e); + } + }); } } else { log.debug("Login is not enabled."); diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java index bbc84821f2..dec64c46f2 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java @@ -26,6 +26,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + import stirling.software.proprietary.security.database.H2SQLCondition; import stirling.software.proprietary.security.service.DatabaseService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java index dec5905bad..e1abb69892 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java @@ -29,11 +29,11 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import stirling.software.proprietary.security.model.AuthenticationType; -import stirling.software.common.model.enumeration.Role; -import stirling.software.proprietary.security.model.User; import stirling.software.common.model.ApplicationProperties; +import stirling.software.common.model.enumeration.Role; import stirling.software.common.model.exception.UnsupportedProviderException; +import stirling.software.proprietary.security.model.AuthenticationType; +import stirling.software.proprietary.security.model.User; import stirling.software.proprietary.security.model.api.user.UsernameAndPass; import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal; import stirling.software.proprietary.security.service.UserService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/controller/web/AccountWebController.java b/proprietary/src/main/java/stirling/software/proprietary/security/controller/web/AccountWebController.java index 311f81a4fa..bdf1df32e6 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/controller/web/AccountWebController.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/controller/web/AccountWebController.java @@ -29,12 +29,12 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; -import stirling.software.common.model.enumeration.Role; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2.Client; import stirling.software.common.model.ApplicationProperties.Security.SAML2; +import stirling.software.common.model.enumeration.Role; import stirling.software.common.model.oauth2.GitHubProvider; import stirling.software.common.model.oauth2.GoogleProvider; import stirling.software.common.model.oauth2.KeycloakProvider; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/database/ScheduledTasks.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/ScheduledTasks.java index 835dc1917f..6821414aab 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/database/ScheduledTasks.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/ScheduledTasks.java @@ -1,10 +1,13 @@ package stirling.software.proprietary.security.database; import java.sql.SQLException; -import lombok.RequiredArgsConstructor; + import org.springframework.context.annotation.Conditional; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; + +import lombok.RequiredArgsConstructor; + import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.proprietary.security.service.DatabaseServiceInterface; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/AuthorityRepository.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/AuthorityRepository.java index a7773d8590..e8d74ec01f 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/AuthorityRepository.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/AuthorityRepository.java @@ -4,6 +4,7 @@ import java.util.Set; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; + import stirling.software.proprietary.security.model.Authority; @Repository diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/JPATokenRepositoryImpl.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/JPATokenRepositoryImpl.java index b98a8094f4..ec7a0078bc 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/JPATokenRepositoryImpl.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/JPATokenRepositoryImpl.java @@ -5,6 +5,7 @@ import java.util.Date; import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken; import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; import org.springframework.transaction.annotation.Transactional; + import stirling.software.proprietary.security.model.PersistentLogin; public class JPATokenRepositoryImpl implements PersistentTokenRepository { diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/PersistentLoginRepository.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/PersistentLoginRepository.java index a9ddf8a377..2ab9566763 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/PersistentLoginRepository.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/PersistentLoginRepository.java @@ -2,6 +2,7 @@ package stirling.software.proprietary.security.database.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; + import stirling.software.proprietary.security.model.PersistentLogin; @Repository diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/SessionRepository.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/SessionRepository.java index b7a7d7a844..78206b2593 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/SessionRepository.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/SessionRepository.java @@ -1,13 +1,16 @@ package stirling.software.proprietary.security.database.repository; -import jakarta.transaction.Transactional; import java.util.Date; import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; + +import jakarta.transaction.Transactional; + import stirling.software.proprietary.security.model.SessionEntity; @Repository diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/UserRepository.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/UserRepository.java index dcf84ee19b..2a8d420969 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/UserRepository.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/UserRepository.java @@ -7,6 +7,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; + import stirling.software.proprietary.security.model.User; @Repository diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java b/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java index a96e6e7691..3bae721957 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java @@ -1,20 +1,24 @@ package stirling.software.proprietary.security.filter; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Optional; + +import org.springframework.context.annotation.Lazy; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Optional; + import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Lazy; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; + import stirling.software.common.util.RequestUriUtils; import stirling.software.proprietary.security.model.User; import stirling.software.proprietary.security.service.UserService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/filter/IPRateLimitingFilter.java b/proprietary/src/main/java/stirling/software/proprietary/security/filter/IPRateLimitingFilter.java index ebc0f949ea..028768c080 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/filter/IPRateLimitingFilter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/filter/IPRateLimitingFilter.java @@ -1,15 +1,18 @@ package stirling.software.proprietary.security.filter; +import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; + import lombok.RequiredArgsConstructor; + import stirling.software.common.util.RequestUriUtils; @RequiredArgsConstructor diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java b/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java index de97ec7858..e9addd2395 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java @@ -1,13 +1,9 @@ package stirling.software.proprietary.security.filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; import java.util.Optional; -import lombok.extern.slf4j.Slf4j; + import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpStatus; @@ -20,6 +16,14 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.SAML2; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java b/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java index 31db979b09..4d1d7bbed9 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java @@ -1,17 +1,10 @@ package stirling.software.proprietary.security.filter; -import io.github.bucket4j.Bandwidth; -import io.github.bucket4j.Bucket; -import io.github.bucket4j.ConsumptionProbe; -import io.github.pixee.security.Newlines; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.time.Duration; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; + import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; @@ -20,6 +13,17 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; + +import io.github.bucket4j.Bandwidth; +import io.github.bucket4j.Bucket; +import io.github.bucket4j.ConsumptionProbe; +import io.github.pixee.security.Newlines; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + import stirling.software.common.model.enumeration.Role; @Component diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java index 6dc32a85d3..b364f37388 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java @@ -14,6 +14,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; + import stirling.software.common.model.enumeration.Role; @Entity diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java index 8fe3cebe6f..4e9421aba7 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java @@ -7,6 +7,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; + import stirling.software.common.model.api.GeneralFile; @Data diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java index 92b053b8ae..7175a5b5d6 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java @@ -1,10 +1,7 @@ package stirling.software.proprietary.security.oauth2; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import lombok.extern.slf4j.Slf4j; + import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.LockedException; @@ -13,6 +10,12 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + @Slf4j public class CustomOAuth2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java index 1c4d04e55d..71bd42a857 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java @@ -1,18 +1,22 @@ package stirling.software.proprietary.security.oauth2; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.http.HttpSession; import java.io.IOException; import java.sql.SQLException; -import lombok.RequiredArgsConstructor; + import org.springframework.security.authentication.LockedException; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.security.web.savedrequest.SavedRequest; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import lombok.RequiredArgsConstructor; + import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.exception.UnsupportedProviderException; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java index cb2771cc07..6516cc7d73 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java @@ -1,13 +1,16 @@ package stirling.software.proprietary.security.oauth2; +import static org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE; +import static stirling.software.common.util.ProviderUtils.validateProvider; +import static stirling.software.common.util.ValidationUtils.isStringEmpty; + import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; -import lombok.extern.slf4j.Slf4j; + import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -20,20 +23,20 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio import org.springframework.security.oauth2.client.registration.ClientRegistrations; import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; import org.springframework.security.oauth2.core.user.OAuth2UserAuthority; + +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2.Client; import stirling.software.common.model.enumeration.UsernameAttribute; -import stirling.software.proprietary.security.model.exception.NoProviderFoundException; import stirling.software.common.model.oauth2.GitHubProvider; import stirling.software.common.model.oauth2.GoogleProvider; import stirling.software.common.model.oauth2.KeycloakProvider; import stirling.software.common.model.oauth2.Provider; import stirling.software.proprietary.security.model.User; +import stirling.software.proprietary.security.model.exception.NoProviderFoundException; import stirling.software.proprietary.security.service.UserService; -import static org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE; -import static stirling.software.common.util.ProviderUtils.validateProvider; -import static stirling.software.common.util.ValidationUtils.isStringEmpty; @Slf4j @Configuration diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java index c2957e2413..fff03fd4f5 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java @@ -6,6 +6,7 @@ import java.nio.charset.StandardCharsets; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; + import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java index 055ac8f4e1..a39a390927 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java @@ -3,6 +3,7 @@ package stirling.software.proprietary.security.saml2; import java.io.Serializable; import java.util.List; import java.util.Map; + import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java index a7e663aac0..7bf0c3a3b3 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java @@ -1,9 +1,7 @@ package stirling.software.proprietary.security.saml2; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import lombok.extern.slf4j.Slf4j; + import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.security.authentication.ProviderNotFoundException; import org.springframework.security.core.AuthenticationException; @@ -11,6 +9,11 @@ import org.springframework.security.saml2.core.Saml2Error; import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + @Slf4j @ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true") public class CustomSaml2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java index 47391e4d05..2170a9632b 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java @@ -1,17 +1,21 @@ package stirling.software.proprietary.security.saml2; +import java.io.IOException; +import java.sql.SQLException; + +import org.springframework.security.authentication.LockedException; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.security.web.savedrequest.SavedRequest; + import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; -import java.io.IOException; -import java.sql.SQLException; + import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.security.authentication.LockedException; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; -import org.springframework.security.web.savedrequest.SavedRequest; + import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.SAML2; import stirling.software.common.model.exception.UnsupportedProviderException; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java index d1c24b4206..e8326c1e30 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java @@ -5,8 +5,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; + import org.opensaml.core.xml.XMLObject; import org.opensaml.saml.saml2.core.Assertion; import org.opensaml.saml.saml2.core.Attribute; @@ -17,6 +16,10 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.ResponseToken; import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + import stirling.software.proprietary.security.model.User; import stirling.software.proprietary.security.service.UserService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java index 836419ea0f..233bcaaddf 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java @@ -1,11 +1,9 @@ package stirling.software.proprietary.security.saml2; -import jakarta.servlet.http.HttpServletRequest; import java.security.cert.X509Certificate; import java.util.Collections; import java.util.UUID; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; + import org.opensaml.saml.saml2.core.AuthnRequest; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -21,6 +19,12 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; import org.springframework.security.saml2.provider.service.web.HttpSessionSaml2AuthenticationRequestRepository; import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver; + +import jakarta.servlet.http.HttpServletRequest; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.SAML2; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/service/AppUpdateAuthService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/AppUpdateAuthService.java index 5687a3b926..19e3005852 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/service/AppUpdateAuthService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/AppUpdateAuthService.java @@ -1,10 +1,13 @@ package stirling.software.proprietary.security.service; import java.util.Optional; -import lombok.RequiredArgsConstructor; + import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; + import stirling.software.common.configuration.interfaces.ShowAdminInterface; import stirling.software.common.model.ApplicationProperties; import stirling.software.proprietary.security.database.repository.UserRepository; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java index b889a06e58..0b286e894f 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java @@ -1,7 +1,7 @@ package stirling.software.proprietary.security.service; import java.util.Optional; -import lombok.extern.slf4j.Slf4j; + import org.springframework.security.authentication.LockedException; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; @@ -10,6 +10,9 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; import org.springframework.security.oauth2.core.oidc.user.OidcUser; + +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.enumeration.UsernameAttribute; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java index 0146669717..6ece48a4e9 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java @@ -2,7 +2,7 @@ package stirling.software.proprietary.security.service; import java.util.Collection; import java.util.Set; -import lombok.RequiredArgsConstructor; + import org.springframework.security.authentication.LockedException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -10,6 +10,9 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; + import stirling.software.proprietary.security.database.repository.UserRepository; import stirling.software.proprietary.security.model.Authority; import stirling.software.proprietary.security.model.User; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java index 37de87cf40..6474ae7ead 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java @@ -18,11 +18,15 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; + import javax.sql.DataSource; -import lombok.extern.slf4j.Slf4j; + import org.springframework.jdbc.datasource.init.CannotReadScriptException; import org.springframework.jdbc.datasource.init.ScriptException; import org.springframework.stereotype.Service; + +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.configuration.InstallationPathConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.FileInfo; @@ -235,27 +239,27 @@ public class DatabaseService implements DatabaseServiceInterface { private boolean isH2Database() { boolean isTypeH2 = - datasourceProps.getType().equalsIgnoreCase(ApplicationProperties.Driver.H2.name()); + datasourceProps.getType().equalsIgnoreCase(ApplicationProperties.Driver.H2.name()); boolean isDBUrlH2 = - datasourceProps.getCustomDatabaseUrl().contains("h2") - || datasourceProps.getCustomDatabaseUrl().contains("H2"); + datasourceProps.getCustomDatabaseUrl().contains("h2") + || datasourceProps.getCustomDatabaseUrl().contains("H2"); boolean isCustomDatabase = datasourceProps.isEnableCustomDatabase(); if (isCustomDatabase) { if (isTypeH2 && !isDBUrlH2) { log.warn( - "Datasource type is H2, but the URL does not contain 'h2'. " - + "Please check your configuration."); + "Datasource type is H2, but the URL does not contain 'h2'. " + + "Please check your configuration."); throw new IllegalStateException( - "Datasource type is H2, but the URL does not contain 'h2'. Please check" - + " your configuration."); + "Datasource type is H2, but the URL does not contain 'h2'. Please check" + + " your configuration."); } else if (!isTypeH2 && isDBUrlH2) { log.warn( - "Datasource URL contains 'h2', but the type is not H2. " - + "Please check your configuration."); + "Datasource URL contains 'h2', but the type is not H2. " + + "Please check your configuration."); throw new IllegalStateException( - "Datasource URL contains 'h2', but the type is not H2. Please check your" - + " configuration."); + "Datasource URL contains 'h2', but the type is not H2. Please check your" + + " configuration."); } } boolean isH2 = isTypeH2 && isDBUrlH2; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java index 852fc8ab90..ecc04bac5a 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java @@ -1,11 +1,15 @@ package stirling.software.proprietary.security.service; -import jakarta.annotation.PostConstruct; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; + +import org.springframework.stereotype.Service; + +import jakarta.annotation.PostConstruct; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; + import stirling.software.common.model.ApplicationProperties; import stirling.software.proprietary.security.model.AttemptCounter; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java index 7bf3e2643c..0823f748ba 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java @@ -1,6 +1,5 @@ package stirling.software.proprietary.security.service; -import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; @@ -9,8 +8,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; + import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -25,10 +23,14 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; +import stirling.software.common.model.enumeration.Role; import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.service.UserServiceInterface; -import stirling.software.common.model.enumeration.Role; import stirling.software.proprietary.security.database.repository.AuthorityRepository; import stirling.software.proprietary.security.database.repository.UserRepository; import stirling.software.proprietary.security.model.AuthenticationType; @@ -84,7 +86,7 @@ public class UserService implements UserServiceInterface { public Authentication getAuthentication(String apiKey) { Optional user = getUserByApiKey(apiKey); - if (!user.isPresent()) { + if (user.isEmpty()) { throw new UsernameNotFoundException("API key is not valid"); } // Convert the user into an Authentication object @@ -301,9 +303,7 @@ public class UserService implements UserServiceInterface { } public void changeUsername(User user, String newUsername) - throws IllegalArgumentException, - SQLException, - UnsupportedProviderException { + throws IllegalArgumentException, SQLException, UnsupportedProviderException { if (!isUsernameValid(newUsername)) { throw new IllegalArgumentException(getInvalidUsernameMessage()); } diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/session/CustomHttpSessionListener.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/CustomHttpSessionListener.java index 7ed0f65064..b69dfaefbf 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/session/CustomHttpSessionListener.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/CustomHttpSessionListener.java @@ -1,15 +1,17 @@ package stirling.software.proprietary.security.session; +import org.springframework.stereotype.Component; + import jakarta.servlet.http.HttpSessionEvent; import jakarta.servlet.http.HttpSessionListener; + import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; @Component @Slf4j public class CustomHttpSessionListener implements HttpSessionListener { - private SessionPersistentRegistry sessionPersistentRegistry; + private final SessionPersistentRegistry sessionPersistentRegistry; public CustomHttpSessionListener(SessionPersistentRegistry sessionPersistentRegistry) { super(); diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionPersistentRegistry.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionPersistentRegistry.java index 5d482e94d2..8931866adb 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionPersistentRegistry.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionPersistentRegistry.java @@ -1,6 +1,5 @@ package stirling.software.proprietary.security.session; -import jakarta.transaction.Transactional; import java.time.Duration; import java.util.ArrayList; import java.util.Collections; @@ -8,13 +7,18 @@ import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Optional; -import lombok.RequiredArgsConstructor; + import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.session.SessionInformation; import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Component; + +import jakarta.transaction.Transactional; + +import lombok.RequiredArgsConstructor; + import stirling.software.proprietary.security.database.repository.SessionRepository; import stirling.software.proprietary.security.model.SessionEntity; import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java index 75afbea9b7..eccd7332e5 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java @@ -3,6 +3,7 @@ package stirling.software.proprietary.security.session; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.core.session.SessionRegistryImpl; + import stirling.software.proprietary.security.database.repository.SessionRepository; @Configuration @@ -14,7 +15,8 @@ public class SessionRegistryConfig { } @Bean - public SessionPersistentRegistry sessionPersistentRegistry(SessionRepository sessionRepository) { + public SessionPersistentRegistry sessionPersistentRegistry( + SessionRepository sessionRepository) { return new SessionPersistentRegistry(sessionRepository); } } diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java index 83403f9f74..1f491bf4d6 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java @@ -4,11 +4,13 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.List; -import lombok.RequiredArgsConstructor; + import org.springframework.scheduling.annotation.Scheduled; import org.springframework.security.core.session.SessionInformation; import org.springframework.stereotype.Component; +import lombok.RequiredArgsConstructor; + @Component @RequiredArgsConstructor public class SessionScheduled { diff --git a/scripts/download-security-jar.sh b/scripts/download-security-jar.sh index 8216179fa0..bee188d972 100644 --- a/scripts/download-security-jar.sh +++ b/scripts/download-security-jar.sh @@ -1,6 +1,6 @@ echo "Running Stirling PDF with ADDITIONAL_FEATURES_OFF=${ADDITIONAL_FEATURES_OFF} and VERSION_TAG=${VERSION_TAG}" -# Check for DOCKER_ENABLE_SECURITY and download the appropriate JAR if required -if [ "$DOCKER_ENABLE_SECURITY" = "true" ] || [ "$ADDITIONAL_FEATURES_OFF" = "false" ] && [ "$VERSION_TAG" != "alpha" ]; then +# Check for $ADDITIONAL_FEATURES_OFF and download the appropriate JAR if required +if [ "$ADDITIONAL_FEATURES_OFF" = "false" ] && [ "$VERSION_TAG" != "alpha" ]; then if [ ! -f app-security.jar ]; then echo "Trying to download from: https://files.stirlingpdf.com/v$VERSION_TAG/Stirling-PDF-with-login.jar" curl -L -o app-security.jar https://files.stirlingpdf.com/v$VERSION_TAG/Stirling-PDF-with-login.jar diff --git a/testing/test.sh b/testing/test.sh index f1169ec170..0891c6bbd2 100644 --- a/testing/test.sh +++ b/testing/test.sh @@ -214,7 +214,6 @@ main() { export DOCKER_CLI_EXPERIMENTAL=enabled export COMPOSE_DOCKER_CLI_BUILD=0 - export DOCKER_ENABLE_SECURITY=false export ADDITIONAL_FEATURES_OFF=true # Run the gradlew build command and check if it fails if ! ./gradlew clean build; then @@ -243,7 +242,6 @@ main() { # run_tests "Stirling-PDF" "./exampleYmlFiles/docker-compose-latest.yml" # docker-compose -f "./exampleYmlFiles/docker-compose-latest.yml" down - export DOCKER_ENABLE_SECURITY=true export ADDITIONAL_FEATURES_OFF=false # Run the gradlew build command and check if it fails if ! ./gradlew clean build; then From febe67eac8af66cc9a7001fe28d5ccac611913f4 Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Fri, 9 May 2025 16:48:48 +0100 Subject: [PATCH 11/15] moving security package and relevant files over to proprietary --- LICENSE | 7 + .../gradle/wrapper/gradle-wrapper.properties | 6 + common/gradlew | 251 ++++++++++++++++++ common/gradlew.bat | 94 +++++++ .../gradle/wrapper/gradle-wrapper.properties | 6 + proprietary/gradlew | 251 ++++++++++++++++++ proprietary/gradlew.bat | 94 +++++++ .../security/configuration/MailConfig.java | 1 - .../proprietary/security/model/User.java | 1 + ...tomOAuth2AuthenticationFailureHandler.java | 11 +- .../security/saml2/CertificateUtils.java | 1 - .../CustomSaml2AuthenticatedPrincipal.java | 1 - ...stomSaml2AuthenticationFailureHandler.java | 9 +- .../security/saml2/SAML2Configuration.java | 10 +- .../session/SessionRegistryConfig.java | 4 +- .../security/session/SessionScheduled.java | 4 +- 16 files changed, 723 insertions(+), 28 deletions(-) create mode 100644 common/gradle/wrapper/gradle-wrapper.properties create mode 100755 common/gradlew create mode 100644 common/gradlew.bat create mode 100644 proprietary/gradle/wrapper/gradle-wrapper.properties create mode 100755 proprietary/gradlew create mode 100644 proprietary/gradlew.bat diff --git a/LICENSE b/LICENSE index 8776631713..62cd6e5cc1 100644 --- a/LICENSE +++ b/LICENSE @@ -9,6 +9,13 @@ if that directory exists, is licensed under the license defined in "proprietary/ * Content outside of the above mentioned directories or restrictions above is available under the MIT License as defined below. +Portions of this software are licensed as follows: + +* All content that resides under the "proprietary/" directory of this repository, +if that directory exists, is licensed under the license defined in "proprietary/LICENSE". +* Content outside of the above mentioned directories or restrictions above is +available under the MIT License as defined below. + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights diff --git a/common/gradle/wrapper/gradle-wrapper.properties b/common/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..f7664bccf7 --- /dev/null +++ b/common/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/common/gradlew b/common/gradlew new file mode 100755 index 0000000000..23d15a9367 --- /dev/null +++ b/common/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/common/gradlew.bat b/common/gradlew.bat new file mode 100644 index 0000000000..db3a6ac207 --- /dev/null +++ b/common/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/proprietary/gradle/wrapper/gradle-wrapper.properties b/proprietary/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..f7664bccf7 --- /dev/null +++ b/proprietary/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/proprietary/gradlew b/proprietary/gradlew new file mode 100755 index 0000000000..23d15a9367 --- /dev/null +++ b/proprietary/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/proprietary/gradlew.bat b/proprietary/gradlew.bat new file mode 100644 index 0000000000..db3a6ac207 --- /dev/null +++ b/proprietary/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java index c9b6e9d77d..82d794d6ea 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java @@ -10,7 +10,6 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; - import stirling.software.common.model.ApplicationProperties; /** diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java index b364f37388..0fd356da20 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java @@ -14,6 +14,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; +import stirling.software.common.model.enumeration.Role; import stirling.software.common.model.enumeration.Role; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java index 7175a5b5d6..92b053b8ae 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java @@ -1,7 +1,10 @@ package stirling.software.proprietary.security.oauth2; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; - +import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.LockedException; @@ -10,12 +13,6 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import lombok.extern.slf4j.Slf4j; - @Slf4j public class CustomOAuth2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java index fff03fd4f5..c2957e2413 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java @@ -6,7 +6,6 @@ import java.nio.charset.StandardCharsets; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; - import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java index a39a390927..055ac8f4e1 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java @@ -3,7 +3,6 @@ package stirling.software.proprietary.security.saml2; import java.io.Serializable; import java.util.List; import java.util.Map; - import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java index 7bf0c3a3b3..a7e663aac0 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java @@ -1,7 +1,9 @@ package stirling.software.proprietary.security.saml2; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; - +import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.security.authentication.ProviderNotFoundException; import org.springframework.security.core.AuthenticationException; @@ -9,11 +11,6 @@ import org.springframework.security.saml2.core.Saml2Error; import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import lombok.extern.slf4j.Slf4j; - @Slf4j @ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true") public class CustomSaml2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java index 233bcaaddf..836419ea0f 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java @@ -1,9 +1,11 @@ package stirling.software.proprietary.security.saml2; +import jakarta.servlet.http.HttpServletRequest; import java.security.cert.X509Certificate; import java.util.Collections; import java.util.UUID; - +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.opensaml.saml.saml2.core.AuthnRequest; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -19,12 +21,6 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; import org.springframework.security.saml2.provider.service.web.HttpSessionSaml2AuthenticationRequestRepository; import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver; - -import jakarta.servlet.http.HttpServletRequest; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.SAML2; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java index eccd7332e5..6c1d334f5e 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java @@ -3,6 +3,7 @@ package stirling.software.proprietary.security.session; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.core.session.SessionRegistryImpl; +import stirling.software.proprietary.security.database.repository.SessionRepository; import stirling.software.proprietary.security.database.repository.SessionRepository; @@ -15,8 +16,7 @@ public class SessionRegistryConfig { } @Bean - public SessionPersistentRegistry sessionPersistentRegistry( - SessionRepository sessionRepository) { + public SessionPersistentRegistry sessionPersistentRegistry(SessionRepository sessionRepository) { return new SessionPersistentRegistry(sessionRepository); } } diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java index 1f491bf4d6..83403f9f74 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java @@ -4,13 +4,11 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.List; - +import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.security.core.session.SessionInformation; import org.springframework.stereotype.Component; -import lombok.RequiredArgsConstructor; - @Component @RequiredArgsConstructor public class SessionScheduled { From a0cb56ab0c9d9ebb3da400b48129b81ef6a1a14f Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Tue, 3 Jun 2025 17:15:50 +0100 Subject: [PATCH 12/15] correcting security logic This Pull Request was automatically generated to synchronize updates to translation files and documentation. Below are the details of the changes made: - Updated translation files (`messages_*.properties`) to reflect changes in the reference file `messages_en_GB.properties`. - Ensured consistency and synchronization across all supported language files. - Highlighted any missing or incomplete translations. - Generated the translation progress table in `README.md`. - Added a summary of the current translation status for all supported languages. - Included up-to-date statistics on translation coverage. - Keeps translation files aligned with the latest reference updates. - Ensures the documentation reflects the current translation progress. --- Auto-generated by [create-pull-request][1]. [1]: https://github.com/peter-evans/create-pull-request Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com> Update messages_de_DE.properties (#3618) Please provide a summary of the changes, including: - What was changed - Why the change was made - Any challenges encountered Closes #(issue_number) --- - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Fix error display for Split by Chapter (#3621) - throw `IllegalArgumentException` when bookmark level is invalid or when a PDF has no outline - rely on global error handling so frontend shows the message - `./gradlew build` ------ https://chatgpt.com/codex/tasks/task_b_683dc51dd31083288be3f9892889fa59 :globe_with_meridians: Sync Translations + Update README Progress Table (#3638) This Pull Request was automatically generated to synchronize updates to translation files and documentation. Below are the details of the changes made: - Updated translation files (`messages_*.properties`) to reflect changes in the reference file `messages_en_GB.properties`. - Ensured consistency and synchronization across all supported language files. - Highlighted any missing or incomplete translations. - Generated the translation progress table in `README.md`. - Added a summary of the current translation status for all supported languages. - Included up-to-date statistics on translation coverage. - Keeps translation files aligned with the latest reference updates. - Ensures the documentation reflects the current translation progress. --- Auto-generated by [create-pull-request][1]. [1]: https://github.com/peter-evans/create-pull-request Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com> GetInfo summary #2388 (#3585) Please provide a summary of the changes, including: - What was changed - Why the change was made - Any challenges encountered Closes #(issue_number) --- - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details. Co-authored-by: a :globe_with_meridians: Sync Translations + Update README Progress Table (#3639) This Pull Request was automatically generated to synchronize updates to translation files and documentation. Below are the details of the changes made: - Updated translation files (`messages_*.properties`) to reflect changes in the reference file `messages_en_GB.properties`. - Ensured consistency and synchronization across all supported language files. - Highlighted any missing or incomplete translations. - Generated the translation progress table in `README.md`. - Added a summary of the current translation status for all supported languages. - Included up-to-date statistics on translation coverage. - Keeps translation files aligned with the latest reference updates. - Ensures the documentation reflects the current translation progress. --- Auto-generated by [create-pull-request][1]. [1]: https://github.com/peter-evans/create-pull-request --------- Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com> clean up :globe_with_meridians: Sync Translations + Update README Progress Table (#3639) This Pull Request was automatically generated to synchronize updates to translation files and documentation. Below are the details of the changes made: - Updated translation files (`messages_*.properties`) to reflect changes in the reference file `messages_en_GB.properties`. - Ensured consistency and synchronization across all supported language files. - Highlighted any missing or incomplete translations. - Generated the translation progress table in `README.md`. - Added a summary of the current translation status for all supported languages. - Included up-to-date statistics on translation coverage. - Keeps translation files aligned with the latest reference updates. - Ensures the documentation reflects the current translation progress. --- Auto-generated by [create-pull-request][1]. [1]: https://github.com/peter-evans/create-pull-request --------- Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com> ADDITIONAL_FEATURES_OFF > ADDITIONAL_FEATURES renamed flag renamed flag in workflows --- .../workflows/PR-Demo-Comment-with-react.yml | 16 +- .github/workflows/build.yml | 4 +- .github/workflows/multiOSReleases.yml | 21 +- .github/workflows/push-docker.yml | 2 +- .github/workflows/releaseArtifacts.yml | 25 +- .github/workflows/sonarqube.yml | 2 +- .github/workflows/testdriver.yml | 4 +- DeveloperGuide.md | 8 +- Dockerfile | 2 +- Dockerfile.fat | 6 +- Dockerfile.ultra-lite | 2 +- build.gradle | 22 +- .../gradle/wrapper/gradle-wrapper.properties | 6 - common/gradlew | 251 ------------------ common/gradlew.bat | 94 ------- .../common/configuration/AppConfig.java | 12 +- ...-compose-latest-fat-endpoints-disabled.yml | 2 +- ...r-compose-latest-fat-security-postgres.yml | 2 +- .../docker-compose-latest-fat-security.yml | 2 +- ...ocker-compose-latest-security-with-sso.yml | 2 +- .../docker-compose-latest-security.yml | 2 +- ...ker-compose-latest-ultra-lite-security.yml | 2 +- .../docker-compose-latest-ultra-lite.yml | 2 +- exampleYmlFiles/docker-compose-latest.yml | 2 +- exampleYmlFiles/test_cicd.yml | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 6 - proprietary/gradlew | 251 ------------------ proprietary/gradlew.bat | 94 ------- .../security/configuration/MailConfig.java | 1 + .../proprietary/security/model/User.java | 1 - ...tomOAuth2AuthenticationFailureHandler.java | 11 +- .../security/saml2/CertificateUtils.java | 1 + .../CustomSaml2AuthenticatedPrincipal.java | 1 + ...stomSaml2AuthenticationFailureHandler.java | 9 +- .../security/saml2/SAML2Configuration.java | 10 +- .../session/SessionRegistryConfig.java | 4 +- .../security/session/SessionScheduled.java | 4 +- scripts/download-security-jar.sh | 6 +- testing/test.sh | 4 +- 39 files changed, 103 insertions(+), 795 deletions(-) delete mode 100644 common/gradle/wrapper/gradle-wrapper.properties delete mode 100755 common/gradlew delete mode 100644 common/gradlew.bat delete mode 100644 proprietary/gradle/wrapper/gradle-wrapper.properties delete mode 100755 proprietary/gradlew delete mode 100644 proprietary/gradlew.bat diff --git a/.github/workflows/PR-Demo-Comment-with-react.yml b/.github/workflows/PR-Demo-Comment-with-react.yml index 7863163656..e9dcc3d8be 100644 --- a/.github/workflows/PR-Demo-Comment-with-react.yml +++ b/.github/workflows/PR-Demo-Comment-with-react.yml @@ -37,7 +37,7 @@ jobs: pr_repository: ${{ steps.get-pr-info.outputs.repository }} pr_ref: ${{ steps.get-pr-info.outputs.ref }} comment_id: ${{ github.event.comment.id }} - enable_security: ${{ steps.check-security-flag.outputs.enable_security }} + disable_security: ${{ steps.check-security-flag.outputs.disable_security }} steps: - name: Harden Runner @@ -92,10 +92,10 @@ jobs: run: | if [[ "$COMMENT_BODY" == *"security"* ]] || [[ "$COMMENT_BODY" == *"login"* ]]; then echo "Security flags detected in comment" - echo "enable_security=true" >> $GITHUB_OUTPUT + echo "disable_security=false" >> $GITHUB_OUTPUT else echo "No security flags detected in comment" - echo "enable_security=false" >> $GITHUB_OUTPUT + echo "disable_security=true" >> $GITHUB_OUTPUT fi - name: Add 'in_progress' reaction to comment @@ -155,10 +155,10 @@ jobs: - name: Run Gradle Command run: | - if [ "${{ needs.check-comment.outputs.enable_security }}" == "true" ]; then - export ADDITIONAL_FEATURES_OFF=false + if [ "${{ needs.check-comment.outputs.disable_security }}" == "true" ]; then + export DISABLE_ADDITIONAL_FEATURES=true else - export ADDITIONAL_FEATURES_OFF=true + export DISABLE_ADDITIONAL_FEATURES=false fi ./gradlew clean build env: @@ -199,7 +199,7 @@ jobs: id: deploy run: | # Set security settings based on flags - if [ "${{ needs.check-comment.outputs.enable_security }}" == "true" ]; then + if [ "${{ needs.check-comment.outputs.disable_security }}" == "false" ]; then DOCKER_SECURITY="true" LOGIN_SECURITY="true" SECURITY_STATUS="🔒 Security Enabled" @@ -223,7 +223,7 @@ jobs: - /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/config:/configs:rw - /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/logs:/logs:rw environment: - ADDITIONAL_FEATURES_OFF: "${DOCKER_SECURITY}" + DISABLE_ADDITIONAL_FEATURES: "${DOCKER_SECURITY}" SECURITY_ENABLELOGIN: "${LOGIN_SECURITY}" SYSTEM_DEFAULTLOCALE: en-GB UI_APPNAME: "Stirling-PDF PR#${{ needs.check-comment.outputs.pr_number }}" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 797a1bca0c..7274c568b0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,12 +40,12 @@ jobs: - name: Build with Gradle and no spring security run: ./gradlew clean build env: - ADDITIONAL_FEATURES_OFF: true + DISABLE_ADDITIONAL_FEATURES: true - name: Build with Gradle and with spring security run: ./gradlew clean build env: - ADDITIONAL_FEATURES_OFF: false + DISABLE_ADDITIONAL_FEATURES: false - name: Upload Test Reports if: always() diff --git a/.github/workflows/multiOSReleases.yml b/.github/workflows/multiOSReleases.yml index d10d8e8b69..c934b7129b 100644 --- a/.github/workflows/multiOSReleases.yml +++ b/.github/workflows/multiOSReleases.yml @@ -48,17 +48,12 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - enable_security: [true, false] disable_security: [true, false] include: - - enable_security: true - file_suffix: "-with-login" - - enable_security: false - file_suffix: "" - - disable_security: true - file_suffix: "" - disable_security: false file_suffix: "-with-login" + - disable_security: true + file_suffix: "" steps: - name: Harden Runner uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 @@ -77,10 +72,10 @@ jobs: with: gradle-version: 8.14 - - name: Generate jar (With Security=${{ matrix.enable_security }}) + - name: Generate jar (Disable Security=${{ matrix.disable_security }}) run: ./gradlew clean createExe env: - ADDITIONAL_FEATURES_OFF: ${{ matrix.disable_security }} + DISABLE_ADDITIONAL_FEATURES: ${{ matrix.disable_security }} STIRLING_PDF_DESKTOP_UI: false - name: Rename binaries @@ -103,11 +98,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - enable_security: [true, false] + disable_security: [true, false] include: - - enable_security: true + - disable_security: false file_suffix: "with-login-" - - enable_security: false + - disable_security: true file_suffix: "" steps: - name: Harden Runner @@ -176,7 +171,7 @@ jobs: - name: Build Installer run: ./gradlew build jpackage -x test --info env: - ADDITIONAL_FEATURES_OFF: true + DISABLE_ADDITIONAL_FEATURES: true STIRLING_PDF_DESKTOP_UI: true BROWSER_OPEN: true diff --git a/.github/workflows/push-docker.yml b/.github/workflows/push-docker.yml index 210007c728..03ea3464de 100644 --- a/.github/workflows/push-docker.yml +++ b/.github/workflows/push-docker.yml @@ -37,7 +37,7 @@ jobs: - name: Run Gradle Command run: ./gradlew clean build env: - ADDITIONAL_FEATURES_OFF: true + DISABLE_ADDITIONAL_FEATURES: true STIRLING_PDF_DESKTOP_UI: false - name: Install cosign diff --git a/.github/workflows/releaseArtifacts.yml b/.github/workflows/releaseArtifacts.yml index 09ad89312c..5434eec96f 100644 --- a/.github/workflows/releaseArtifacts.yml +++ b/.github/workflows/releaseArtifacts.yml @@ -13,17 +13,12 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - enable_security: [true, false] disable_security: [true, false] include: - - enable_security: true - file_suffix: "-with-login" - - enable_security: false - file_suffix: "" - - disable_security: true - file_suffix: "" - disable_security: false file_suffix: "-with-login" + - disable_security: true + file_suffix: "" outputs: version: ${{ steps.versionNumber.outputs.versionNumber }} steps: @@ -44,10 +39,10 @@ jobs: with: gradle-version: 8.14 - - name: Generate jar (With Security=${{ matrix.enable_security }}) + - name: Generate jar (Disable Security=${{ matrix.disable_security }}) run: ./gradlew clean createExe env: - ADDITIONAL_FEATURES_OFF: ${{ matrix.disable_security }} + DISABLE_ADDITIONAL_FEATURES: ${{ matrix.disable_security }} STIRLING_PDF_DESKTOP_UI: false - name: Get version number @@ -80,11 +75,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - enable_security: [true, false] + disable_security: [true, false] include: - - enable_security: true + - disable_security: false file_suffix: "-with-login" - - enable_security: false + - disable_security: true file_suffix: "" steps: - name: Harden Runner @@ -158,11 +153,11 @@ jobs: contents: write strategy: matrix: - enable_security: [true, false] + disable_security: [true, false] include: - - enable_security: true + - disable_security: false file_suffix: "-with-login" - - enable_security: false + - disable_security: true file_suffix: "" steps: - name: Harden Runner diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml index 5509d74bc0..16d004dd9f 100644 --- a/.github/workflows/sonarqube.yml +++ b/.github/workflows/sonarqube.yml @@ -33,7 +33,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - ADDITIONAL_FEATURES_OFF: false + DISABLE_ADDITIONAL_FEATURES: false STIRLING_PDF_DESKTOP_UI: true run: | ./gradlew clean build sonar \ diff --git a/.github/workflows/testdriver.yml b/.github/workflows/testdriver.yml index 27a8255a48..e4ef4138fc 100644 --- a/.github/workflows/testdriver.yml +++ b/.github/workflows/testdriver.yml @@ -28,7 +28,7 @@ jobs: - name: Build with Gradle run: ./gradlew clean build env: - ADDITIONAL_FEATURES_OFF: true + DISABLE_ADDITIONAL_FEATURES: true - name: Set up Docker Buildx uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 @@ -76,7 +76,7 @@ jobs: - /stirling/test-${{ github.sha }}/config:/configs:rw - /stirling/test-${{ github.sha }}/logs:/logs:rw environment: - ADDITIONAL_FEATURES_OFF: "true" + DISABLE_ADDITIONAL_FEATURES: "true" SECURITY_ENABLELOGIN: "false" SYSTEM_DEFAULTLOCALE: en-GB UI_APPNAME: "Stirling-PDF Test" diff --git a/DeveloperGuide.md b/DeveloperGuide.md index cb4c4827aa..f9b8833b84 100644 --- a/DeveloperGuide.md +++ b/DeveloperGuide.md @@ -55,7 +55,7 @@ Stirling-PDF uses Lombok to reduce boilerplate code. Some IDEs, like Eclipse, do Visit the [Lombok website](https://projectlombok.org/setup/) for installation instructions specific to your IDE. 5. Add environment variable -For local testing, you should generally be testing the full 'Security' version of Stirling-PDF. To do this, you must add the environment flag ADDITIONAL_FEATURES_OFF=false to your system and/or IDE build/run step. +For local testing, you should generally be testing the full 'Security' version of Stirling-PDF. To do this, you must add the environment flag DISABLE_ADDITIONAL_FEATURES=false to your system and/or IDE build/run step. ## 4. Project Structure @@ -141,7 +141,7 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - ADDITIONAL_FEATURES_OFF: "false" + DISABLE_ADDITIONAL_FEATURES: "false" SECURITY_ENABLELOGIN: "true" PUID: 1002 PGID: 1002 @@ -170,7 +170,7 @@ Stirling-PDF uses different Docker images for various configurations. The build 1. Set the security environment variable: ```bash - export ADDITIONAL_FEATURES_OFF=true # or false for security-enabled builds + export DISABLE_ADDITIONAL_FEATURES=true # or false for security-enabled builds ``` 2. Build the project with Gradle: @@ -196,7 +196,7 @@ Stirling-PDF uses different Docker images for various configurations. The build For the fat version (with security enabled): ```bash - export ADDITIONAL_FEATURES_OFF=false + export DISABLE_ADDITIONAL_FEATURES=false docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-fat -f ./Dockerfile.fat . ``` diff --git a/Dockerfile b/Dockerfile index ad8f7c5903..bef88cd98e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ LABEL org.opencontainers.image.version="${VERSION_TAG}" LABEL org.opencontainers.image.keywords="PDF, manipulation, merge, split, convert, OCR, watermark" # Set Environment Variables -ENV ADDITIONAL_FEATURES_OFF=true \ +ENV DISABLE_ADDITIONAL_FEATURES=true \ VERSION_TAG=$VERSION_TAG \ JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \ JAVA_CUSTOM_OPTS="" \ diff --git a/Dockerfile.fat b/Dockerfile.fat index e742dd43b8..20ce8030f4 100644 --- a/Dockerfile.fat +++ b/Dockerfile.fat @@ -15,8 +15,8 @@ WORKDIR /app # Copy the entire project to the working directory COPY . . -# Build the application with ADDITIONAL_FEATURES_OFF=false -RUN ADDITIONAL_FEATURES_OFF=false \ +# Build the application with DISABLE_ADDITIONAL_FEATURES=false +RUN DISABLE_ADDITIONAL_FEATURES=false \ STIRLING_PDF_DESKTOP_UI=false \ ./gradlew clean build -x spotlessApply -x spotlessCheck -x test -x sonarqube @@ -32,7 +32,7 @@ COPY --from=build /app/build/libs/*.jar app.jar ARG VERSION_TAG # Set Environment Variables -ENV ADDITIONAL_FEATURES_OFF=true \ +ENV DISABLE_ADDITIONAL_FEATURES=true \ VERSION_TAG=$VERSION_TAG \ JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \ JAVA_CUSTOM_OPTS="" \ diff --git a/Dockerfile.ultra-lite b/Dockerfile.ultra-lite index 3b54091b1a..6da0990f93 100644 --- a/Dockerfile.ultra-lite +++ b/Dockerfile.ultra-lite @@ -4,7 +4,7 @@ FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be02 ARG VERSION_TAG # Set Environment Variables -ENV ADDITIONAL_FEATURES_OFF=true \ +ENV DISABLE_ADDITIONAL_FEATURES=true \ HOME=/home/stirlingpdfuser \ VERSION_TAG=$VERSION_TAG \ JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \ diff --git a/build.gradle b/build.gradle index 987b4b14fb..7cdc6683bd 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ plugins { id "com.diffplug.spotless" version "7.0.4" id "com.github.jk1.dependency-license-report" version "2.9" //id "nebula.lint" version "19.0.3" - id("org.panteleyev.jpackageplugin") version "1.6.1" + id "org.panteleyev.jpackageplugin" version "1.6.1" id "org.sonarqube" version "6.2.0.5505" } @@ -51,9 +51,9 @@ licenseReport { sourceSets { main { java { - if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('ADDITIONAL_FEATURES_OFF') == 'false' - || (project.hasProperty('ADDITIONAL_FEATURES_OFF') - && System.getProperty('ADDITIONAL_FEATURES_OFF'))) { + if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('DISABLE_ADDITIONAL_FEATURES') == 'true' + || (project.hasProperty('DISABLE_ADDITIONAL_FEATURES') + && System.getProperty('DISABLE_ADDITIONAL_FEATURES') == 'true')) { exclude 'stirling/software/proprietary/security/**' } @@ -66,9 +66,9 @@ sourceSets { test { java { - if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('ADDITIONAL_FEATURES_OFF') == 'false' - || (project.hasProperty('ADDITIONAL_FEATURES_OFF') - && System.getProperty('ADDITIONAL_FEATURES_OFF'))) { + if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('DISABLE_ADDITIONAL_FEATURES') == 'true' + || (project.hasProperty('DISABLE_ADDITIONAL_FEATURES') + && System.getProperty('DISABLE_ADDITIONAL_FEATURES') == 'true')) { exclude 'stirling/software/proprietary/security/**' } @@ -285,18 +285,18 @@ tasks.register('downloadTempJre') { def jreArchive = new File(tmpDir, 'jre.tar.gz') def jreDir = new File(tmpDir, 'jre') - println "🔽 Downloading JRE to $jreArchive..." + println "Downloading JRE to $jreArchive..." jreArchive.withOutputStream { out -> new URI(jreUrl).toURL().withInputStream { from -> out << from } } - println "📦 Extracting JRE to $jreDir..." + println "Extracting JRE to $jreDir..." jreDir.mkdirs() providers.exec { commandLine 'tar', '-xzf', jreArchive.absolutePath, '-C', jreDir.absolutePath, '--strip-components=1' }.result.get() - println "✅ JRE ready at: $jreDir" + println "JRE ready at: $jreDir" ext.tempJrePath = jreDir.absolutePath project.ext.tempJrePath = jreDir.absolutePath } catch (Exception e) { @@ -431,7 +431,7 @@ dependencies { implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1' implementation 'org.snakeyaml:snakeyaml-engine:2.9' - if (System.getenv("DOCKER_ENABLE_SECURITY") != "false" || System.getenv("ADDITIONAL_FEATURES_OFF") == "false") { + if (System.getenv("DOCKER_ENABLE_SECURITY") != "false" && System.getenv("DISABLE_ADDITIONAL_FEATURES") != "true") { implementation project(':proprietary') } diff --git a/common/gradle/wrapper/gradle-wrapper.properties b/common/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index f7664bccf7..0000000000 --- a/common/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/common/gradlew b/common/gradlew deleted file mode 100755 index 23d15a9367..0000000000 --- a/common/gradlew +++ /dev/null @@ -1,251 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH="\\\"\\\"" - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/common/gradlew.bat b/common/gradlew.bat deleted file mode 100644 index db3a6ac207..0000000000 --- a/common/gradlew.bat +++ /dev/null @@ -1,94 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH= - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/common/src/main/java/stirling/software/common/configuration/AppConfig.java b/common/src/main/java/stirling/software/common/configuration/AppConfig.java index f6b8b2d454..6c243eb59b 100644 --- a/common/src/main/java/stirling/software/common/configuration/AppConfig.java +++ b/common/src/main/java/stirling/software/common/configuration/AppConfig.java @@ -148,10 +148,16 @@ public class AppConfig { } @Bean(name = "activeSecurity") - @ConditionalOnClass( - name = "stirling.software.proprietary.security.configuration.SecurityConfiguration") public boolean activeSecurity() { - return true; + String additionalFeaturesOff = env.getProperty("DISABLE_ADDITIONAL_FEATURES"); + + if (additionalFeaturesOff != null) { + // DISABLE_ADDITIONAL_FEATURES=true means security OFF, so return false + // DISABLE_ADDITIONAL_FEATURES=false means security ON, so return true + return !Boolean.parseBoolean(additionalFeaturesOff); + } + + return env.getProperty("DOCKER_ENABLE_SECURITY", Boolean.class, true); } @Bean(name = "missingActiveSecurity") diff --git a/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml b/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml index 4f3b25948d..827de1e193 100644 --- a/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml +++ b/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml @@ -20,7 +20,7 @@ services: - ./stirling/latest/logs:/logs:rw - ../testing/allEndpointsRemovedSettings.yml:/configs/settings.yml:rw environment: - ADDITIONAL_FEATURES_OFF: "false" + DISABLE_ADDITIONAL_FEATURES: "false" SECURITY_ENABLELOGIN: "false" PUID: 1002 PGID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml b/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml index f38ed84e21..bbf8a2115d 100644 --- a/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml +++ b/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml @@ -20,7 +20,7 @@ services: - ./stirling/latest/config:/configs:rw - ./stirling/latest/logs:/logs:rw environment: - ADDITIONAL_FEATURES_OFF: "false" + DISABLE_ADDITIONAL_FEATURES: "false" SECURITY_ENABLELOGIN: "false" PUID: 1002 PGID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-fat-security.yml b/exampleYmlFiles/docker-compose-latest-fat-security.yml index 88441ee9ac..5b07420ff3 100644 --- a/exampleYmlFiles/docker-compose-latest-fat-security.yml +++ b/exampleYmlFiles/docker-compose-latest-fat-security.yml @@ -18,7 +18,7 @@ services: - ./stirling/latest/config:/configs:rw - ./stirling/latest/logs:/logs:rw environment: - ADDITIONAL_FEATURES_OFF: "false" + DISABLE_ADDITIONAL_FEATURES: "false" SECURITY_ENABLELOGIN: "false" PUID: 1002 PGID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-security-with-sso.yml b/exampleYmlFiles/docker-compose-latest-security-with-sso.yml index 947ddc4479..89d0fc94e1 100644 --- a/exampleYmlFiles/docker-compose-latest-security-with-sso.yml +++ b/exampleYmlFiles/docker-compose-latest-security-with-sso.yml @@ -18,7 +18,7 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - ADDITIONAL_FEATURES_OFF: "false" + DISABLE_ADDITIONAL_FEATURES: "false" SECURITY_ENABLELOGIN: "true" SECURITY_OAUTH2_ENABLED: "true" SECURITY_OAUTH2_AUTOCREATEUSER: "true" # This is set to true to allow auto-creation of non-existing users in Stirling-PDF diff --git a/exampleYmlFiles/docker-compose-latest-security.yml b/exampleYmlFiles/docker-compose-latest-security.yml index fa8d768889..c6589ab9c7 100644 --- a/exampleYmlFiles/docker-compose-latest-security.yml +++ b/exampleYmlFiles/docker-compose-latest-security.yml @@ -18,7 +18,7 @@ services: - ./stirling/latest/config:/configs:rw - ./stirling/latest/logs:/logs:rw environment: - ADDITIONAL_FEATURES_OFF: "false" + DISABLE_ADDITIONAL_FEATURES: "false" SECURITY_ENABLELOGIN: "true" PUID: 1002 PGID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml b/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml index 434bbcd613..c927ab7068 100644 --- a/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml +++ b/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml @@ -18,7 +18,7 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - ADDITIONAL_FEATURES_OFF: "false" + DISABLE_ADDITIONAL_FEATURES: "false" SECURITY_ENABLELOGIN: "true" SYSTEM_DEFAULTLOCALE: en-US UI_APPNAME: Stirling-PDF-Lite diff --git a/exampleYmlFiles/docker-compose-latest-ultra-lite.yml b/exampleYmlFiles/docker-compose-latest-ultra-lite.yml index 484acf2698..d3e1b97591 100644 --- a/exampleYmlFiles/docker-compose-latest-ultra-lite.yml +++ b/exampleYmlFiles/docker-compose-latest-ultra-lite.yml @@ -17,7 +17,7 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - ADDITIONAL_FEATURES_OFF: "true" + DISABLE_ADDITIONAL_FEATURES: "true" SECURITY_ENABLELOGIN: "false" SYSTEM_DEFAULTLOCALE: en-US UI_APPNAME: Stirling-PDF-Ultra-lite diff --git a/exampleYmlFiles/docker-compose-latest.yml b/exampleYmlFiles/docker-compose-latest.yml index 46cfe35536..d8b1aee749 100644 --- a/exampleYmlFiles/docker-compose-latest.yml +++ b/exampleYmlFiles/docker-compose-latest.yml @@ -18,7 +18,7 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - ADDITIONAL_FEATURES_OFF: "true" + DISABLE_ADDITIONAL_FEATURES: "true" SECURITY_ENABLELOGIN: "false" LANGS: "en_GB,en_US,ar_AR,de_DE,fr_FR,es_ES,zh_CN,zh_TW,ca_CA,it_IT,sv_SE,pl_PL,ro_RO,ko_KR,pt_BR,ru_RU,el_GR,hi_IN,hu_HU,tr_TR,id_ID" SYSTEM_DEFAULTLOCALE: en-US diff --git a/exampleYmlFiles/test_cicd.yml b/exampleYmlFiles/test_cicd.yml index c76471bd84..749e863a31 100644 --- a/exampleYmlFiles/test_cicd.yml +++ b/exampleYmlFiles/test_cicd.yml @@ -18,7 +18,7 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - ADDITIONAL_FEATURES_OFF: "false" + DISABLE_ADDITIONAL_FEATURES: "false" SECURITY_ENABLELOGIN: "true" PUID: 1002 PGID: 1002 diff --git a/proprietary/gradle/wrapper/gradle-wrapper.properties b/proprietary/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index f7664bccf7..0000000000 --- a/proprietary/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/proprietary/gradlew b/proprietary/gradlew deleted file mode 100755 index 23d15a9367..0000000000 --- a/proprietary/gradlew +++ /dev/null @@ -1,251 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH="\\\"\\\"" - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/proprietary/gradlew.bat b/proprietary/gradlew.bat deleted file mode 100644 index db3a6ac207..0000000000 --- a/proprietary/gradlew.bat +++ /dev/null @@ -1,94 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH= - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java index 82d794d6ea..c9b6e9d77d 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java @@ -10,6 +10,7 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; /** diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java index 0fd356da20..b364f37388 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java @@ -14,7 +14,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; -import stirling.software.common.model.enumeration.Role; import stirling.software.common.model.enumeration.Role; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java index 92b053b8ae..7175a5b5d6 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java @@ -1,10 +1,7 @@ package stirling.software.proprietary.security.oauth2; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import lombok.extern.slf4j.Slf4j; + import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.LockedException; @@ -13,6 +10,12 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + @Slf4j public class CustomOAuth2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java index c2957e2413..fff03fd4f5 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java @@ -6,6 +6,7 @@ import java.nio.charset.StandardCharsets; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; + import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java index 055ac8f4e1..a39a390927 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java @@ -3,6 +3,7 @@ package stirling.software.proprietary.security.saml2; import java.io.Serializable; import java.util.List; import java.util.Map; + import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java index a7e663aac0..7bf0c3a3b3 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java @@ -1,9 +1,7 @@ package stirling.software.proprietary.security.saml2; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import lombok.extern.slf4j.Slf4j; + import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.security.authentication.ProviderNotFoundException; import org.springframework.security.core.AuthenticationException; @@ -11,6 +9,11 @@ import org.springframework.security.saml2.core.Saml2Error; import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + @Slf4j @ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true") public class CustomSaml2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java index 836419ea0f..233bcaaddf 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java @@ -1,11 +1,9 @@ package stirling.software.proprietary.security.saml2; -import jakarta.servlet.http.HttpServletRequest; import java.security.cert.X509Certificate; import java.util.Collections; import java.util.UUID; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; + import org.opensaml.saml.saml2.core.AuthnRequest; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -21,6 +19,12 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; import org.springframework.security.saml2.provider.service.web.HttpSessionSaml2AuthenticationRequestRepository; import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver; + +import jakarta.servlet.http.HttpServletRequest; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.SAML2; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java index 6c1d334f5e..eccd7332e5 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java @@ -3,7 +3,6 @@ package stirling.software.proprietary.security.session; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.core.session.SessionRegistryImpl; -import stirling.software.proprietary.security.database.repository.SessionRepository; import stirling.software.proprietary.security.database.repository.SessionRepository; @@ -16,7 +15,8 @@ public class SessionRegistryConfig { } @Bean - public SessionPersistentRegistry sessionPersistentRegistry(SessionRepository sessionRepository) { + public SessionPersistentRegistry sessionPersistentRegistry( + SessionRepository sessionRepository) { return new SessionPersistentRegistry(sessionRepository); } } diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java index 83403f9f74..1f491bf4d6 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java @@ -4,11 +4,13 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.List; -import lombok.RequiredArgsConstructor; + import org.springframework.scheduling.annotation.Scheduled; import org.springframework.security.core.session.SessionInformation; import org.springframework.stereotype.Component; +import lombok.RequiredArgsConstructor; + @Component @RequiredArgsConstructor public class SessionScheduled { diff --git a/scripts/download-security-jar.sh b/scripts/download-security-jar.sh index bee188d972..d49cf36055 100644 --- a/scripts/download-security-jar.sh +++ b/scripts/download-security-jar.sh @@ -1,6 +1,6 @@ -echo "Running Stirling PDF with ADDITIONAL_FEATURES_OFF=${ADDITIONAL_FEATURES_OFF} and VERSION_TAG=${VERSION_TAG}" -# Check for $ADDITIONAL_FEATURES_OFF and download the appropriate JAR if required -if [ "$ADDITIONAL_FEATURES_OFF" = "false" ] && [ "$VERSION_TAG" != "alpha" ]; then +echo "Running Stirling PDF with DISABLE_ADDITIONAL_FEATURES=${DISABLE_ADDITIONAL_FEATURES} and VERSION_TAG=${VERSION_TAG}" +# Check for $DISABLE_ADDITIONAL_FEATURES and download the appropriate JAR if required +if [ "$DISABLE_ADDITIONAL_FEATURES" = "false" ] && [ "$VERSION_TAG" != "alpha" ]; then if [ ! -f app-security.jar ]; then echo "Trying to download from: https://files.stirlingpdf.com/v$VERSION_TAG/Stirling-PDF-with-login.jar" curl -L -o app-security.jar https://files.stirlingpdf.com/v$VERSION_TAG/Stirling-PDF-with-login.jar diff --git a/testing/test.sh b/testing/test.sh index 0891c6bbd2..51f63b453d 100644 --- a/testing/test.sh +++ b/testing/test.sh @@ -214,7 +214,7 @@ main() { export DOCKER_CLI_EXPERIMENTAL=enabled export COMPOSE_DOCKER_CLI_BUILD=0 - export ADDITIONAL_FEATURES_OFF=true + export DISABLE_ADDITIONAL_FEATURES=true # Run the gradlew build command and check if it fails if ! ./gradlew clean build; then echo "Gradle build failed with security disabled, exiting script." @@ -242,7 +242,7 @@ main() { # run_tests "Stirling-PDF" "./exampleYmlFiles/docker-compose-latest.yml" # docker-compose -f "./exampleYmlFiles/docker-compose-latest.yml" down - export ADDITIONAL_FEATURES_OFF=false + export DISABLE_ADDITIONAL_FEATURES=false # Run the gradlew build command and check if it fails if ! ./gradlew clean build; then echo "Gradle build failed with security enabled, exiting script." From 2df70daf169169cef8162f48993f60ab73d5cce3 Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Wed, 4 Jun 2025 16:31:40 +0100 Subject: [PATCH 13/15] updated jpackage --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index 7cdc6683bd..3d003bb85b 100644 --- a/build.gradle +++ b/build.gradle @@ -110,6 +110,7 @@ jpackage { javaOptions = [ "-DBROWSER_OPEN=true", "-DSTIRLING_PDF_DESKTOP_UI=true", + "-DDISABLE_ADDITIONAL_FEATURES=false", "-Djava.awt.headless=false", "-Dapple.awt.UIElement=true", "--add-opens=java.base/java.lang=ALL-UNNAMED", @@ -246,6 +247,7 @@ tasks.register('jpackageMacX64') { // Java options '--java-options', '-DBROWSER_OPEN=true', '--java-options', '-DSTIRLING_PDF_DESKTOP_UI=true', + '--java-options', '-DDISABLE_ADDITIONAL_FEATURES=false', '--java-options', '-Djava.awt.headless=false', '--java-options', '-Dapple.awt.UIElement=true', '--java-options', '--add-opens=java.base/java.lang=ALL-UNNAMED', From 6cef1fac5f30fddd11211dc6f041a88f88139c9e Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Wed, 4 Jun 2025 17:18:41 +0100 Subject: [PATCH 14/15] renamed proprietary/LICENSE and fixed main LICENSE --- LICENSE | 7 ------- proprietary/{LICENSE-proprietary => LICENSE} | 0 2 files changed, 7 deletions(-) rename proprietary/{LICENSE-proprietary => LICENSE} (100%) diff --git a/LICENSE b/LICENSE index 62cd6e5cc1..8776631713 100644 --- a/LICENSE +++ b/LICENSE @@ -9,13 +9,6 @@ if that directory exists, is licensed under the license defined in "proprietary/ * Content outside of the above mentioned directories or restrictions above is available under the MIT License as defined below. -Portions of this software are licensed as follows: - -* All content that resides under the "proprietary/" directory of this repository, -if that directory exists, is licensed under the license defined in "proprietary/LICENSE". -* Content outside of the above mentioned directories or restrictions above is -available under the MIT License as defined below. - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights diff --git a/proprietary/LICENSE-proprietary b/proprietary/LICENSE similarity index 100% rename from proprietary/LICENSE-proprietary rename to proprietary/LICENSE From 0006a77b5da1276217bfc9bcc5d36dc1d85fce07 Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Thu, 5 Jun 2025 10:35:52 +0100 Subject: [PATCH 15/15] updated comments in DeveloperGuide.md --- DeveloperGuide.md | 12 ++++++------ build.gradle | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/DeveloperGuide.md b/DeveloperGuide.md index f9b8833b84..d484838e09 100644 --- a/DeveloperGuide.md +++ b/DeveloperGuide.md @@ -55,7 +55,7 @@ Stirling-PDF uses Lombok to reduce boilerplate code. Some IDEs, like Eclipse, do Visit the [Lombok website](https://projectlombok.org/setup/) for installation instructions specific to your IDE. 5. Add environment variable -For local testing, you should generally be testing the full 'Security' version of Stirling-PDF. To do this, you must add the environment flag DISABLE_ADDITIONAL_FEATURES=false to your system and/or IDE build/run step. +For local testing, you should generally be testing the full 'Security' version of Stirling PDF. To do this, you must add the environment flag DISABLE_ADDITIONAL_FEATURES=false to your system and/or IDE build/run step. ## 4. Project Structure @@ -114,9 +114,9 @@ Stirling-PDF offers several Docker versions: Stirling-PDF provides several example Docker Compose files in the `exampleYmlFiles` directory, such as: -- `docker-compose-latest.yml`: Latest version without security features -- `docker-compose-latest-security.yml`: Latest version with security features enabled -- `docker-compose-latest-fat-security.yml`: Fat version with security features enabled +- `docker-compose-latest.yml`: Latest version without login and security features +- `docker-compose-latest-security.yml`: Latest version with login and security features enabled +- `docker-compose-latest-fat-security.yml`: Fat version with login and security features enabled These files provide pre-configured setups for different scenarios. For example, here's a snippet from `docker-compose-latest-security.yml`: @@ -170,7 +170,7 @@ Stirling-PDF uses different Docker images for various configurations. The build 1. Set the security environment variable: ```bash - export DISABLE_ADDITIONAL_FEATURES=true # or false for security-enabled builds + export DISABLE_ADDITIONAL_FEATURES=true # or false for to enable login and security features for builds ``` 2. Build the project with Gradle: @@ -193,7 +193,7 @@ Stirling-PDF uses different Docker images for various configurations. The build docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite . ``` - For the fat version (with security enabled): + For the fat version (with login and security features enabled): ```bash export DISABLE_ADDITIONAL_FEATURES=false diff --git a/build.gradle b/build.gradle index 3d003bb85b..6ca36d7275 100644 --- a/build.gradle +++ b/build.gradle @@ -433,7 +433,9 @@ dependencies { implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1' implementation 'org.snakeyaml:snakeyaml-engine:2.9' - if (System.getenv("DOCKER_ENABLE_SECURITY") != "false" && System.getenv("DISABLE_ADDITIONAL_FEATURES") != "true") { + if (System.getenv("DOCKER_ENABLE_SECURITY") != "false" || System.getenv('DISABLE_ADDITIONAL_FEATURES') != 'true' + || (project.hasProperty('DISABLE_ADDITIONAL_FEATURES') + && System.getProperty('DISABLE_ADDITIONAL_FEATURES') != 'true')) { implementation project(':proprietary') }