From 1ce813bcd8d6819f971d0dedf964c40be1f413fc Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Tue, 29 Jul 2025 13:11:53 +0100 Subject: [PATCH 1/9] Endpoint UI data for V2 (#4044) # Description of Changes This pull request introduces several enhancements and new features, primarily focused on improving API documentation support, expanding backend functionality, and adding new frontend tools. Key changes include the integration of Swagger API documentation, the addition of a new `UIDataController` for backend data handling, and updates to the frontend to include a Swagger UI tool. ### Backend Enhancements: * **Swagger API Documentation Integration**: - Added support for dynamically configuring Swagger servers using the `SWAGGER_SERVER_URL` environment variable in `OpenApiConfig` (`[app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.javaR54-L63](diffhunk://#diff-6080fb3dc14efc430c9de1bf9fa4996a23deebc14230dde7788949b2c49cca68R54-L63)`). - Imported necessary Swagger dependencies (`[app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.javaR13](diffhunk://#diff-6080fb3dc14efc430c9de1bf9fa4996a23deebc14230dde7788949b2c49cca68R13)`). - Updated `nginx.conf` to proxy Swagger-related requests to the backend (`[docker/frontend/nginx.confR55-R92](diffhunk://#diff-6d35fafb4405bd052c6d5e48bd946bcef7c77552a74e1b902de45e85eee09aceR55-R92)`). * **New `UIDataController`**: - Introduced a new controller (`UIDataController`) to serve React UI data, including endpoints for home data, licenses, pipeline configurations, signature data, and OCR data (`[app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.javaR1-R301](diffhunk://#diff-3e7063d4e921c7b9e6eedfcad0e535ba3eff68476dcff5e6f28b00c388cff646R1-R301)`). * **Endpoint Handling**: - Modified `ConfigController` to include explicit parameter naming for better clarity in API requests (`[app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.javaL113-R120](diffhunk://#diff-43d19d45ae547fd79090596c06d58cb0eb7f722ed43eb4da59f9dec39f6def6eL113-R120)`). ### Frontend Enhancements: * **Swagger UI Tool**: - Added a new tool definition (`swagger`) in `useToolManagement.tsx`, with an icon and lazy-loaded component (`[frontend/src/hooks/useToolManagement.tsxR30-R38](diffhunk://#diff-57f8a6b3e75ecaec10ad445b01afe8fccc376af6f8ad4d693c68cf98e8863273R30-R38)`). - Implemented the `SwaggerUI` component to open the Swagger documentation in a new tab (`[frontend/src/tools/SwaggerUI.tsxR1-R18](diffhunk://#diff-ca9bdf83c5d611a5edff10255103d7939895635b33a258dd77db6571da6c4600R1-R18)`). * **Localization Updates**: - Updated English (US and GB) translation files to include Swagger-related strings (`[[1]](diffhunk://#diff-14c707e28788a3a84ed5293ff6689be73d4bca00e155beaf090f9b37c978babbR578-R581)`, `[[2]](diffhunk://#diff-14c707e28788a3a84ed5293ff6689be73d4bca00e155beaf090f9b37c978babbR1528-R1533)`, `[[3]](diffhunk://#diff-e4d543afa388d9eb8a423e45dfebb91641e3558d00848d70b285ebb91c40b249R578-R581)`, `[[4]](diffhunk://#diff-e4d543afa388d9eb8a423e45dfebb91641e3558d00848d70b285ebb91c40b249R1528-R1533)`). ### Workflow Updates: * **Environment Variable Additions**: - Added `SWAGGER_SERVER_URL` to the `PR-Auto-Deploy-V2.yml` and `deploy-on-v2-commit.yml` workflows for configuring Swagger server URLs (`[[1]](diffhunk://#diff-931fcb06ba030420d7044dde06465ad55b4e769a9bd374dcd6a0c76f79a5e30eR320)`, `[[2]](diffhunk://#diff-f8b6ec3c0af9cd2d8dffef6f3def2be6357fe596a606850ca7f5d799e1349069R150)`). --- ## Checklist ### General - [ ] 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/devGuide/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/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] 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/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --- .github/workflows/PR-Auto-Deploy-V2.yml | 1 + .github/workflows/deploy-on-v2-commit.yml | 1 + .gitignore | 2 +- .../SPDF/config/CleanUrlInterceptor.java | 5 + .../software/SPDF/config/OpenApiConfig.java | 16 +- .../SPDF/controller/api/UIDataController.java | 301 +++++++++++ .../controller/api/misc/ConfigController.java | 4 +- .../api/ProprietaryUIDataController.java | 484 ++++++++++++++++++ docker/frontend/nginx.conf | 38 ++ .../public/locales/en-GB/translation.json | 10 + .../public/locales/en-US/translation.json | 10 + frontend/src/hooks/useToolManagement.tsx | 10 + frontend/src/tools/SwaggerUI.tsx | 18 + 13 files changed, 894 insertions(+), 6 deletions(-) create mode 100644 app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java create mode 100644 app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java create mode 100644 frontend/src/tools/SwaggerUI.tsx diff --git a/.github/workflows/PR-Auto-Deploy-V2.yml b/.github/workflows/PR-Auto-Deploy-V2.yml index a8f971d53..c8fabfd59 100644 --- a/.github/workflows/PR-Auto-Deploy-V2.yml +++ b/.github/workflows/PR-Auto-Deploy-V2.yml @@ -317,6 +317,7 @@ jobs: SYSTEM_MAXFILESIZE: "100" METRICS_ENABLED: "true" SYSTEM_GOOGLEVISIBILITY: "false" + SWAGGER_SERVER_URL: "http://${{ secrets.VPS_HOST }}:${V2_PORT}" restart: on-failure:5 stirling-pdf-v2-frontend: diff --git a/.github/workflows/deploy-on-v2-commit.yml b/.github/workflows/deploy-on-v2-commit.yml index eb12d5cd9..d5e3a7b16 100644 --- a/.github/workflows/deploy-on-v2-commit.yml +++ b/.github/workflows/deploy-on-v2-commit.yml @@ -147,6 +147,7 @@ jobs: SYSTEM_MAXFILESIZE: "100" METRICS_ENABLED: "true" SYSTEM_GOOGLEVISIBILITY: "false" + SWAGGER_SERVER_URL: "http://${{ secrets.VPS_HOST }}:3000" restart: on-failure:5 frontend: diff --git a/.gitignore b/.gitignore index 8a5168e49..de9f6f24a 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,7 @@ clientWebUI/ !cucumber/exampleFiles/ !cucumber/exampleFiles/example_html.zip exampleYmlFiles/stirling/ -stirling/ +/stirling/ /testing/file_snapshots SwaggerDoc.json diff --git a/app/core/src/main/java/stirling/software/SPDF/config/CleanUrlInterceptor.java b/app/core/src/main/java/stirling/software/SPDF/config/CleanUrlInterceptor.java index 088c0c0bf..a696df56a 100644 --- a/app/core/src/main/java/stirling/software/SPDF/config/CleanUrlInterceptor.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/CleanUrlInterceptor.java @@ -39,6 +39,11 @@ public class CleanUrlInterceptor implements HandlerInterceptor { String queryString = request.getQueryString(); if (queryString != null && !queryString.isEmpty()) { String requestURI = request.getRequestURI(); + + if (requestURI.contains("/api/")) { + return true; + } + Map allowedParameters = new HashMap<>(); // Keep only the allowed parameters diff --git a/app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java b/app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java index 78d2a3d2b..1a5635baa 100644 --- a/app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java @@ -10,6 +10,7 @@ import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; import lombok.RequiredArgsConstructor; @@ -50,17 +51,26 @@ public class OpenApiConfig { .url("https://www.stirlingpdf.com") .email("contact@stirlingpdf.com")) .description(DEFAULT_DESCRIPTION); + + OpenAPI openAPI = new OpenAPI().info(info); + + // Add server configuration from environment variable + String swaggerServerUrl = System.getenv("SWAGGER_SERVER_URL"); + if (swaggerServerUrl != null && !swaggerServerUrl.trim().isEmpty()) { + Server server = new Server().url(swaggerServerUrl).description("API Server"); + openAPI.addServersItem(server); + } + if (!applicationProperties.getSecurity().getEnableLogin()) { - return new OpenAPI().components(new Components()).info(info); + return openAPI.components(new Components()); } else { SecurityScheme apiKeyScheme = new SecurityScheme() .type(SecurityScheme.Type.APIKEY) .in(SecurityScheme.In.HEADER) .name("X-API-KEY"); - return new OpenAPI() + return openAPI .components(new Components().addSecuritySchemes("apiKey", apiKeyScheme)) - .info(info) .addSecurityItem(new SecurityRequirement().addList("apiKey")); } } diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java new file mode 100644 index 000000000..3161560ae --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java @@ -0,0 +1,301 @@ +package stirling.software.SPDF.controller.api; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Stream; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import stirling.software.SPDF.model.Dependency; +import stirling.software.SPDF.model.SignatureFile; +import stirling.software.SPDF.service.SignatureService; +import stirling.software.common.configuration.InstallationPathConfig; +import stirling.software.common.configuration.RuntimePathConfig; +import stirling.software.common.model.ApplicationProperties; +import stirling.software.common.service.UserServiceInterface; +import stirling.software.common.util.ExceptionUtils; +import stirling.software.common.util.GeneralUtils; + +@Slf4j +@RestController +@RequestMapping("/api/v1/ui-data") +@Tag(name = "UI Data", description = "APIs for React UI data") +public class UIDataController { + + private final ApplicationProperties applicationProperties; + private final SignatureService signatureService; + private final UserServiceInterface userService; + private final ResourceLoader resourceLoader; + private final RuntimePathConfig runtimePathConfig; + + public UIDataController( + ApplicationProperties applicationProperties, + SignatureService signatureService, + @Autowired(required = false) UserServiceInterface userService, + ResourceLoader resourceLoader, + RuntimePathConfig runtimePathConfig) { + this.applicationProperties = applicationProperties; + this.signatureService = signatureService; + this.userService = userService; + this.resourceLoader = resourceLoader; + this.runtimePathConfig = runtimePathConfig; + } + + @GetMapping("/home") + @Operation(summary = "Get home page data") + public ResponseEntity getHomeData() { + String showSurvey = System.getenv("SHOW_SURVEY"); + boolean showSurveyValue = showSurvey == null || "true".equalsIgnoreCase(showSurvey); + + HomeData data = new HomeData(); + data.setShowSurveyFromDocker(showSurveyValue); + + return ResponseEntity.ok(data); + } + + @GetMapping("/licenses") + @Operation(summary = "Get third-party licenses data") + public ResponseEntity getLicensesData() { + LicensesData data = new LicensesData(); + Resource resource = new ClassPathResource("static/3rdPartyLicenses.json"); + + try { + InputStream is = resource.getInputStream(); + String json = new String(is.readAllBytes(), StandardCharsets.UTF_8); + ObjectMapper mapper = new ObjectMapper(); + Map> licenseData = + mapper.readValue(json, new TypeReference<>() {}); + data.setDependencies(licenseData.get("dependencies")); + } catch (IOException e) { + log.error("Failed to load licenses data", e); + data.setDependencies(Collections.emptyList()); + } + + return ResponseEntity.ok(data); + } + + @GetMapping("/pipeline") + @Operation(summary = "Get pipeline configuration data") + public ResponseEntity getPipelineData() { + PipelineData data = new PipelineData(); + List pipelineConfigs = new ArrayList<>(); + List> pipelineConfigsWithNames = new ArrayList<>(); + + if (new java.io.File(runtimePathConfig.getPipelineDefaultWebUiConfigs()).exists()) { + try (Stream paths = + Files.walk(Paths.get(runtimePathConfig.getPipelineDefaultWebUiConfigs()))) { + List jsonFiles = + paths.filter(Files::isRegularFile) + .filter(p -> p.toString().endsWith(".json")) + .toList(); + + for (Path jsonFile : jsonFiles) { + String content = Files.readString(jsonFile, StandardCharsets.UTF_8); + pipelineConfigs.add(content); + } + + for (String config : pipelineConfigs) { + Map jsonContent = + new ObjectMapper() + .readValue(config, new TypeReference>() {}); + String name = (String) jsonContent.get("name"); + if (name == null || name.length() < 1) { + String filename = + jsonFiles + .get(pipelineConfigs.indexOf(config)) + .getFileName() + .toString(); + name = filename.substring(0, filename.lastIndexOf('.')); + } + Map configWithName = new HashMap<>(); + configWithName.put("json", config); + configWithName.put("name", name); + pipelineConfigsWithNames.add(configWithName); + } + } catch (IOException e) { + log.error("Failed to load pipeline configs", e); + } + } + + if (pipelineConfigsWithNames.isEmpty()) { + Map configWithName = new HashMap<>(); + configWithName.put("json", ""); + configWithName.put("name", "No preloaded configs found"); + pipelineConfigsWithNames.add(configWithName); + } + + data.setPipelineConfigsWithNames(pipelineConfigsWithNames); + data.setPipelineConfigs(pipelineConfigs); + + return ResponseEntity.ok(data); + } + + @GetMapping("/sign") + @Operation(summary = "Get signature form data") + public ResponseEntity getSignData() { + String username = ""; + if (userService != null) { + username = userService.getCurrentUsername(); + } + + List signatures = signatureService.getAvailableSignatures(username); + List fonts = getFontNames(); + + SignData data = new SignData(); + data.setSignatures(signatures); + data.setFonts(fonts); + + return ResponseEntity.ok(data); + } + + @GetMapping("/ocr-pdf") + @Operation(summary = "Get OCR PDF data") + public ResponseEntity getOcrPdfData() { + List languages = getAvailableTesseractLanguages(); + + OcrData data = new OcrData(); + data.setLanguages(languages); + + return ResponseEntity.ok(data); + } + + private List getAvailableTesseractLanguages() { + String tessdataDir = applicationProperties.getSystem().getTessdataDir(); + java.io.File[] files = new java.io.File(tessdataDir).listFiles(); + if (files == null) { + return Collections.emptyList(); + } + return Arrays.stream(files) + .filter(file -> file.getName().endsWith(".traineddata")) + .map(file -> file.getName().replace(".traineddata", "")) + .filter(lang -> !"osd".equalsIgnoreCase(lang)) + .sorted() + .toList(); + } + + private List getFontNames() { + List fontNames = new ArrayList<>(); + fontNames.addAll(getFontNamesFromLocation("classpath:static/fonts/*.woff2")); + fontNames.addAll( + getFontNamesFromLocation( + "file:" + + InstallationPathConfig.getStaticPath() + + "fonts" + + java.io.File.separator + + "*")); + return fontNames; + } + + private List getFontNamesFromLocation(String locationPattern) { + try { + Resource[] resources = + GeneralUtils.getResourcesFromLocationPattern(locationPattern, resourceLoader); + return Arrays.stream(resources) + .map( + resource -> { + try { + String filename = resource.getFilename(); + if (filename != null) { + int lastDotIndex = filename.lastIndexOf('.'); + if (lastDotIndex != -1) { + String name = filename.substring(0, lastDotIndex); + String extension = filename.substring(lastDotIndex + 1); + return new FontResource(name, extension); + } + } + return null; + } catch (Exception e) { + throw ExceptionUtils.createRuntimeException( + "error.fontLoadingFailed", + "Error processing font file", + e); + } + }) + .filter(Objects::nonNull) + .toList(); + } catch (Exception e) { + throw ExceptionUtils.createRuntimeException( + "error.fontDirectoryReadFailed", "Failed to read font directory", e); + } + } + + // Data classes + @Data + public static class HomeData { + private boolean showSurveyFromDocker; + } + + @Data + public static class LicensesData { + private List dependencies; + } + + @Data + public static class PipelineData { + private List> pipelineConfigsWithNames; + private List pipelineConfigs; + } + + @Data + public static class SignData { + private List signatures; + private List fonts; + } + + @Data + public static class OcrData { + private List languages; + } + + @Data + public static class FontResource { + private String name; + private String extension; + private String type; + + public FontResource(String name, String extension) { + this.name = name; + this.extension = extension; + this.type = getFormatFromExtension(extension); + } + + private static String getFormatFromExtension(String extension) { + switch (extension) { + case "ttf": + return "truetype"; + case "woff": + return "woff"; + case "woff2": + return "woff2"; + case "eot": + return "embedded-opentype"; + case "svg": + return "svg"; + default: + return ""; + } + } + } +} diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java index 6b69e4b2e..fb1b7b2ca 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java @@ -110,14 +110,14 @@ public class ConfigController { } @GetMapping("/endpoint-enabled") - public ResponseEntity isEndpointEnabled(@RequestParam String endpoint) { + public ResponseEntity isEndpointEnabled(@RequestParam(name = "endpoint") String endpoint) { boolean enabled = endpointConfiguration.isEndpointEnabled(endpoint); return ResponseEntity.ok(enabled); } @GetMapping("/endpoints-enabled") public ResponseEntity> areEndpointsEnabled( - @RequestParam String endpoints) { + @RequestParam(name = "endpoints") String endpoints) { Map result = new HashMap<>(); String[] endpointArray = endpoints.split(","); for (String endpoint : endpointArray) { diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java new file mode 100644 index 000000000..f4eb114ef --- /dev/null +++ b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java @@ -0,0 +1,484 @@ +package stirling.software.proprietary.controller.api; + +import static stirling.software.common.util.ProviderUtils.validateProvider; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.*; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +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.FileInfo; +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; +import stirling.software.proprietary.audit.AuditEventType; +import stirling.software.proprietary.audit.AuditLevel; +import stirling.software.proprietary.config.AuditConfigurationProperties; +import stirling.software.proprietary.model.Team; +import stirling.software.proprietary.model.dto.TeamWithUserCountDTO; +import stirling.software.proprietary.security.config.EnterpriseEndpoint; +import stirling.software.proprietary.security.database.repository.SessionRepository; +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.repository.TeamRepository; +import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal; +import stirling.software.proprietary.security.service.DatabaseService; +import stirling.software.proprietary.security.service.TeamService; +import stirling.software.proprietary.security.session.SessionPersistentRegistry; + +@Slf4j +@RestController +@RequestMapping("/api/v1/proprietary/ui-data") +@Tag(name = "Proprietary UI Data", description = "APIs for React UI data (Proprietary features)") +@EnterpriseEndpoint +public class ProprietaryUIDataController { + + private final ApplicationProperties applicationProperties; + private final AuditConfigurationProperties auditConfig; + private final SessionPersistentRegistry sessionPersistentRegistry; + private final UserRepository userRepository; + private final TeamRepository teamRepository; + private final SessionRepository sessionRepository; + private final DatabaseService databaseService; + private final boolean runningEE; + private final ObjectMapper objectMapper; + + public ProprietaryUIDataController( + ApplicationProperties applicationProperties, + AuditConfigurationProperties auditConfig, + SessionPersistentRegistry sessionPersistentRegistry, + UserRepository userRepository, + TeamRepository teamRepository, + SessionRepository sessionRepository, + DatabaseService databaseService, + ObjectMapper objectMapper, + @Qualifier("runningEE") boolean runningEE) { + this.applicationProperties = applicationProperties; + this.auditConfig = auditConfig; + this.sessionPersistentRegistry = sessionPersistentRegistry; + this.userRepository = userRepository; + this.teamRepository = teamRepository; + this.sessionRepository = sessionRepository; + this.databaseService = databaseService; + this.objectMapper = objectMapper; + this.runningEE = runningEE; + } + + @GetMapping("/audit-dashboard") + @PreAuthorize("hasRole('ADMIN')") + @Operation(summary = "Get audit dashboard data") + public ResponseEntity getAuditDashboardData() { + AuditDashboardData data = new AuditDashboardData(); + data.setAuditEnabled(auditConfig.isEnabled()); + data.setAuditLevel(auditConfig.getAuditLevel()); + data.setAuditLevelInt(auditConfig.getLevel()); + data.setRetentionDays(auditConfig.getRetentionDays()); + data.setAuditLevels(AuditLevel.values()); + data.setAuditEventTypes(AuditEventType.values()); + + return ResponseEntity.ok(data); + } + + @GetMapping("/login") + @Operation(summary = "Get login page data") + public ResponseEntity getLoginData() { + LoginData data = new LoginData(); + Map providerList = new HashMap<>(); + Security securityProps = applicationProperties.getSecurity(); + OAUTH2 oauth = securityProps.getOauth2(); + + if (oauth != null && oauth.getEnabled()) { + if (oauth.isSettingsValid()) { + String firstChar = String.valueOf(oauth.getProvider().charAt(0)); + String clientName = + oauth.getProvider().replaceFirst(firstChar, firstChar.toUpperCase()); + providerList.put("/oauth2/authorization/" + oauth.getProvider(), clientName); + } + + Client client = oauth.getClient(); + if (client != null) { + GoogleProvider google = client.getGoogle(); + if (validateProvider(google)) { + providerList.put( + "/oauth2/authorization/" + google.getName(), google.getClientName()); + } + + GitHubProvider github = client.getGithub(); + if (validateProvider(github)) { + providerList.put( + "/oauth2/authorization/" + github.getName(), github.getClientName()); + } + + KeycloakProvider keycloak = client.getKeycloak(); + if (validateProvider(keycloak)) { + providerList.put( + "/oauth2/authorization/" + keycloak.getName(), + keycloak.getClientName()); + } + } + } + + SAML2 saml2 = securityProps.getSaml2(); + if (securityProps.isSaml2Active() + && applicationProperties.getSystem().getEnableAlphaFunctionality() + && applicationProperties.getPremium().isEnabled()) { + String samlIdp = saml2.getProvider(); + String saml2AuthenticationPath = "/saml2/authenticate/" + saml2.getRegistrationId(); + + if (!applicationProperties.getPremium().getProFeatures().isSsoAutoLogin()) { + providerList.put(saml2AuthenticationPath, samlIdp + " (SAML 2)"); + } + } + + // Remove null entries + providerList + .entrySet() + .removeIf(entry -> entry.getKey() == null || entry.getValue() == null); + + data.setProviderList(providerList); + data.setLoginMethod(securityProps.getLoginMethod()); + data.setAltLogin(!providerList.isEmpty() && securityProps.isAltLogin()); + + return ResponseEntity.ok(data); + } + + @GetMapping("/admin-settings") + @PreAuthorize("hasRole('ROLE_ADMIN')") + @Operation(summary = "Get admin settings data") + public ResponseEntity getAdminSettingsData(Authentication authentication) { + List allUsers = userRepository.findAllWithTeam(); + Iterator iterator = allUsers.iterator(); + Map roleDetails = Role.getAllRoleDetails(); + + Map userSessions = new HashMap<>(); + Map userLastRequest = new HashMap<>(); + int activeUsers = 0; + int disabledUsers = 0; + + while (iterator.hasNext()) { + User user = iterator.next(); + if (user != null) { + boolean shouldRemove = false; + + // Check if user is an INTERNAL_API_USER + for (Authority authority : user.getAuthorities()) { + if (authority.getAuthority().equals(Role.INTERNAL_API_USER.getRoleId())) { + shouldRemove = true; + roleDetails.remove(Role.INTERNAL_API_USER.getRoleId()); + break; + } + } + + // Check if user is part of the Internal team + if (user.getTeam() != null + && user.getTeam().getName().equals(TeamService.INTERNAL_TEAM_NAME)) { + shouldRemove = true; + } + + if (shouldRemove) { + iterator.remove(); + continue; + } + + // Session status and last request time + int maxInactiveInterval = sessionPersistentRegistry.getMaxInactiveInterval(); + boolean hasActiveSession = false; + Date lastRequest = null; + Optional latestSession = + sessionPersistentRegistry.findLatestSession(user.getUsername()); + + if (latestSession.isPresent()) { + SessionEntity sessionEntity = latestSession.get(); + Date lastAccessedTime = sessionEntity.getLastRequest(); + Instant now = Instant.now(); + Instant expirationTime = + lastAccessedTime + .toInstant() + .plus(maxInactiveInterval, ChronoUnit.SECONDS); + + if (now.isAfter(expirationTime)) { + sessionPersistentRegistry.expireSession(sessionEntity.getSessionId()); + } else { + hasActiveSession = !sessionEntity.isExpired(); + } + lastRequest = sessionEntity.getLastRequest(); + } else { + lastRequest = new Date(0); + } + + userSessions.put(user.getUsername(), hasActiveSession); + userLastRequest.put(user.getUsername(), lastRequest); + + if (hasActiveSession) activeUsers++; + if (!user.isEnabled()) disabledUsers++; + } + } + + // Sort users by active status and last request date + List sortedUsers = + allUsers.stream() + .sorted( + (u1, u2) -> { + boolean u1Active = userSessions.get(u1.getUsername()); + boolean u2Active = userSessions.get(u2.getUsername()); + if (u1Active && !u2Active) return -1; + if (!u1Active && u2Active) return 1; + + Date u1LastRequest = + userLastRequest.getOrDefault( + u1.getUsername(), new Date(0)); + Date u2LastRequest = + userLastRequest.getOrDefault( + u2.getUsername(), new Date(0)); + return u2LastRequest.compareTo(u1LastRequest); + }) + .toList(); + + List allTeams = + teamRepository.findAll().stream() + .filter(team -> !team.getName().equals(TeamService.INTERNAL_TEAM_NAME)) + .toList(); + + AdminSettingsData data = new AdminSettingsData(); + data.setUsers(sortedUsers); + data.setCurrentUsername(authentication.getName()); + data.setRoleDetails(roleDetails); + data.setUserSessions(userSessions); + data.setUserLastRequest(userLastRequest); + data.setTotalUsers(allUsers.size()); + data.setActiveUsers(activeUsers); + data.setDisabledUsers(disabledUsers); + data.setTeams(allTeams); + data.setMaxPaidUsers(applicationProperties.getPremium().getMaxUsers()); + + return ResponseEntity.ok(data); + } + + @GetMapping("/account") + @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')") + @Operation(summary = "Get account page data") + public ResponseEntity getAccountData(Authentication authentication) { + if (authentication == null || !authentication.isAuthenticated()) { + return ResponseEntity.status(401).build(); + } + + Object principal = authentication.getPrincipal(); + String username = null; + boolean isOAuth2Login = false; + boolean isSaml2Login = false; + + if (principal instanceof UserDetails detailsUser) { + username = detailsUser.getUsername(); + } else if (principal instanceof OAuth2User oAuth2User) { + username = oAuth2User.getName(); + isOAuth2Login = true; + } else if (principal instanceof CustomSaml2AuthenticatedPrincipal saml2User) { + username = saml2User.name(); + isSaml2Login = true; + } + + if (username == null) { + return ResponseEntity.status(401).build(); + } + + Optional user = userRepository.findByUsernameIgnoreCaseWithSettings(username); + if (user.isEmpty()) { + return ResponseEntity.status(404).build(); + } + + String settingsJson; + try { + settingsJson = objectMapper.writeValueAsString(user.get().getSettings()); + } catch (JsonProcessingException e) { + log.error("Error converting settings map", e); + return ResponseEntity.status(500).build(); + } + + AccountData data = new AccountData(); + data.setUsername(username); + data.setRole(user.get().getRolesAsString()); + data.setSettings(settingsJson); + data.setChangeCredsFlag(user.get().isFirstLogin()); + data.setOAuth2Login(isOAuth2Login); + data.setSaml2Login(isSaml2Login); + + return ResponseEntity.ok(data); + } + + @GetMapping("/teams") + @PreAuthorize("hasRole('ROLE_ADMIN')") + @Operation(summary = "Get teams list data") + public ResponseEntity getTeamsData() { + List allTeamsWithCounts = teamRepository.findAllTeamsWithUserCount(); + List teamsWithCounts = + allTeamsWithCounts.stream() + .filter(team -> !team.getName().equals(TeamService.INTERNAL_TEAM_NAME)) + .toList(); + + List teamActivities = sessionRepository.findLatestActivityByTeam(); + Map teamLastRequest = new HashMap<>(); + for (Object[] result : teamActivities) { + Long teamId = (Long) result[0]; + Date lastActivity = (Date) result[1]; + teamLastRequest.put(teamId, lastActivity); + } + + TeamsData data = new TeamsData(); + data.setTeamsWithCounts(teamsWithCounts); + data.setTeamLastRequest(teamLastRequest); + + return ResponseEntity.ok(data); + } + + @GetMapping("/teams/{id}") + @PreAuthorize("hasRole('ROLE_ADMIN')") + @Operation(summary = "Get team details data") + public ResponseEntity getTeamDetailsData(@PathVariable("id") Long id) { + Team team = + teamRepository + .findById(id) + .orElseThrow(() -> new RuntimeException("Team not found")); + + if (team.getName().equals(TeamService.INTERNAL_TEAM_NAME)) { + return ResponseEntity.status(403).build(); + } + + List teamUsers = userRepository.findAllByTeamId(id); + List allUsers = userRepository.findAllWithTeam(); + List availableUsers = + allUsers.stream() + .filter( + user -> + (user.getTeam() == null + || !user.getTeam().getId().equals(id)) + && (user.getTeam() == null + || !user.getTeam() + .getName() + .equals( + TeamService + .INTERNAL_TEAM_NAME))) + .toList(); + + List userSessions = sessionRepository.findLatestSessionByTeamId(id); + Map userLastRequest = new HashMap<>(); + for (Object[] result : userSessions) { + String username = (String) result[0]; + Date lastRequest = (Date) result[1]; + userLastRequest.put(username, lastRequest); + } + + TeamDetailsData data = new TeamDetailsData(); + data.setTeam(team); + data.setTeamUsers(teamUsers); + data.setAvailableUsers(availableUsers); + data.setUserLastRequest(userLastRequest); + + return ResponseEntity.ok(data); + } + + @GetMapping("/database") + @PreAuthorize("hasRole('ROLE_ADMIN')") + @Operation(summary = "Get database management data") + public ResponseEntity getDatabaseData() { + List backupList = databaseService.getBackupList(); + String dbVersion = databaseService.getH2Version(); + boolean isVersionUnknown = "Unknown".equalsIgnoreCase(dbVersion); + + DatabaseData data = new DatabaseData(); + data.setBackupFiles(backupList); + data.setDatabaseVersion(dbVersion); + data.setVersionUnknown(isVersionUnknown); + + return ResponseEntity.ok(data); + } + + // Data classes + @Data + public static class AuditDashboardData { + private boolean auditEnabled; + private AuditLevel auditLevel; + private int auditLevelInt; + private int retentionDays; + private AuditLevel[] auditLevels; + private AuditEventType[] auditEventTypes; + } + + @Data + public static class LoginData { + private Map providerList; + private String loginMethod; + private boolean altLogin; + } + + @Data + public static class AdminSettingsData { + private List users; + private String currentUsername; + private Map roleDetails; + private Map userSessions; + private Map userLastRequest; + private int totalUsers; + private int activeUsers; + private int disabledUsers; + private List teams; + private int maxPaidUsers; + } + + @Data + public static class AccountData { + private String username; + private String role; + private String settings; + private boolean changeCredsFlag; + private boolean oAuth2Login; + private boolean saml2Login; + } + + @Data + public static class TeamsData { + private List teamsWithCounts; + private Map teamLastRequest; + } + + @Data + public static class TeamDetailsData { + private Team team; + private List teamUsers; + private List availableUsers; + private Map userLastRequest; + } + + @Data + public static class DatabaseData { + private List backupFiles; + private String databaseVersion; + private boolean versionUnknown; + } +} diff --git a/docker/frontend/nginx.conf b/docker/frontend/nginx.conf index 456d70140..af4ca85f2 100644 --- a/docker/frontend/nginx.conf +++ b/docker/frontend/nginx.conf @@ -52,6 +52,44 @@ http { proxy_request_buffering off; } + # Proxy Swagger UI to backend (including versioned paths) + location ~ ^/swagger-ui(.*)$ { + proxy_pass ${VITE_API_BASE_URL}/swagger-ui$1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + + proxy_set_header Connection ''; + proxy_http_version 1.1; + proxy_buffering off; + proxy_cache off; + } + + # Proxy API docs to backend (with query parameters and sub-paths) + location ~ ^/v3/api-docs(.*)$ { + proxy_pass ${VITE_API_BASE_URL}/v3/api-docs$1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + } + + # Proxy v1 API docs to backend (with query parameters and sub-paths) + location ~ ^/v1/api-docs(.*)$ { + proxy_pass ${VITE_API_BASE_URL}/v1/api-docs$1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + } + # Cache static assets location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; diff --git a/frontend/public/locales/en-GB/translation.json b/frontend/public/locales/en-GB/translation.json index 081f746ee..37c0e5355 100644 --- a/frontend/public/locales/en-GB/translation.json +++ b/frontend/public/locales/en-GB/translation.json @@ -575,6 +575,10 @@ "title": "Validate PDF Signature", "desc": "Verify digital signatures and certificates in PDF documents" }, + "swagger": { + "title": "API Documentation", + "desc": "View API documentation and test endpoints" + }, "replaceColorPdf": { "title": "Advanced Colour options", "desc": "Replace colour for text and background in PDF and invert full colour of pdf to reduce file size" @@ -1521,6 +1525,12 @@ }, "note": "Release notes are only available in English" }, + "swagger": { + "title": "API Documentation", + "header": "API Documentation", + "desc": "View and test the Stirling PDF API endpoints", + "tags": "api,documentation,swagger,endpoints,development" + }, "cookieBanner": { "popUp": { "title": "How we use Cookies", diff --git a/frontend/public/locales/en-US/translation.json b/frontend/public/locales/en-US/translation.json index e73175694..1b258a824 100644 --- a/frontend/public/locales/en-US/translation.json +++ b/frontend/public/locales/en-US/translation.json @@ -575,6 +575,10 @@ "title": "Validate PDF Signature", "desc": "Verify digital signatures and certificates in PDF documents" }, + "swagger": { + "title": "API Documentation", + "desc": "View API documentation and test endpoints" + }, "replaceColorPdf": { "title": "Replace and Invert Color", "desc": "Replace color for text and background in PDF and invert full color of pdf to reduce file size" @@ -1521,6 +1525,12 @@ }, "note": "Release notes are only available in English" }, + "swagger": { + "title": "API Documentation", + "header": "API Documentation", + "desc": "View and test the Stirling PDF API endpoints", + "tags": "api,documentation,swagger,endpoints,development" + }, "cookieBanner": { "popUp": { "title": "How we use Cookies", diff --git a/frontend/src/hooks/useToolManagement.tsx b/frontend/src/hooks/useToolManagement.tsx index 7ada59024..bdf2744ac 100644 --- a/frontend/src/hooks/useToolManagement.tsx +++ b/frontend/src/hooks/useToolManagement.tsx @@ -2,6 +2,7 @@ import React, { useState, useCallback, useMemo, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import ContentCutIcon from "@mui/icons-material/ContentCut"; import ZoomInMapIcon from "@mui/icons-material/ZoomInMap"; +import ApiIcon from "@mui/icons-material/Api"; import { useMultipleEndpointsEnabled } from "./useEndpointConfig"; import { Tool, ToolDefinition, BaseToolProps, ToolRegistry } from "../types/tool"; @@ -26,6 +27,15 @@ const toolDefinitions: Record = { description: "Reduce PDF file size", endpoints: ["compress-pdf"] }, + swagger: { + id: "swagger", + icon: , + component: React.lazy(() => import("../tools/SwaggerUI")), + maxFiles: 0, + category: "utility", + description: "Open API documentation", + endpoints: ["swagger-ui"] + }, }; diff --git a/frontend/src/tools/SwaggerUI.tsx b/frontend/src/tools/SwaggerUI.tsx new file mode 100644 index 000000000..0712b6068 --- /dev/null +++ b/frontend/src/tools/SwaggerUI.tsx @@ -0,0 +1,18 @@ +import React, { useEffect } from 'react'; +import { BaseToolProps } from '../types/tool'; + +const SwaggerUI: React.FC = () => { + useEffect(() => { + // Redirect to Swagger UI + window.open('/swagger-ui/5.21.0/index.html', '_blank'); + }, []); + + return ( +
+

Opening Swagger UI in a new tab...

+

If it didn't open automatically, click here

+
+ ); +}; + +export default SwaggerUI; \ No newline at end of file From 75bd154a82cc51dbf530b6be85e92634cfdbcec8 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Tue, 29 Jul 2025 13:44:17 +0100 Subject: [PATCH 2/9] V2 async requests (#4043) # Description of Changes --- ## Checklist ### General - [ ] 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/devGuide/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/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] 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/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: a --- .../controller/api/AnalysisController.java | 18 ++++++++++-------- .../SPDF/controller/api/CropController.java | 4 +++- .../api/EditTableOfContentsController.java | 6 ++++-- .../SPDF/controller/api/MergeController.java | 4 +++- .../api/MultiPageLayoutController.java | 4 +++- .../api/PdfImageRemovalController.java | 4 +++- .../controller/api/PdfOverlayController.java | 4 +++- .../api/RearrangePagesPDFController.java | 6 ++++-- .../controller/api/RotationController.java | 4 +++- .../controller/api/ScalePagesController.java | 4 +++- .../controller/api/SettingsController.java | 4 +++- .../controller/api/SplitPDFController.java | 4 +++- .../api/SplitPdfByChaptersController.java | 4 +++- .../api/SplitPdfBySectionsController.java | 4 +++- .../api/SplitPdfBySizeController.java | 4 +++- .../controller/api/ToSinglePageController.java | 4 +++- .../api/converters/ConvertEmlToPDF.java | 4 +++- .../api/converters/ConvertHtmlToPDF.java | 4 +++- .../converters/ConvertImgPDFController.java | 6 ++++-- .../api/converters/ConvertMarkdownToPdf.java | 4 +++- .../converters/ConvertOfficeController.java | 4 +++- .../api/converters/ConvertPDFToHtml.java | 4 +++- .../api/converters/ConvertPDFToOffice.java | 10 ++++++---- .../api/converters/ConvertPDFToPDFA.java | 4 +++- .../api/converters/ConvertWebsiteToPDF.java | 4 +++- .../api/converters/ExtractCSVController.java | 4 +++- .../api/filters/FilterController.java | 14 ++++++++------ .../api/misc/AttachmentController.java | 4 +++- .../api/misc/AutoRenameController.java | 4 +++- .../api/misc/AutoSplitPdfController.java | 4 +++- .../api/misc/BlankPageController.java | 4 +++- .../api/misc/CompressController.java | 4 +++- .../api/misc/DecompressPdfController.java | 4 +++- .../api/misc/ExtractImageScansController.java | 4 +++- .../api/misc/ExtractImagesController.java | 4 +++- .../controller/api/misc/FlattenController.java | 4 +++- .../api/misc/MetadataController.java | 4 +++- .../controller/api/misc/OCRController.java | 4 +++- .../api/misc/OverlayImageController.java | 4 +++- .../api/misc/PageNumbersController.java | 4 +++- .../api/misc/PrintFileController.java | 4 +++- .../controller/api/misc/RepairController.java | 4 +++- .../misc/ReplaceAndInvertColorController.java | 4 +++- .../api/misc/ScannerEffectController.java | 4 +++- .../controller/api/misc/ShowJavascript.java | 4 +++- .../controller/api/misc/StampController.java | 4 +++- .../api/misc/UnlockPDFFormsController.java | 4 +++- .../api/pipeline/PipelineController.java | 4 +++- .../api/security/CertSignController.java | 4 +++- .../controller/api/security/GetInfoOnPDF.java | 4 +++- .../api/security/PasswordController.java | 6 ++++-- .../api/security/RedactController.java | 6 ++++-- .../api/security/RemoveCertSignController.java | 4 +++- .../api/security/SanitizeController.java | 4 +++- .../security/ValidateSignatureController.java | 4 +++- .../api/security/WatermarkController.java | 4 +++- .../api/converters/ConvertPDFToMarkdown.java | 4 +++- .../controller/api/EmailController.java | 4 +++- testing/cucumber/features/examples.feature | 2 +- 59 files changed, 195 insertions(+), 79 deletions(-) diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java index b6419890a..27fff75d2 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import java.util.*; @@ -29,7 +31,7 @@ public class AnalysisController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(value = "/page-count", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/page-count", consumes = "multipart/form-data") @Operation( summary = "Get PDF page count", description = "Returns total number of pages in PDF. Input:PDF Output:JSON Type:SISO") @@ -39,7 +41,7 @@ public class AnalysisController { } } - @PostMapping(value = "/basic-info", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/basic-info", consumes = "multipart/form-data") @Operation( summary = "Get basic PDF information", description = "Returns page count, version, file size. Input:PDF Output:JSON Type:SISO") @@ -53,7 +55,7 @@ public class AnalysisController { } } - @PostMapping(value = "/document-properties", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/document-properties", consumes = "multipart/form-data") @Operation( summary = "Get PDF document properties", description = "Returns title, author, subject, etc. Input:PDF Output:JSON Type:SISO") @@ -76,7 +78,7 @@ public class AnalysisController { } } - @PostMapping(value = "/page-dimensions", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/page-dimensions", consumes = "multipart/form-data") @Operation( summary = "Get page dimensions for all pages", description = "Returns width and height of each page. Input:PDF Output:JSON Type:SISO") @@ -96,7 +98,7 @@ public class AnalysisController { } } - @PostMapping(value = "/form-fields", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/form-fields", consumes = "multipart/form-data") @Operation( summary = "Get form field information", description = @@ -119,7 +121,7 @@ public class AnalysisController { } } - @PostMapping(value = "/annotation-info", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/annotation-info", consumes = "multipart/form-data") @Operation( summary = "Get annotation information", description = "Returns count and types of annotations. Input:PDF Output:JSON Type:SISO") @@ -143,7 +145,7 @@ public class AnalysisController { } } - @PostMapping(value = "/font-info", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/font-info", consumes = "multipart/form-data") @Operation( summary = "Get font information", description = @@ -165,7 +167,7 @@ public class AnalysisController { } } - @PostMapping(value = "/security-info", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/security-info", consumes = "multipart/form-data") @Operation( summary = "Get security information", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java index 3a2d16757..f47bd0d0c 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -33,7 +35,7 @@ public class CropController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(value = "/crop", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/crop", consumes = "multipart/form-data") @Operation( summary = "Crops a PDF document", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java index 6a30e6bb3..2f823695e 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.HashMap; @@ -44,7 +46,7 @@ public class EditTableOfContentsController { private final CustomPDFDocumentFactory pdfDocumentFactory; private final ObjectMapper objectMapper; - @PostMapping(value = "/extract-bookmarks", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/extract-bookmarks", consumes = "multipart/form-data") @Operation( summary = "Extract PDF Bookmarks", description = "Extracts bookmarks/table of contents from a PDF document as JSON.") @@ -152,7 +154,7 @@ public class EditTableOfContentsController { return bookmark; } - @PostMapping(value = "/edit-table-of-contents", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/edit-table-of-contents", consumes = "multipart/form-data") @Operation( summary = "Edit Table of Contents", description = "Add or edit bookmarks/table of contents in a PDF document.") diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java index 4e05392c8..538b82a90 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; @@ -154,7 +156,7 @@ public class MergeController { } } - @PostMapping(consumes = "multipart/form-data", value = "/merge-pdfs") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/merge-pdfs") @Operation( summary = "Merge multiple PDF files into one", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java index c57e3a6c0..d07b5314e 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.*; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -36,7 +38,7 @@ public class MultiPageLayoutController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(value = "/multi-page-layout", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/multi-page-layout", consumes = "multipart/form-data") @Operation( summary = "Merge multiple pages of a PDF document into a single page", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java index d6602351e..5c262ecc6 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -46,7 +48,7 @@ public class PdfImageRemovalController { * content type and filename. * @throws IOException If an error occurs while processing the PDF file. */ - @PostMapping(consumes = "multipart/form-data", value = "/remove-image-pdf") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-image-pdf") @Operation( summary = "Remove images from file to reduce the file size.", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java index e6fc2c561..4f90ddac0 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; @@ -39,7 +41,7 @@ public class PdfOverlayController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(value = "/overlay-pdfs", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/overlay-pdfs", consumes = "multipart/form-data") @Operation( summary = "Overlay PDF files in various modes", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java index 717c85016..6254183b0 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -38,7 +40,7 @@ public class RearrangePagesPDFController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/remove-pages") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-pages") @Operation( summary = "Remove pages from a PDF file", description = @@ -237,7 +239,7 @@ public class RearrangePagesPDFController { } } - @PostMapping(consumes = "multipart/form-data", value = "/rearrange-pages") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/rearrange-pages") @Operation( summary = "Rearrange pages in a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/RotationController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/RotationController.java index 58b502cfa..e5a8ae90c 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/RotationController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/RotationController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; @@ -31,7 +33,7 @@ public class RotationController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/rotate-pdf") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/rotate-pdf") @Operation( summary = "Rotate a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java index 56f6f77fa..abc4c4e46 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashMap; @@ -38,7 +40,7 @@ public class ScalePagesController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(value = "/scale-pages", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/scale-pages", consumes = "multipart/form-data") @Operation( summary = "Change the size of a PDF page/document", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java index 0e9cd96dc..efa77b54a 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import java.util.Map; @@ -31,7 +33,7 @@ public class SettingsController { private final ApplicationProperties applicationProperties; private final EndpointConfiguration endpointConfiguration; - @PostMapping("/update-enable-analytics") + @AutoJobPostMapping("/update-enable-analytics") @Hidden public ResponseEntity updateApiKey(@RequestBody Boolean enabled) throws IOException { if (applicationProperties.getSystem().getEnableAnalytics() != null) { diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java index f2425ac9a..32691b2d0 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.file.Files; @@ -41,7 +43,7 @@ public class SplitPDFController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/split-pages") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/split-pages") @Operation( summary = "Split a PDF file into separate documents", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java index f0f9fb012..a30b208c9 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.nio.file.Files; import java.nio.file.Path; @@ -117,7 +119,7 @@ public class SplitPdfByChaptersController { return bookmarks; } - @PostMapping(value = "/split-pdf-by-chapters", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/split-pdf-by-chapters", consumes = "multipart/form-data") @Operation( summary = "Split PDFs by Chapters", description = "Splits a PDF into chapters and returns a ZIP file.") diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java index c2bbd31b5..a27d7f1b9 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.file.Files; @@ -43,7 +45,7 @@ public class SplitPdfBySectionsController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(value = "/split-pdf-by-sections", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/split-pdf-by-sections", consumes = "multipart/form-data") @Operation( summary = "Split PDF pages into smaller sections", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java index 0dbbd933c..adfe42b46 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.file.Files; @@ -39,7 +41,7 @@ public class SplitPdfBySizeController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(value = "/split-by-size-or-count", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/split-by-size-or-count", consumes = "multipart/form-data") @Operation( summary = "Auto split PDF pages into separate documents based on size or count", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java index 104a0f351..e52f1bfef 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.geom.AffineTransform; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -33,7 +35,7 @@ public class ToSinglePageController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/pdf-to-single-page") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf-to-single-page") @Operation( summary = "Convert a multi-page PDF into a single long page PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEmlToPDF.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEmlToPDF.java index 33d51a2a1..1bc2bf2bb 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEmlToPDF.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEmlToPDF.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.converters; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -38,7 +40,7 @@ public class ConvertEmlToPDF { private final RuntimePathConfig runtimePathConfig; private final TempFileManager tempFileManager; - @PostMapping(consumes = "multipart/form-data", value = "/eml/pdf") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/eml/pdf") @Operation( summary = "Convert EML to PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java index 9b3b64506..5adb65d8f 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.converters; +import stirling.software.common.annotations.AutoJobPostMapping; + import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -36,7 +38,7 @@ public class ConvertHtmlToPDF { private final TempFileManager tempFileManager; - @PostMapping(consumes = "multipart/form-data", value = "/html/pdf") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/html/pdf") @Operation( summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java index 5eff72a4a..39af4a002 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.converters; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; @@ -51,7 +53,7 @@ public class ConvertImgPDFController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/pdf/img") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/img") @Operation( summary = "Convert PDF to image(s)", description = @@ -211,7 +213,7 @@ public class ConvertImgPDFController { } } - @PostMapping(consumes = "multipart/form-data", value = "/img/pdf") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/img/pdf") @Operation( summary = "Convert images to a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java index 6cb22be7e..b86b2a8d1 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.converters; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.util.List; import java.util.Map; @@ -45,7 +47,7 @@ public class ConvertMarkdownToPdf { private final TempFileManager tempFileManager; - @PostMapping(consumes = "multipart/form-data", value = "/markdown/pdf") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/markdown/pdf") @Operation( summary = "Convert a Markdown file to PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java index d81e3843f..57e211fcf 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.converters; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -84,7 +86,7 @@ public class ConvertOfficeController { return fileExtension.matches(extensionPattern); } - @PostMapping(consumes = "multipart/form-data", value = "/file/pdf") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/file/pdf") @Operation( summary = "Convert a file to a PDF using LibreOffice", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java index 9015dee2e..6b47a498b 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.converters; +import stirling.software.common.annotations.AutoJobPostMapping; + import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -18,7 +20,7 @@ import stirling.software.common.util.PDFToFile; @RequestMapping("/api/v1/convert") public class ConvertPDFToHtml { - @PostMapping(consumes = "multipart/form-data", value = "/pdf/html") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/html") @Operation( summary = "Convert PDF to HTML", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java index 585185460..3d133f943 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.converters; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; @@ -34,7 +36,7 @@ public class ConvertPDFToOffice { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/pdf/presentation") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/presentation") @Operation( summary = "Convert PDF to Presentation format", description = @@ -49,7 +51,7 @@ public class ConvertPDFToOffice { return pdfToFile.processPdfToOfficeFormat(inputFile, outputFormat, "impress_pdf_import"); } - @PostMapping(consumes = "multipart/form-data", value = "/pdf/text") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/text") @Operation( summary = "Convert PDF to Text or RTF format", description = @@ -77,7 +79,7 @@ public class ConvertPDFToOffice { } } - @PostMapping(consumes = "multipart/form-data", value = "/pdf/word") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/word") @Operation( summary = "Convert PDF to Word document", description = @@ -91,7 +93,7 @@ public class ConvertPDFToOffice { return pdfToFile.processPdfToOfficeFormat(inputFile, outputFormat, "writer_pdf_import"); } - @PostMapping(consumes = "multipart/form-data", value = "/pdf/xml") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/xml") @Operation( summary = "Convert PDF to XML", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java index 7c5435aaa..1e77e2b44 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.converters; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.Color; import java.io.ByteArrayOutputStream; import java.io.File; @@ -78,7 +80,7 @@ import stirling.software.common.util.WebResponseUtils; @Tag(name = "Convert", description = "Convert APIs") public class ConvertPDFToPDFA { - @PostMapping(consumes = "multipart/form-data", value = "/pdf/pdfa") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/pdfa") @Operation( summary = "Convert a PDF to a PDF/A", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java index a7e194d4f..1b5467587 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.converters; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -40,7 +42,7 @@ public class ConvertWebsiteToPDF { private final RuntimePathConfig runtimePathConfig; private final ApplicationProperties applicationProperties; - @PostMapping(consumes = "multipart/form-data", value = "/url/pdf") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/url/pdf") @Operation( summary = "Convert a URL to a PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java index 847904b60..2bec58d38 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.converters; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.StringWriter; @@ -46,7 +48,7 @@ public class ExtractCSVController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(value = "/pdf/csv", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/pdf/csv", consumes = "multipart/form-data") @Operation( summary = "Extracts a CSV document from a PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java index ce9dab8c5..b4e9dc285 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.filters; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; @@ -37,7 +39,7 @@ public class FilterController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/filter-contains-text") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-contains-text") @Operation( summary = "Checks if a PDF contains set text, returns true if does", description = "Input:PDF Output:Boolean Type:SISO") @@ -55,7 +57,7 @@ public class FilterController { } // TODO - @PostMapping(consumes = "multipart/form-data", value = "/filter-contains-image") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-contains-image") @Operation( summary = "Checks if a PDF contains an image", description = "Input:PDF Output:Boolean Type:SISO") @@ -71,7 +73,7 @@ public class FilterController { return null; } - @PostMapping(consumes = "multipart/form-data", value = "/filter-page-count") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-count") @Operation( summary = "Checks if a PDF is greater, less or equal to a setPageCount", description = "Input:PDF Output:Boolean Type:SISO") @@ -104,7 +106,7 @@ public class FilterController { return null; } - @PostMapping(consumes = "multipart/form-data", value = "/filter-page-size") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-size") @Operation( summary = "Checks if a PDF is of a certain size", description = "Input:PDF Output:Boolean Type:SISO") @@ -147,7 +149,7 @@ public class FilterController { return null; } - @PostMapping(consumes = "multipart/form-data", value = "/filter-file-size") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-file-size") @Operation( summary = "Checks if a PDF is a set file size", description = "Input:PDF Output:Boolean Type:SISO") @@ -180,7 +182,7 @@ public class FilterController { return null; } - @PostMapping(consumes = "multipart/form-data", value = "/filter-page-rotation") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-rotation") @Operation( summary = "Checks if a PDF is of a certain rotation", description = "Input:PDF Output:Boolean Type:SISO") diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AttachmentController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AttachmentController.java index b36065612..3729af9d8 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AttachmentController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AttachmentController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import java.util.List; @@ -34,7 +36,7 @@ public class AttachmentController { private final AttachmentServiceInterface pdfAttachmentService; - @PostMapping(consumes = "multipart/form-data", value = "/add-attachments") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-attachments") @Operation( summary = "Add attachments to PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java index 8d803708c..628e0d028 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import java.util.ArrayList; import java.util.Comparator; @@ -38,7 +40,7 @@ public class AutoRenameController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/auto-rename") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/auto-rename") @Operation( summary = "Extract header from PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java index 44d575575..0650481bf 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferInt; @@ -102,7 +104,7 @@ public class AutoSplitPdfController { } } - @PostMapping(value = "/auto-split-pdf", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/auto-split-pdf", consumes = "multipart/form-data") @Operation( summary = "Auto split PDF pages into separate documents", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java index 7d5086b4c..010d6d0bb 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -69,7 +71,7 @@ public class BlankPageController { return whitePixelPercentage >= whitePercent; } - @PostMapping(consumes = "multipart/form-data", value = "/remove-blanks") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-blanks") @Operation( summary = "Remove blank pages from a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java index ab8e5b3f8..9b0b43dc1 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.*; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; @@ -658,7 +660,7 @@ public class CompressController { }; } - @PostMapping(consumes = "multipart/form-data", value = "/compress-pdf") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/compress-pdf") @Operation( summary = "Optimize PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java index 5c432ce57..b5fe504c4 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -38,7 +40,7 @@ public class DecompressPdfController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(value = "/decompress-pdf", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/decompress-pdf", consumes = "multipart/form-data") @Operation( summary = "Decompress PDF streams", description = "Fully decompresses all PDF streams including text content") diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java index 3992595ab..aa3c40519 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.image.BufferedImage; import java.io.FileOutputStream; import java.io.IOException; @@ -50,7 +52,7 @@ public class ExtractImageScansController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/extract-image-scans") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/extract-image-scans") @Operation( summary = "Extract image scans from an input file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java index 09486f9e8..2e2968c9c 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.*; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; @@ -54,7 +56,7 @@ public class ExtractImagesController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/extract-images") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/extract-images") @Operation( summary = "Extract images from a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java index d82a1971a..ecd263c1c 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.image.BufferedImage; import java.io.IOException; @@ -38,7 +40,7 @@ public class FlattenController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/flatten") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/flatten") @Operation( summary = "Flatten PDF form fields or full page", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java index 1d5196940..37b1c209e 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -51,7 +53,7 @@ public class MetadataController { binder.registerCustomEditor(Map.class, "allRequestParams", new StringToMapPropertyEditor()); } - @PostMapping(consumes = "multipart/form-data", value = "/update-metadata") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/update-metadata") @Operation( summary = "Update metadata of a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java index c1fd4ade1..5cd80384c 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.image.BufferedImage; import java.io.*; import java.nio.file.Files; @@ -76,7 +78,7 @@ public class OCRController { .toList(); } - @PostMapping(consumes = "multipart/form-data", value = "/ocr-pdf") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/ocr-pdf") @Operation( summary = "Process a PDF file with OCR", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java index d50c80967..5b61f66ea 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import org.springframework.http.HttpStatus; @@ -31,7 +33,7 @@ public class OverlayImageController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/add-image") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-image") @Operation( summary = "Overlay image onto a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java index 4233d11e4..d91c30bae 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.List; @@ -37,7 +39,7 @@ public class PageNumbersController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(value = "/add-page-numbers", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/add-page-numbers", consumes = "multipart/form-data") @Operation( summary = "Add page numbers to a PDF document", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java index fc7b7d298..34ed58540 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.*; import java.awt.image.BufferedImage; import java.awt.print.PageFormat; @@ -37,7 +39,7 @@ import stirling.software.SPDF.model.api.misc.PrintFileRequest; public class PrintFileController { // TODO - // @PostMapping(value = "/print-file", consumes = "multipart/form-data") + // @AutoJobPostMapping(value = "/print-file", consumes = "multipart/form-data") // @Operation( // summary = "Prints PDF/Image file to a set printer", // description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java index 7cde1d078..e1084a457 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -46,7 +48,7 @@ public class RepairController { return endpointConfiguration.isGroupEnabled("qpdf"); } - @PostMapping(consumes = "multipart/form-data", value = "/repair") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/repair") @Operation( summary = "Repair a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java index 85fb7cfc3..b935d59da 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import org.springframework.core.io.InputStreamResource; @@ -27,7 +29,7 @@ public class ReplaceAndInvertColorController { private final ReplaceAndInvertColorService replaceAndInvertColorService; - @PostMapping(consumes = "multipart/form-data", value = "/replace-invert-pdf") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/replace-invert-pdf") @Operation( summary = "Replace-Invert Color PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ScannerEffectController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ScannerEffectController.java index a94b487b4..a140e9029 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ScannerEffectController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ScannerEffectController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; @@ -52,7 +54,7 @@ public class ScannerEffectController { private static final int MAX_IMAGE_HEIGHT = 8192; private static final long MAX_IMAGE_PIXELS = 16_777_216; // 4096x4096 - @PostMapping(value = "/scanner-effect", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/scanner-effect", consumes = "multipart/form-data") @Operation( summary = "Apply scanner effect to PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java index 94e9b57c6..709d8bd09 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.nio.charset.StandardCharsets; import java.util.Map; @@ -32,7 +34,7 @@ public class ShowJavascript { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/show-javascript") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/show-javascript") @Operation( summary = "Grabs all JS from a PDF and returns a single JS file with all code", description = "desc. Input:PDF Output:JS Type:SISO") diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java index f5bc9dc65..512b241c3 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -52,7 +54,7 @@ public class StampController { private final CustomPDFDocumentFactory pdfDocumentFactory; private final TempFileManager tempFileManager; - @PostMapping(consumes = "multipart/form-data", value = "/add-stamp") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-stamp") @Operation( summary = "Add stamp to a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java index 21fd61d11..d80c35022 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.misc; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; @@ -37,7 +39,7 @@ public class UnlockPDFFormsController { this.pdfDocumentFactory = pdfDocumentFactory; } - @PostMapping(consumes = "multipart/form-data", value = "/unlock-pdf-forms") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/unlock-pdf-forms") @Operation( summary = "Remove read-only property from form fields", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java index d6b4fa0da..166668db9 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.pipeline; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.HashMap; @@ -46,7 +48,7 @@ public class PipelineController { private final PostHogService postHogService; - @PostMapping(value = "/handleData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @AutoJobPostMapping(value = "/handleData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity handleData(@ModelAttribute HandleDataRequest request) throws JsonMappingException, JsonProcessingException { MultipartFile[] files = request.getFileInput(); diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java index 7675355da..b43d918e8 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.security; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.*; import java.beans.PropertyEditorSupport; import java.io.*; @@ -138,7 +140,7 @@ public class CertSignController { } } - @PostMapping( + @AutoJobPostMapping( consumes = { MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_FORM_URLENCODED_VALUE diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java index f3c0a5e29..436b2ba30 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.security; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -188,7 +190,7 @@ public class GetInfoOnPDF { return false; } - @PostMapping(consumes = "multipart/form-data", value = "/get-info-on-pdf") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/get-info-on-pdf") @Operation(summary = "Summary here", description = "desc. Input:PDF Output:JSON Type:SISO") public ResponseEntity getPdfInfo(@ModelAttribute PDFFile request) throws IOException { MultipartFile inputFile = request.getFileInput(); diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java index ef382ee44..d3e78ef6e 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.security; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; @@ -32,7 +34,7 @@ public class PasswordController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/remove-password") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-password") @Operation( summary = "Remove password from a PDF file", description = @@ -58,7 +60,7 @@ public class PasswordController { } } - @PostMapping(consumes = "multipart/form-data", value = "/add-password") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-password") @Operation( summary = "Add password to a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java index 88d271cfb..23d7e20ad 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.security; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.*; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -56,7 +58,7 @@ public class RedactController { List.class, "redactions", new StringToArrayListPropertyEditor()); } - @PostMapping(value = "/redact", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/redact", consumes = "multipart/form-data") @Operation( summary = "Redacts areas and pages in a PDF document", description = @@ -190,7 +192,7 @@ public class RedactController { return pageNumbers; } - @PostMapping(value = "/auto-redact", consumes = "multipart/form-data") + @AutoJobPostMapping(value = "/auto-redact", consumes = "multipart/form-data") @Operation( summary = "Redacts listOfText in a PDF document", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java index 79fd18914..8ecfe7cb7 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.security; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.util.List; import org.apache.pdfbox.pdmodel.PDDocument; @@ -32,7 +34,7 @@ public class RemoveCertSignController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/remove-cert-sign") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-cert-sign") @Operation( summary = "Remove digital signature from PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java index 47e45c595..5935a5152 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.security; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.io.IOException; import org.apache.pdfbox.cos.COSDictionary; @@ -46,7 +48,7 @@ public class SanitizeController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @PostMapping(consumes = "multipart/form-data", value = "/sanitize-pdf") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/sanitize-pdf") @Operation( summary = "Sanitize a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java index a98f0c0d1..0ed9e98f9 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.security; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.beans.PropertyEditorSupport; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -69,7 +71,7 @@ public class ValidateSignatureController { description = "Validates the digital signatures in a PDF file against default or custom" + " certificates. Input:PDF Output:JSON Type:SISO") - @PostMapping(value = "/validate-signature", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @AutoJobPostMapping(value = "/validate-signature", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity> validateSignature( @ModelAttribute SignatureValidationRequest request) throws IOException { List results = new ArrayList<>(); diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java index 484a1c116..b3abf2df7 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.controller.api.security; +import stirling.software.common.annotations.AutoJobPostMapping; + import java.awt.*; import java.awt.image.BufferedImage; import java.beans.PropertyEditorSupport; @@ -64,7 +66,7 @@ public class WatermarkController { }); } - @PostMapping(consumes = "multipart/form-data", value = "/add-watermark") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-watermark") @Operation( summary = "Add watermark to a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPDFToMarkdown.java b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPDFToMarkdown.java index fbbd4723a..a3ebcfd3d 100644 --- a/app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPDFToMarkdown.java +++ b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPDFToMarkdown.java @@ -1,5 +1,7 @@ package stirling.software.SPDF.model.api.converters; +import stirling.software.common.annotations.AutoJobPostMapping; + import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -18,7 +20,7 @@ import stirling.software.common.util.PDFToFile; @RequestMapping("/api/v1/convert") public class ConvertPDFToMarkdown { - @PostMapping(consumes = "multipart/form-data", value = "/pdf/markdown") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/markdown") @Operation( summary = "Convert PDF to Markdown", description = diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java index 7fb767573..839c07083 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java @@ -1,5 +1,7 @@ package stirling.software.proprietary.security.controller.api; +import stirling.software.common.annotations.AutoJobPostMapping; + import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -42,7 +44,7 @@ public class EmailController { * attachment. * @return ResponseEntity with success or error message. */ - @PostMapping(consumes = "multipart/form-data", value = "/send-email") + @AutoJobPostMapping(consumes = "multipart/form-data", value = "/send-email") @Operation( summary = "Send an email with an attachment", description = diff --git a/testing/cucumber/features/examples.feature b/testing/cucumber/features/examples.feature index 398a80ce1..a9cf5b41a 100644 --- a/testing/cucumber/features/examples.feature +++ b/testing/cucumber/features/examples.feature @@ -25,7 +25,7 @@ Feature: API Validation | password | wrongPassword | When I send the API request to the endpoint "/api/v1/security/remove-password" Then the response status code should be 500 - And the response should contain error message "Internal Server Error" + And the response should contain error message "Job failed: org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException: Cannot decrypt PDF, the password is incorrect" @positive @info Scenario: Get info From 1bd166f6fb8835acb834c1e02f2f4df9b3c64469 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Tue, 29 Jul 2025 15:38:37 +0100 Subject: [PATCH 3/9] V2 Update PR-Auto-Deploy-V2.yml to use common tag (#4046) # Description of Changes --- ## Checklist ### General - [ ] 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/devGuide/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/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] 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/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --- .github/workflows/PR-Auto-Deploy-V2.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/PR-Auto-Deploy-V2.yml b/.github/workflows/PR-Auto-Deploy-V2.yml index c8fabfd59..35fa7275c 100644 --- a/.github/workflows/PR-Auto-Deploy-V2.yml +++ b/.github/workflows/PR-Auto-Deploy-V2.yml @@ -261,26 +261,31 @@ jobs: - name: Build and push V2 frontend image if: steps.check-frontend.outputs.exists == 'false' - uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: . file: ./docker/frontend/Dockerfile push: true - tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }} + tags: | + ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }} + ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-latest build-args: VERSION_TAG=v2-alpha platforms: linux/amd64 - + - name: Build and push V2 backend image if: steps.check-backend.outputs.exists == 'false' - uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: . file: ./docker/backend/Dockerfile push: true - tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-${{ steps.commit-hashes.outputs.backend_short }} + tags: | + ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-${{ steps.commit-hashes.outputs.backend_short }} + ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-latest build-args: VERSION_TAG=v2-alpha platforms: linux/amd64 + - name: Set up SSH run: | mkdir -p ~/.ssh/ From 8989bdb211774b734058148163a57fe1bec3301b Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Tue, 29 Jul 2025 15:49:27 +0100 Subject: [PATCH 4/9] Revert "V2 Update PR-Auto-Deploy-V2.yml to use common tag" (#4047) Reverts Stirling-Tools/Stirling-PDF#4046 --- .github/workflows/PR-Auto-Deploy-V2.yml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.github/workflows/PR-Auto-Deploy-V2.yml b/.github/workflows/PR-Auto-Deploy-V2.yml index 35fa7275c..c8fabfd59 100644 --- a/.github/workflows/PR-Auto-Deploy-V2.yml +++ b/.github/workflows/PR-Auto-Deploy-V2.yml @@ -261,31 +261,26 @@ jobs: - name: Build and push V2 frontend image if: steps.check-frontend.outputs.exists == 'false' - uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: . file: ./docker/frontend/Dockerfile push: true - tags: | - ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }} - ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-latest + tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }} build-args: VERSION_TAG=v2-alpha platforms: linux/amd64 - + - name: Build and push V2 backend image if: steps.check-backend.outputs.exists == 'false' - uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: . file: ./docker/backend/Dockerfile push: true - tags: | - ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-${{ steps.commit-hashes.outputs.backend_short }} - ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-latest + tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-${{ steps.commit-hashes.outputs.backend_short }} build-args: VERSION_TAG=v2-alpha platforms: linux/amd64 - - name: Set up SSH run: | mkdir -p ~/.ssh/ From dbe84f7e96859705e0be4508e39352f5a2276fef Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Tue, 29 Jul 2025 15:50:36 +0100 Subject: [PATCH 5/9] Update deploy-on-v2-commit.yml --- .github/workflows/deploy-on-v2-commit.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-on-v2-commit.yml b/.github/workflows/deploy-on-v2-commit.yml index d5e3a7b16..3c9ba85b8 100644 --- a/.github/workflows/deploy-on-v2-commit.yml +++ b/.github/workflows/deploy-on-v2-commit.yml @@ -98,7 +98,9 @@ jobs: context: . file: ./docker/frontend/Dockerfile push: true - tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }} + tags: | + ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }} + ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-latest build-args: VERSION_TAG=v2-alpha platforms: linux/amd64 @@ -109,7 +111,9 @@ jobs: context: . file: ./docker/backend/Dockerfile push: true - tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-${{ steps.commit-hashes.outputs.backend_short }} + tags: | + ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-${{ steps.commit-hashes.outputs.backend_short }} + ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-latest build-args: VERSION_TAG=v2-alpha platforms: linux/amd64 From 989052b0997c52be212a88620bece3efb05e8088 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Tue, 29 Jul 2025 16:00:08 +0100 Subject: [PATCH 6/9] Update deploy-on-v2-commit.yml --- .github/workflows/deploy-on-v2-commit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-on-v2-commit.yml b/.github/workflows/deploy-on-v2-commit.yml index 3c9ba85b8..8c3218869 100644 --- a/.github/workflows/deploy-on-v2-commit.yml +++ b/.github/workflows/deploy-on-v2-commit.yml @@ -100,7 +100,7 @@ jobs: push: true tags: | ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }} - ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-latest + ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-latest build-args: VERSION_TAG=v2-alpha platforms: linux/amd64 From a6df5e4246952f8d3fb542291c44ce7a84c86d32 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Wed, 30 Jul 2025 11:19:13 +0100 Subject: [PATCH 7/9] Update docker-compose.yml --- docker/compose/docker-compose.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker/compose/docker-compose.yml b/docker/compose/docker-compose.yml index 4defef872..b0061f785 100644 --- a/docker/compose/docker-compose.yml +++ b/docker/compose/docker-compose.yml @@ -25,7 +25,6 @@ services: environment: 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 UI_APPNAME: Stirling-PDF UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest @@ -59,4 +58,4 @@ networks: volumes: stirling-data: stirling-config: - stirling-logs: \ No newline at end of file + stirling-logs: From fc89ee2c783ef0fd9efc6fe101aa3a14c128d89d Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Wed, 30 Jul 2025 11:19:28 +0100 Subject: [PATCH 8/9] Update docker-compose.fat.yml --- docker/compose/docker-compose.fat.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docker/compose/docker-compose.fat.yml b/docker/compose/docker-compose.fat.yml index 8399c4080..1757782d5 100644 --- a/docker/compose/docker-compose.fat.yml +++ b/docker/compose/docker-compose.fat.yml @@ -26,8 +26,6 @@ services: DISABLE_ADDITIONAL_FEATURES: "false" SECURITY_ENABLELOGIN: "false" FAT_DOCKER: "true" - INSTALL_BOOK_AND_ADVANCED_HTML_OPS: "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 UI_APPNAME: Stirling-PDF UI_HOMEDESCRIPTION: Full-featured Stirling-PDF with all capabilities @@ -61,4 +59,4 @@ networks: volumes: stirling-data: stirling-config: - stirling-logs: \ No newline at end of file + stirling-logs: From 64a471c3a9ec25ab287586529d9deb972029feef Mon Sep 17 00:00:00 2001 From: Ludy Date: Wed, 30 Jul 2025 23:38:03 +0200 Subject: [PATCH 9/9] fix(workflows): correct YAML indentation in frontend license update workflow (#4056) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …orkflow # Description of Changes - Fixed invalid YAML syntax caused by inconsistent indentation inside a multi-line JavaScript template string in `.github/workflows/frontend-licenses-update.yml`. - The incorrect indentation broke the GitHub Actions runner with a syntax error on line 131. - This change ensures that the entire `commentBody = \`...\`;` block is treated as a valid JavaScript string inside the `run:` shell context. --- ## Checklist ### General - [ ] 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/devGuide/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/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] 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/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --- .github/workflows/frontend-licenses-update.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/frontend-licenses-update.yml b/.github/workflows/frontend-licenses-update.yml index b6f37ce3a..ac8676c8a 100644 --- a/.github/workflows/frontend-licenses-update.yml +++ b/.github/workflows/frontend-licenses-update.yml @@ -126,19 +126,19 @@ jobs: commentBody = `## ❌ Frontend License Check Failed -The frontend license check has detected compatibility warnings that require review: + The frontend license check has detected compatibility warnings that require review: -${warningDetails} + ${warningDetails} -**Action Required:** Please review these licenses to ensure they are acceptable for your use case before merging. + **Action Required:** Please review these licenses to ensure they are acceptable for your use case before merging. -_This check will fail the PR until license issues are resolved._`; + _This check will fail the PR until license issues are resolved._`; } else { commentBody = `## ✅ Frontend License Check Passed -All frontend licenses have been validated and no compatibility warnings were detected. + All frontend licenses have been validated and no compatibility warnings were detected. -The frontend license report has been updated successfully.`; + The frontend license report has been updated successfully.`; } await github.rest.issues.createComment({