diff --git a/build.gradle b/build.gradle index d3e0d430..2c9e9f48 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ ext { } group = "stirling.software" -version = "0.45.0" +version = "0.45.1" java { // 17 is lowest but we support and recommend 21 diff --git a/src/main/java/stirling/software/SPDF/EE/EEAppConfig.java b/src/main/java/stirling/software/SPDF/EE/EEAppConfig.java index b651b853..f1df7d34 100644 --- a/src/main/java/stirling/software/SPDF/EE/EEAppConfig.java +++ b/src/main/java/stirling/software/SPDF/EE/EEAppConfig.java @@ -7,6 +7,7 @@ import org.springframework.core.annotation.Order; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.EE.KeygenLicenseVerifier.License; import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.model.ApplicationProperties.EnterpriseEdition; import stirling.software.SPDF.model.ApplicationProperties.Premium; @@ -27,9 +28,14 @@ public class EEAppConfig { migrateEnterpriseSettingsToPremium(this.applicationProperties); } + @Bean(name = "runningProOrHigher") + public boolean runningProOrHigher() { + return licenseKeyChecker.getPremiumLicenseEnabledResult() != License.NORMAL; + } + @Bean(name = "runningEE") - public boolean runningEnterpriseEdition() { - return licenseKeyChecker.getEnterpriseEnabledResult(); + public boolean runningEnterprise() { + return licenseKeyChecker.getPremiumLicenseEnabledResult() == License.ENTERPRISE; } @Bean(name = "SSOAutoLogin") diff --git a/src/main/java/stirling/software/SPDF/EE/KeygenLicenseVerifier.java b/src/main/java/stirling/software/SPDF/EE/KeygenLicenseVerifier.java index 28e0c7e7..20e3e803 100644 --- a/src/main/java/stirling/software/SPDF/EE/KeygenLicenseVerifier.java +++ b/src/main/java/stirling/software/SPDF/EE/KeygenLicenseVerifier.java @@ -25,6 +25,13 @@ import stirling.software.SPDF.utils.GeneralUtils; @Service @Slf4j public class KeygenLicenseVerifier { + + enum License { + NORMAL, + PRO, + ENTERPRISE + } + // License verification configuration private static final String ACCOUNT_ID = "e5430f69-e834-4ae4-befd-b602aae5f372"; private static final String BASE_URL = "https://api.keygen.sh/v1/accounts"; @@ -45,19 +52,26 @@ public class KeygenLicenseVerifier { this.applicationProperties = applicationProperties; } - public boolean verifyLicense(String licenseKeyOrCert) { + public License verifyLicense(String licenseKeyOrCert) { if (isCertificateLicense(licenseKeyOrCert)) { log.info("Detected certificate-based license. Processing..."); - return verifyCertificateLicense(licenseKeyOrCert); + return resultToEnum(verifyCertificateLicense(licenseKeyOrCert), License.ENTERPRISE); } else if (isJWTLicense(licenseKeyOrCert)) { log.info("Detected JWT-style license key. Processing..."); - return verifyJWTLicense(licenseKeyOrCert); + return resultToEnum(verifyJWTLicense(licenseKeyOrCert), License.ENTERPRISE); } else { log.info("Detected standard license key. Processing..."); - return verifyStandardLicense(licenseKeyOrCert); + return resultToEnum(verifyStandardLicense(licenseKeyOrCert), License.PRO); } } + private License resultToEnum(boolean result, License option) { + if (result) { + return option; + } + return License.NORMAL; + } + private boolean isCertificateLicense(String license) { return license != null && license.trim().startsWith(CERT_PREFIX); } diff --git a/src/main/java/stirling/software/SPDF/EE/LicenseKeyChecker.java b/src/main/java/stirling/software/SPDF/EE/LicenseKeyChecker.java index d2935112..d788504c 100644 --- a/src/main/java/stirling/software/SPDF/EE/LicenseKeyChecker.java +++ b/src/main/java/stirling/software/SPDF/EE/LicenseKeyChecker.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Component; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.EE.KeygenLicenseVerifier.License; import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.utils.GeneralUtils; @@ -24,7 +25,7 @@ public class LicenseKeyChecker { private final ApplicationProperties applicationProperties; - private boolean premiumEnabledResult = false; + private License premiumEnabledResult = License.NORMAL; @Autowired public LicenseKeyChecker( @@ -41,19 +42,21 @@ public class LicenseKeyChecker { private void checkLicense() { if (!applicationProperties.getPremium().isEnabled()) { - premiumEnabledResult = false; + premiumEnabledResult = License.NORMAL; } else { String licenseKey = getLicenseKeyContent(applicationProperties.getPremium().getKey()); if (licenseKey != null) { premiumEnabledResult = licenseService.verifyLicense(licenseKey); - if (premiumEnabledResult) { - log.info("License key is valid."); + if (License.ENTERPRISE == premiumEnabledResult) { + log.info("License key is Enterprise."); + } else if (License.PRO == premiumEnabledResult) { + log.info("License key is Pro."); } else { - log.info("License key is invalid."); + log.info("License key is invalid, defaulting to non pro license."); } } else { log.error("Failed to obtain license key content."); - premiumEnabledResult = false; + premiumEnabledResult = License.NORMAL; } } } @@ -91,7 +94,7 @@ public class LicenseKeyChecker { checkLicense(); } - public boolean getEnterpriseEnabledResult() { + public License getPremiumLicenseEnabledResult() { return premiumEnabledResult; } } diff --git a/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java b/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java index 9c2d2654..f36b2c72 100644 --- a/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java +++ b/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -23,14 +22,14 @@ public class EndpointConfiguration { private final ApplicationProperties applicationProperties; private Map endpointStatuses = new ConcurrentHashMap<>(); private Map> endpointGroups = new ConcurrentHashMap<>(); - private final boolean runningEE; + private final boolean runningProOrHigher; @Autowired public EndpointConfiguration( ApplicationProperties applicationProperties, - @Qualifier("runningEE") boolean runningEE) { + @Qualifier("runningProOrHigher") boolean runningProOrHigher) { this.applicationProperties = applicationProperties; - this.runningEE = runningEE; + this.runningProOrHigher = runningProOrHigher; init(); processEnvironmentConfigs(); } @@ -98,7 +97,7 @@ public class EndpointConfiguration { // is false) .map(Map.Entry::getKey) .sorted() - .collect(Collectors.toList()); + .toList(); if (!disabledList.isEmpty()) { log.info( @@ -286,7 +285,7 @@ public class EndpointConfiguration { } } } - if (!runningEE) { + if (!runningProOrHigher) { disableGroup("enterprise"); } diff --git a/src/main/java/stirling/software/SPDF/config/EnterpriseEndpointFilter.java b/src/main/java/stirling/software/SPDF/config/EnterpriseEndpointFilter.java index e0534b99..040e0e07 100644 --- a/src/main/java/stirling/software/SPDF/config/EnterpriseEndpointFilter.java +++ b/src/main/java/stirling/software/SPDF/config/EnterpriseEndpointFilter.java @@ -14,10 +14,10 @@ import jakarta.servlet.http.HttpServletResponse; @Component public class EnterpriseEndpointFilter extends OncePerRequestFilter { - private final boolean runningEE; + private final boolean runningProOrHigher; - public EnterpriseEndpointFilter(@Qualifier("runningEE") boolean runningEE) { - this.runningEE = runningEE; + public EnterpriseEndpointFilter(@Qualifier("runningProOrHigher") boolean runningProOrHigher) { + this.runningProOrHigher = runningProOrHigher; } @Override @@ -25,7 +25,7 @@ public class EnterpriseEndpointFilter extends OncePerRequestFilter { HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - if (!runningEE && isPrometheusEndpointRequest(request)) { + if (!runningProOrHigher && isPrometheusEndpointRequest(request)) { response.setStatus(HttpStatus.NOT_FOUND.value()); return; } diff --git a/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java b/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java index 3a77dd08..6ff5c271 100644 --- a/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java +++ b/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java @@ -62,7 +62,7 @@ public class ExternalAppDepConfig { private List getAffectedFeatures(String group) { return endpointConfiguration.getEndpointsForGroup(group).stream() .map(endpoint -> formatEndpointAsFeature(endpoint)) - .collect(Collectors.toList()); + .toList(); } private String formatEndpointAsFeature(String endpoint) { diff --git a/src/main/java/stirling/software/SPDF/config/security/CustomUserDetailsService.java b/src/main/java/stirling/software/SPDF/config/security/CustomUserDetailsService.java index 69b06ec1..d0ee65f3 100644 --- a/src/main/java/stirling/software/SPDF/config/security/CustomUserDetailsService.java +++ b/src/main/java/stirling/software/SPDF/config/security/CustomUserDetailsService.java @@ -2,7 +2,6 @@ package stirling.software.SPDF.config.security; import java.util.Collection; import java.util.Set; -import java.util.stream.Collectors; import org.springframework.security.authentication.LockedException; import org.springframework.security.core.GrantedAuthority; @@ -58,6 +57,6 @@ public class CustomUserDetailsService implements UserDetailsService { private Collection getAuthorities(Set authorities) { return authorities.stream() .map(authority -> new SimpleGrantedAuthority(authority.getAuthority())) - .collect(Collectors.toList()); + .toList(); } } diff --git a/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java b/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java index 3fd9db48..6ff37a9d 100644 --- a/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java +++ b/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java @@ -46,13 +46,13 @@ import stirling.software.SPDF.repository.PersistentLoginRepository; @EnableWebSecurity @EnableMethodSecurity @Slf4j -@DependsOn("runningEE") +@DependsOn("runningProOrHigher") public class SecurityConfiguration { private final CustomUserDetailsService userDetailsService; private final UserService userService; private final boolean loginEnabledValue; - private final boolean runningEE; + private final boolean runningProOrHigher; private final ApplicationProperties applicationProperties; private final UserAuthenticationFilter userAuthenticationFilter; @@ -69,7 +69,7 @@ public class SecurityConfiguration { CustomUserDetailsService userDetailsService, @Lazy UserService userService, @Qualifier("loginEnabled") boolean loginEnabledValue, - @Qualifier("runningEE") boolean runningEE, + @Qualifier("runningProOrHigher") boolean runningProOrHigher, ApplicationProperties applicationProperties, UserAuthenticationFilter userAuthenticationFilter, LoginAttemptService loginAttemptService, @@ -83,7 +83,7 @@ public class SecurityConfiguration { this.userDetailsService = userDetailsService; this.userService = userService; this.loginEnabledValue = loginEnabledValue; - this.runningEE = runningEE; + this.runningProOrHigher = runningProOrHigher; this.applicationProperties = applicationProperties; this.userAuthenticationFilter = userAuthenticationFilter; this.loginAttemptService = loginAttemptService; @@ -254,7 +254,7 @@ public class SecurityConfiguration { .permitAll()); } // Handle SAML - if (applicationProperties.getSecurity().isSaml2Active() && runningEE) { + if (applicationProperties.getSecurity().isSaml2Active() && runningProOrHigher) { // Configure the authentication provider OpenSaml4AuthenticationProvider authenticationProvider = new OpenSaml4AuthenticationProvider(); 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 6ddd893a..b2e9d184 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java +++ b/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java @@ -3,7 +3,6 @@ package stirling.software.SPDF.config.security; import java.io.IOException; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Lazy; @@ -86,7 +85,7 @@ public class UserAuthenticationFilter extends OncePerRequestFilter { authority -> new SimpleGrantedAuthority( authority.getAuthority())) - .collect(Collectors.toList()); + .toList(); authentication = new ApiKeyAuthenticationToken(user.get(), apiKey, authorities); SecurityContextHolder.getContext().setAuthentication(authentication); } catch (AuthenticationException e) { 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 49cd7dfd..e585d677 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserService.java +++ b/src/main/java/stirling/software/SPDF/config/security/UserService.java @@ -3,7 +3,6 @@ package stirling.software.SPDF.config.security; import java.io.IOException; import java.sql.SQLException; import java.util.*; -import java.util.stream.Collectors; import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; @@ -107,7 +106,7 @@ public class UserService implements UserServiceInterface { // Convert each Authority object into a SimpleGrantedAuthority object. return user.getAuthorities().stream() .map((Authority authority) -> new SimpleGrantedAuthority(authority.getAuthority())) - .collect(Collectors.toList()); + .toList(); } private String generateApiKey() { 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 ba4a02f0..d221704e 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 @@ -27,18 +27,18 @@ public class DatabaseConfig { public static final String POSTGRES_DRIVER = "org.postgresql.Driver"; private final ApplicationProperties applicationProperties; - private final boolean runningEE; + private final boolean runningProOrHigher; public DatabaseConfig( ApplicationProperties applicationProperties, - @Qualifier("runningEE") boolean runningEE) { + @Qualifier("runningProOrHigher") boolean runningProOrHigher) { DATASOURCE_DEFAULT_URL = "jdbc:h2:file:" + InstallationPathConfig.getConfigPath() + "stirling-pdf-DB-2.3.232;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"; log.debug("Database URL: {}", DATASOURCE_DEFAULT_URL); this.applicationProperties = applicationProperties; - this.runningEE = runningEE; + this.runningProOrHigher = runningProOrHigher; } /** @@ -54,7 +54,7 @@ public class DatabaseConfig { public DataSource dataSource() throws UnsupportedProviderException { DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); - if (!runningEE) { + if (!runningProOrHigher) { return useDefaultDataSource(dataSourceBuilder); } diff --git a/src/main/java/stirling/software/SPDF/config/security/database/DatabaseService.java b/src/main/java/stirling/software/SPDF/config/security/database/DatabaseService.java index a8daede3..83b9ee63 100644 --- a/src/main/java/stirling/software/SPDF/config/security/database/DatabaseService.java +++ b/src/main/java/stirling/software/SPDF/config/security/database/DatabaseService.java @@ -17,7 +17,6 @@ import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Comparator; import java.util.List; -import java.util.stream.Collectors; import javax.sql.DataSource; @@ -170,7 +169,7 @@ public class DatabaseService implements DatabaseInterface { List filteredBackupList = this.getBackupList().stream() .filter(backup -> !backup.getFileName().startsWith(BACKUP_PREFIX + "user_")) - .collect(Collectors.toList()); + .toList(); if (filteredBackupList.size() > 5) { deleteOldestBackup(filteredBackupList); diff --git a/src/main/java/stirling/software/SPDF/controller/api/MergeController.java b/src/main/java/stirling/software/SPDF/controller/api/MergeController.java index 22815b73..279dd248 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/MergeController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/MergeController.java @@ -10,7 +10,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; -import java.util.stream.Collectors; import org.apache.pdfbox.multipdf.PDFMergerUtility; import org.apache.pdfbox.pdmodel.PDDocument; @@ -165,7 +164,7 @@ public class MergeController { List fieldsToRemove = acroForm.getFields().stream() .filter(field -> field instanceof PDSignatureField) - .collect(Collectors.toList()); + .toList(); if (!fieldsToRemove.isEmpty()) { acroForm.flatten( diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java index 2aa75f15..c64084bf 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java @@ -8,7 +8,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -146,7 +145,7 @@ public class ConvertImgPDFController { List webpFiles = Files.walk(tempOutputDir) .filter(path -> path.toString().endsWith(".webp")) - .collect(Collectors.toList()); + .toList(); if (webpFiles.isEmpty()) { log.error("No WebP files were created in: {}", tempOutputDir.toString()); diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java index 47d6d5b3..e96a29c4 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java @@ -5,7 +5,6 @@ import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; -import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -63,7 +62,7 @@ public class OCRController { .filter(file -> file.getName().endsWith(".traineddata")) .map(file -> file.getName().replace(".traineddata", "")) .filter(lang -> !lang.equalsIgnoreCase("osd")) - .collect(Collectors.toList()); + .toList(); } @PostMapping(consumes = "multipart/form-data", value = "/ocr-pdf") diff --git a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java index 2ab90cac..a7dd8a0e 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java @@ -5,7 +5,6 @@ import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -64,9 +63,7 @@ public class PipelineController { log.info("Received POST request to /handleData with {} files", files.length); List operationNames = - config.getOperations().stream() - .map(PipelineOperation::getOperation) - .collect(Collectors.toList()); + config.getOperations().stream().map(PipelineOperation::getOperation).toList(); Map properties = new HashMap<>(); properties.put("operations", operationNames); 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 56fe768a..c3d21211 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 @@ -11,7 +11,6 @@ import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -168,7 +167,7 @@ public class PipelineProcessor { file -> finalinputFileTypes.stream() .anyMatch(file.getFilename()::endsWith)) - .collect(Collectors.toList()); + .toList(); } // Check if there are matching files if (!matchingFiles.isEmpty()) { diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java b/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java index 81c0bcfb..ddead433 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java @@ -1,7 +1,6 @@ package stirling.software.SPDF.controller.api.security; import java.util.List; -import java.util.stream.Collectors; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocumentCatalog; @@ -59,7 +58,7 @@ public class RemoveCertSignController { List fieldsToRemove = acroForm.getFields().stream() .filter(field -> field instanceof PDSignatureField) - .collect(Collectors.toList()); + .toList(); if (!fieldsToRemove.isEmpty()) { acroForm.flatten(fieldsToRemove, false); 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 28499e1e..9615c82a 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 @@ -66,13 +66,13 @@ public class SanitizeController { } if (removeXMPMetadata) { - sanitizeXMPMetadata(document); + sanitizeXMPMetadata(document); } if (removeMetadata) { - sanitizeDocumentInfoMetadata(document); + sanitizeDocumentInfoMetadata(document); } - + if (removeLinks) { sanitizeLinks(document); } @@ -158,7 +158,7 @@ public class SanitizeController { } } } - + private void sanitizeDocumentInfoMetadata(PDDocument document) { PDDocumentInformation docInfo = document.getDocumentInformation(); if (docInfo != null) { @@ -167,8 +167,6 @@ public class SanitizeController { } } - - private void sanitizeLinks(PDDocument document) throws IOException { for (PDPage page : document.getPages()) { for (PDAnnotation annotation : page.getAnnotations()) { diff --git a/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java b/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java index f9583a7e..17018408 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java +++ b/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java @@ -10,7 +10,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.security.access.prepost.PreAuthorize; @@ -59,16 +58,19 @@ public class AccountWebController { // Assuming you have a repository for user operations private final UserRepository userRepository; private final boolean loginEnabledValue; + private final boolean runningEE; public AccountWebController( ApplicationProperties applicationProperties, SessionPersistentRegistry sessionPersistentRegistry, UserRepository userRepository, - @Qualifier("loginEnabled") boolean loginEnabledValue) { + @Qualifier("loginEnabled") boolean loginEnabledValue, + @Qualifier("runningEE") boolean runningEE) { this.applicationProperties = applicationProperties; this.sessionPersistentRegistry = sessionPersistentRegistry; this.userRepository = userRepository; this.loginEnabledValue = loginEnabledValue; + this.runningEE = runningEE; } @GetMapping("/login") @@ -203,6 +205,9 @@ public class AccountWebController { @PreAuthorize("hasRole('ROLE_ADMIN')") @GetMapping("/usage") public String showUsage() { + if (!runningEE) { + return "error"; + } return "usage"; } @@ -292,7 +297,7 @@ public class AccountWebController { return u2LastRequest.compareTo(u1LastRequest); } }) - .collect(Collectors.toList()); + .toList(); String messageType = request.getParameter("messageType"); String deleteMessage; @@ -344,6 +349,7 @@ public class AccountWebController { model.addAttribute("maxUserSessions", maxUserSessions); model.addAttribute("sessionCount", sessionCount); model.addAttribute("maxEnterpriseUsers", applicationProperties.getPremium().getMaxUsers()); + model.addAttribute("maxPaidUsers", applicationProperties.getPremium().getMaxUsers()); return "adminSettings"; } diff --git a/src/main/java/stirling/software/SPDF/controller/web/GeneralWebController.java b/src/main/java/stirling/software/SPDF/controller/web/GeneralWebController.java index ed6b247c..83337ae6 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/GeneralWebController.java +++ b/src/main/java/stirling/software/SPDF/controller/web/GeneralWebController.java @@ -7,7 +7,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.springframework.beans.factory.annotation.Autowired; @@ -65,7 +64,7 @@ public class GeneralWebController { List jsonFiles = paths.filter(Files::isRegularFile) .filter(p -> p.toString().endsWith(".json")) - .collect(Collectors.toList()); + .toList(); for (Path jsonFile : jsonFiles) { String content = Files.readString(jsonFile, StandardCharsets.UTF_8); pipelineConfigs.add(content); @@ -261,7 +260,7 @@ public class GeneralWebController { } }) .filter(Objects::nonNull) - .collect(Collectors.toList()); + .toList(); } catch (Exception e) { throw new RuntimeException("Failed to read font directory from " + locationPattern, e); } diff --git a/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java b/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java index aae09341..0fabeeae 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java +++ b/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java @@ -3,7 +3,6 @@ package stirling.software.SPDF.controller.web; import java.time.Duration; import java.time.LocalDateTime; import java.util.*; -import java.util.stream.Collectors; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -287,7 +286,7 @@ public class MetricsController { return counts.entrySet().stream() .map(entry -> new EndpointCount(entry.getKey(), entry.getValue())) .sorted(Comparator.comparing(EndpointCount::getCount).reversed()) - .collect(Collectors.toList()); + .toList(); } private double getUniqueUserCount(String method, Optional endpoint) { @@ -349,7 +348,7 @@ public class MetricsController { return uniqueUsers.entrySet().stream() .map(entry -> new EndpointCount(entry.getKey(), entry.getValue().size())) .sorted(Comparator.comparing(EndpointCount::getCount).reversed()) - .collect(Collectors.toList()); + .toList(); } @GetMapping("/uptime") diff --git a/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java b/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java index 0732a227..c70560e3 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java +++ b/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java @@ -4,7 +4,6 @@ import java.io.File; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -123,8 +122,8 @@ public class OtherWebController { return Arrays.stream(files) .filter(file -> file.getName().endsWith(".traineddata")) .map(file -> file.getName().replace(".traineddata", "")) - .filter(lang -> !lang.equalsIgnoreCase("osd")) - .collect(Collectors.toList()); + .filter(lang -> !lang.equalsIgnoreCase("osd")).sorted() + .toList(); } @GetMapping("/ocr-pdf") @@ -132,7 +131,6 @@ public class OtherWebController { public ModelAndView ocrPdfPage() { ModelAndView modelAndView = new ModelAndView("misc/ocr-pdf"); List languages = getAvailableTesseractLanguages(); - Collections.sort(languages); modelAndView.addObject("languages", languages); modelAndView.addObject("currentPage", "ocr-pdf"); return modelAndView; diff --git a/src/main/java/stirling/software/SPDF/model/api/security/SanitizePdfRequest.java b/src/main/java/stirling/software/SPDF/model/api/security/SanitizePdfRequest.java index e930db75..7be655f7 100644 --- a/src/main/java/stirling/software/SPDF/model/api/security/SanitizePdfRequest.java +++ b/src/main/java/stirling/software/SPDF/model/api/security/SanitizePdfRequest.java @@ -22,7 +22,7 @@ public class SanitizePdfRequest extends PDFFile { @Schema(description = "Remove document info metadata from the PDF", defaultValue = "false") private boolean removeMetadata; - + @Schema(description = "Remove links from the PDF", defaultValue = "false") private boolean removeLinks; diff --git a/src/main/java/stirling/software/SPDF/model/provider/Provider.java b/src/main/java/stirling/software/SPDF/model/provider/Provider.java index 4e20c15f..da1d19f3 100644 --- a/src/main/java/stirling/software/SPDF/model/provider/Provider.java +++ b/src/main/java/stirling/software/SPDF/model/provider/Provider.java @@ -5,7 +5,6 @@ import static stirling.software.SPDF.model.UsernameAttribute.EMAIL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.stream.Collectors; import lombok.Data; import lombok.NoArgsConstructor; @@ -59,8 +58,7 @@ public class Provider { public void setScopes(String scopes) { if (scopes != null && !scopes.isBlank()) { - this.scopes = - Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList()); + this.scopes = Arrays.stream(scopes.split(",")).map(String::trim).toList(); } } diff --git a/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java b/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java index 73868347..3a3198fb 100644 --- a/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java +++ b/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java @@ -68,17 +68,17 @@ public class CustomPDFDocumentFactory { } /** - * Main entry point for loading a PDF document from a file. Automatically selects the most - * appropriate loading strategy. - */ + * Main entry point for loading a PDF document from a file. Automatically selects the most + * appropriate loading strategy. + */ public PDDocument load(File file) throws IOException { return load(file, false); } /** - * Main entry point for loading a PDF document from a file with read-only option. - * Automatically selects the most appropriate loading strategy. - */ + * Main entry point for loading a PDF document from a file with read-only option. Automatically + * selects the most appropriate loading strategy. + */ public PDDocument load(File file, boolean readOnly) throws IOException { if (file == null) { throw new IllegalArgumentException("File cannot be null"); @@ -95,17 +95,17 @@ public class CustomPDFDocumentFactory { } /** - * Main entry point for loading a PDF document from a Path. Automatically selects the most - * appropriate loading strategy. - */ + * Main entry point for loading a PDF document from a Path. Automatically selects the most + * appropriate loading strategy. + */ public PDDocument load(Path path) throws IOException { return load(path, false); } /** - * Main entry point for loading a PDF document from a Path with read-only option. - * Automatically selects the most appropriate loading strategy. - */ + * Main entry point for loading a PDF document from a Path with read-only option. Automatically + * selects the most appropriate loading strategy. + */ public PDDocument load(Path path, boolean readOnly) throws IOException { if (path == null) { throw new IllegalArgumentException("File cannot be null"); @@ -170,7 +170,8 @@ public class CustomPDFDocumentFactory { } /** Load with password from InputStream and read-only option */ - public PDDocument load(InputStream input, String password, boolean readOnly) throws IOException { + public PDDocument load(InputStream input, String password, boolean readOnly) + throws IOException { if (input == null) { throw new IllegalArgumentException("InputStream cannot be null"); } @@ -179,7 +180,8 @@ public class CustomPDFDocumentFactory { Path tempFile = createTempFile("pdf-stream-"); Files.copy(input, tempFile, StandardCopyOption.REPLACE_EXISTING); - PDDocument doc = loadAdaptivelyWithPassword(tempFile.toFile(), Files.size(tempFile), password); + PDDocument doc = + loadAdaptivelyWithPassword(tempFile.toFile(), Files.size(tempFile), password); if (!readOnly) { postProcessDocument(doc); } @@ -203,7 +205,7 @@ public class CustomPDFDocumentFactory { /** Load from a PDFFile object with read-only option */ public PDDocument load(PDFFile pdfFile, boolean readOnly) throws IOException { - return load(pdfFile.getFileInput(), readOnly); + return load(pdfFile.getFileInput(), readOnly); } /** Load from a MultipartFile */ @@ -213,8 +215,7 @@ public class CustomPDFDocumentFactory { /** Load from a MultipartFile with read-only option */ public PDDocument load(MultipartFile pdfFile, boolean readOnly) throws IOException { - return load(pdfFile.getInputStream(), readOnly); - + return load(pdfFile.getInputStream(), readOnly); } /** Load with password from MultipartFile */ @@ -223,10 +224,11 @@ public class CustomPDFDocumentFactory { } /** Load with password from MultipartFile with read-only option */ - public PDDocument load(MultipartFile fileInput, String password, boolean readOnly) throws IOException { - return load(fileInput.getInputStream(), password, readOnly); + public PDDocument load(MultipartFile fileInput, String password, boolean readOnly) + throws IOException { + return load(fileInput.getInputStream(), password, readOnly); } - + /** * Determine the appropriate caching strategy based on file size and available memory. This * common method is used by both password and non-password loading paths. @@ -471,5 +473,4 @@ public class CustomPDFDocumentFactory { return saveToBytes(document); } } - } diff --git a/src/main/java/stirling/software/SPDF/service/PdfMetadataService.java b/src/main/java/stirling/software/SPDF/service/PdfMetadataService.java index 9586ad34..173de33f 100644 --- a/src/main/java/stirling/software/SPDF/service/PdfMetadataService.java +++ b/src/main/java/stirling/software/SPDF/service/PdfMetadataService.java @@ -17,18 +17,18 @@ public class PdfMetadataService { private final ApplicationProperties applicationProperties; private final String stirlingPDFLabel; private final UserServiceInterface userService; - private final boolean runningEE; + private final boolean runningProOrHigher; @Autowired public PdfMetadataService( ApplicationProperties applicationProperties, @Qualifier("StirlingPDFLabel") String stirlingPDFLabel, - @Qualifier("runningEE") boolean runningEE, + @Qualifier("runningProOrHigher") boolean runningProOrHigher, @Autowired(required = false) UserServiceInterface userService) { this.applicationProperties = applicationProperties; this.stirlingPDFLabel = stirlingPDFLabel; this.userService = userService; - this.runningEE = runningEE; + this.runningProOrHigher = runningProOrHigher; } public PdfMetadata extractMetadataFromPdf(PDDocument pdf) { @@ -69,7 +69,7 @@ public class PdfMetadataService { .getProFeatures() .getCustomMetadata() .isAutoUpdateMetadata() - && runningEE) { + && runningProOrHigher) { creator = applicationProperties @@ -98,7 +98,7 @@ public class PdfMetadataService { .getProFeatures() .getCustomMetadata() .isAutoUpdateMetadata() - && runningEE) { + && runningProOrHigher) { author = applicationProperties .getPremium() diff --git a/src/main/java/stirling/software/SPDF/service/SignatureService.java b/src/main/java/stirling/software/SPDF/service/SignatureService.java index f6686f3b..984bd0ba 100644 --- a/src/main/java/stirling/software/SPDF/service/SignatureService.java +++ b/src/main/java/stirling/software/SPDF/service/SignatureService.java @@ -7,7 +7,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.thymeleaf.util.StringUtils; @@ -70,7 +69,7 @@ public class SignatureService { return Files.list(folder) .filter(path -> isImageFile(path)) .map(path -> new SignatureFile(path.getFileName().toString(), category)) - .collect(Collectors.toList()); + .toList(); } public byte[] getSignatureBytes(String username, String fileName) throws IOException { diff --git a/src/main/java/stirling/software/SPDF/utils/FileToPdf.java b/src/main/java/stirling/software/SPDF/utils/FileToPdf.java index af7fd063..da4aeab3 100644 --- a/src/main/java/stirling/software/SPDF/utils/FileToPdf.java +++ b/src/main/java/stirling/software/SPDF/utils/FileToPdf.java @@ -9,7 +9,6 @@ import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -172,9 +171,7 @@ public class FileToPdf { // Search for the main HTML file. try (Stream walk = Files.walk(tempDirectory)) { - List htmlFiles = - walk.filter(file -> file.toString().endsWith(".html")) - .collect(Collectors.toList()); + List htmlFiles = walk.filter(file -> file.toString().endsWith(".html")).toList(); if (htmlFiles.isEmpty()) { throw new IOException("No HTML files found in the unzipped directory."); diff --git a/src/main/resources/templates/adminSettings.html b/src/main/resources/templates/adminSettings.html index 7d54331b..13c51a68 100644 --- a/src/main/resources/templates/adminSettings.html +++ b/src/main/resources/templates/adminSettings.html @@ -38,40 +38,48 @@
- + person_add Add New User + edit Change User's Role - + + analytics Usage Statistics +
Total Users: + th:text="${totalUsers}"> + + Active Users: + Disabled Users: - + Total Sessions: - + Total Sessions: /
+
@@ -116,17 +124,16 @@ - + - + -
-

+