diff --git a/build.gradle b/build.gradle index eb36bc5cb..8a9c2f69a 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 b651b8534..f1df7d340 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 28e0c7e7e..20e3e8035 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 d29351125..d788504c5 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 9c2d26548..f36b2c722 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 e0534b999..040e0e070 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 3a77dd08e..6ff5c271c 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 69b06ec11..d0ee65f30 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 289071b03..a4c10d1ae 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 714096c61..b0684d750 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; @@ -99,7 +98,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 61b7c40af..155ed76b0 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; @@ -108,7 +107,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 ba4a02f00..d221704ea 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 a8daede36..83b9ee630 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 22815b73e..279dd2489 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 2aa75f159..c64084bf4 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 47d6d5b35..e96a29c4b 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 2ab90cac2..a7dd8a0ec 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 56fe768a0..c3d212115 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 81c0bcfb1..ddead4338 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 28499e1e2..9615c82af 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 fb06350df..3f478abe9 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java +++ b/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java @@ -10,8 +10,8 @@ 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; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; @@ -56,14 +56,17 @@ public class AccountWebController { private final SessionPersistentRegistry sessionPersistentRegistry; // Assuming you have a repository for user operations private final UserRepository userRepository; + private final boolean runningEE; public AccountWebController( ApplicationProperties applicationProperties, SessionPersistentRegistry sessionPersistentRegistry, - UserRepository userRepository) { + UserRepository userRepository, + @Qualifier("runningEE") boolean runningEE) { this.applicationProperties = applicationProperties; this.sessionPersistentRegistry = sessionPersistentRegistry; this.userRepository = userRepository; + this.runningEE = runningEE; } @GetMapping("/login") @@ -197,6 +200,9 @@ public class AccountWebController { @PreAuthorize("hasRole('ROLE_ADMIN')") @GetMapping("/usage") public String showUsage() { + if (!runningEE) { + return "error"; + } return "usage"; } @@ -279,7 +285,7 @@ public class AccountWebController { return u2LastRequest.compareTo(u1LastRequest); } }) - .collect(Collectors.toList()); + .toList(); String messageType = request.getParameter("messageType"); String deleteMessage; @@ -325,7 +331,7 @@ public class AccountWebController { model.addAttribute("activeUsers", activeUsers); model.addAttribute("disabledUsers", disabledUsers); - 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 ed6b247ce..83337ae6a 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 aae09341e..0fabeeae4 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 0732a2270..c70560e3f 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 e930db756..7be655f76 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 4e20c15f4..da1d19f32 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 73868347d..3a3198fbf 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 9586ad341..173de33f4 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 f6686f3b6..984bd0baf 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 af7fd0637..da4aeab3c 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 ecd9defd7..da4d16c1c 100644 --- a/src/main/resources/templates/adminSettings.html +++ b/src/main/resources/templates/adminSettings.html @@ -34,10 +34,10 @@
+ th:data-bs-toggle="${@runningProOrHigher && totalUsers >= maxPaidUsers} ? null : 'modal'" + th:data-bs-target="${@runningProOrHigher && totalUsers >= maxPaidUsers} ? null : '#addUserModal'" + th:class="${@runningProOrHigher && totalUsers >= maxPaidUsers} ? 'btn btn-danger' : 'btn btn-outline-success'" + th:title="${@runningProOrHigher && totalUsers >= maxPaidUsers} ? #{adminUserSettings.maxUsersReached} : #{adminUserSettings.addUser}"> person_add Add New User @@ -51,7 +51,7 @@ Change User's Role - analytics @@ -61,7 +61,7 @@
Total Users: - + Active Users: @@ -126,7 +126,7 @@
-

+