mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-04 03:25:21 +00:00
Merge remote-tracking branch 'origin/V2' into feature/react-convert
This commit is contained in:
commit
0c67b640c2
1
.github/workflows/PR-Auto-Deploy-V2.yml
vendored
1
.github/workflows/PR-Auto-Deploy-V2.yml
vendored
@ -317,6 +317,7 @@ jobs:
|
|||||||
SYSTEM_MAXFILESIZE: "100"
|
SYSTEM_MAXFILESIZE: "100"
|
||||||
METRICS_ENABLED: "true"
|
METRICS_ENABLED: "true"
|
||||||
SYSTEM_GOOGLEVISIBILITY: "false"
|
SYSTEM_GOOGLEVISIBILITY: "false"
|
||||||
|
SWAGGER_SERVER_URL: "http://${{ secrets.VPS_HOST }}:${V2_PORT}"
|
||||||
restart: on-failure:5
|
restart: on-failure:5
|
||||||
|
|
||||||
stirling-pdf-v2-frontend:
|
stirling-pdf-v2-frontend:
|
||||||
|
9
.github/workflows/deploy-on-v2-commit.yml
vendored
9
.github/workflows/deploy-on-v2-commit.yml
vendored
@ -98,7 +98,9 @@ jobs:
|
|||||||
context: .
|
context: .
|
||||||
file: ./docker/frontend/Dockerfile
|
file: ./docker/frontend/Dockerfile
|
||||||
push: true
|
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
|
build-args: VERSION_TAG=v2-alpha
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
|
|
||||||
@ -109,7 +111,9 @@ jobs:
|
|||||||
context: .
|
context: .
|
||||||
file: ./docker/backend/Dockerfile
|
file: ./docker/backend/Dockerfile
|
||||||
push: true
|
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
|
build-args: VERSION_TAG=v2-alpha
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
|
|
||||||
@ -147,6 +151,7 @@ jobs:
|
|||||||
SYSTEM_MAXFILESIZE: "100"
|
SYSTEM_MAXFILESIZE: "100"
|
||||||
METRICS_ENABLED: "true"
|
METRICS_ENABLED: "true"
|
||||||
SYSTEM_GOOGLEVISIBILITY: "false"
|
SYSTEM_GOOGLEVISIBILITY: "false"
|
||||||
|
SWAGGER_SERVER_URL: "http://${{ secrets.VPS_HOST }}:3000"
|
||||||
restart: on-failure:5
|
restart: on-failure:5
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
|
12
.github/workflows/frontend-licenses-update.yml
vendored
12
.github/workflows/frontend-licenses-update.yml
vendored
@ -126,19 +126,19 @@ jobs:
|
|||||||
|
|
||||||
commentBody = `## ❌ Frontend License Check Failed
|
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 {
|
} else {
|
||||||
commentBody = `## ✅ Frontend License Check Passed
|
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({
|
await github.rest.issues.createComment({
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -27,7 +27,7 @@ clientWebUI/
|
|||||||
!cucumber/exampleFiles/
|
!cucumber/exampleFiles/
|
||||||
!cucumber/exampleFiles/example_html.zip
|
!cucumber/exampleFiles/example_html.zip
|
||||||
exampleYmlFiles/stirling/
|
exampleYmlFiles/stirling/
|
||||||
stirling/
|
/stirling/
|
||||||
/testing/file_snapshots
|
/testing/file_snapshots
|
||||||
SwaggerDoc.json
|
SwaggerDoc.json
|
||||||
|
|
||||||
|
@ -39,6 +39,11 @@ public class CleanUrlInterceptor implements HandlerInterceptor {
|
|||||||
String queryString = request.getQueryString();
|
String queryString = request.getQueryString();
|
||||||
if (queryString != null && !queryString.isEmpty()) {
|
if (queryString != null && !queryString.isEmpty()) {
|
||||||
String requestURI = request.getRequestURI();
|
String requestURI = request.getRequestURI();
|
||||||
|
|
||||||
|
if (requestURI.contains("/api/")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, String> allowedParameters = new HashMap<>();
|
Map<String, String> allowedParameters = new HashMap<>();
|
||||||
|
|
||||||
// Keep only the allowed parameters
|
// Keep only the allowed parameters
|
||||||
|
@ -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.info.License;
|
||||||
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||||
|
import io.swagger.v3.oas.models.servers.Server;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
@ -50,17 +51,26 @@ public class OpenApiConfig {
|
|||||||
.url("https://www.stirlingpdf.com")
|
.url("https://www.stirlingpdf.com")
|
||||||
.email("contact@stirlingpdf.com"))
|
.email("contact@stirlingpdf.com"))
|
||||||
.description(DEFAULT_DESCRIPTION);
|
.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()) {
|
if (!applicationProperties.getSecurity().getEnableLogin()) {
|
||||||
return new OpenAPI().components(new Components()).info(info);
|
return openAPI.components(new Components());
|
||||||
} else {
|
} else {
|
||||||
SecurityScheme apiKeyScheme =
|
SecurityScheme apiKeyScheme =
|
||||||
new SecurityScheme()
|
new SecurityScheme()
|
||||||
.type(SecurityScheme.Type.APIKEY)
|
.type(SecurityScheme.Type.APIKEY)
|
||||||
.in(SecurityScheme.In.HEADER)
|
.in(SecurityScheme.In.HEADER)
|
||||||
.name("X-API-KEY");
|
.name("X-API-KEY");
|
||||||
return new OpenAPI()
|
return openAPI
|
||||||
.components(new Components().addSecuritySchemes("apiKey", apiKeyScheme))
|
.components(new Components().addSecuritySchemes("apiKey", apiKeyScheme))
|
||||||
.info(info)
|
|
||||||
.addSecurityItem(new SecurityRequirement().addList("apiKey"));
|
.addSecurityItem(new SecurityRequirement().addList("apiKey"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -29,7 +31,7 @@ public class AnalysisController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(value = "/page-count", consumes = "multipart/form-data")
|
@AutoJobPostMapping(value = "/page-count", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Get PDF page count",
|
summary = "Get PDF page count",
|
||||||
description = "Returns total number of pages in PDF. Input:PDF Output:JSON Type:SISO")
|
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(
|
@Operation(
|
||||||
summary = "Get basic PDF information",
|
summary = "Get basic PDF information",
|
||||||
description = "Returns page count, version, file size. Input:PDF Output:JSON Type:SISO")
|
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(
|
@Operation(
|
||||||
summary = "Get PDF document properties",
|
summary = "Get PDF document properties",
|
||||||
description = "Returns title, author, subject, etc. Input:PDF Output:JSON Type:SISO")
|
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(
|
@Operation(
|
||||||
summary = "Get page dimensions for all pages",
|
summary = "Get page dimensions for all pages",
|
||||||
description = "Returns width and height of each page. Input:PDF Output:JSON Type:SISO")
|
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(
|
@Operation(
|
||||||
summary = "Get form field information",
|
summary = "Get form field information",
|
||||||
description =
|
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(
|
@Operation(
|
||||||
summary = "Get annotation information",
|
summary = "Get annotation information",
|
||||||
description = "Returns count and types of annotations. Input:PDF Output:JSON Type:SISO")
|
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(
|
@Operation(
|
||||||
summary = "Get font information",
|
summary = "Get font information",
|
||||||
description =
|
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(
|
@Operation(
|
||||||
summary = "Get security information",
|
summary = "Get security information",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -33,7 +35,7 @@ public class CropController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(value = "/crop", consumes = "multipart/form-data")
|
@AutoJobPostMapping(value = "/crop", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Crops a PDF document",
|
summary = "Crops a PDF document",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -44,7 +46,7 @@ public class EditTableOfContentsController {
|
|||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
@PostMapping(value = "/extract-bookmarks", consumes = "multipart/form-data")
|
@AutoJobPostMapping(value = "/extract-bookmarks", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Extract PDF Bookmarks",
|
summary = "Extract PDF Bookmarks",
|
||||||
description = "Extracts bookmarks/table of contents from a PDF document as JSON.")
|
description = "Extracts bookmarks/table of contents from a PDF document as JSON.")
|
||||||
@ -152,7 +154,7 @@ public class EditTableOfContentsController {
|
|||||||
return bookmark;
|
return bookmark;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/edit-table-of-contents", consumes = "multipart/form-data")
|
@AutoJobPostMapping(value = "/edit-table-of-contents", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Edit Table of Contents",
|
summary = "Edit Table of Contents",
|
||||||
description = "Add or edit bookmarks/table of contents in a PDF document.")
|
description = "Add or edit bookmarks/table of contents in a PDF document.")
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
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(
|
@Operation(
|
||||||
summary = "Merge multiple PDF files into one",
|
summary = "Merge multiple PDF files into one",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -36,7 +38,7 @@ public class MultiPageLayoutController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(value = "/multi-page-layout", consumes = "multipart/form-data")
|
@AutoJobPostMapping(value = "/multi-page-layout", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Merge multiple pages of a PDF document into a single page",
|
summary = "Merge multiple pages of a PDF document into a single page",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -46,7 +48,7 @@ public class PdfImageRemovalController {
|
|||||||
* content type and filename.
|
* content type and filename.
|
||||||
* @throws IOException If an error occurs while processing the PDF file.
|
* @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(
|
@Operation(
|
||||||
summary = "Remove images from file to reduce the file size.",
|
summary = "Remove images from file to reduce the file size.",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -39,7 +41,7 @@ public class PdfOverlayController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(value = "/overlay-pdfs", consumes = "multipart/form-data")
|
@AutoJobPostMapping(value = "/overlay-pdfs", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Overlay PDF files in various modes",
|
summary = "Overlay PDF files in various modes",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -38,7 +40,7 @@ public class RearrangePagesPDFController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-pages")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-pages")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Remove pages from a PDF file",
|
summary = "Remove pages from a PDF file",
|
||||||
description =
|
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(
|
@Operation(
|
||||||
summary = "Rearrange pages in a PDF file",
|
summary = "Rearrange pages in a PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
@ -31,7 +33,7 @@ public class RotationController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/rotate-pdf")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/rotate-pdf")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Rotate a PDF file",
|
summary = "Rotate a PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -38,7 +40,7 @@ public class ScalePagesController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(value = "/scale-pages", consumes = "multipart/form-data")
|
@AutoJobPostMapping(value = "/scale-pages", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Change the size of a PDF page/document",
|
summary = "Change the size of a PDF page/document",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -31,7 +33,7 @@ public class SettingsController {
|
|||||||
private final ApplicationProperties applicationProperties;
|
private final ApplicationProperties applicationProperties;
|
||||||
private final EndpointConfiguration endpointConfiguration;
|
private final EndpointConfiguration endpointConfiguration;
|
||||||
|
|
||||||
@PostMapping("/update-enable-analytics")
|
@AutoJobPostMapping("/update-enable-analytics")
|
||||||
@Hidden
|
@Hidden
|
||||||
public ResponseEntity<String> updateApiKey(@RequestBody Boolean enabled) throws IOException {
|
public ResponseEntity<String> updateApiKey(@RequestBody Boolean enabled) throws IOException {
|
||||||
if (applicationProperties.getSystem().getEnableAnalytics() != null) {
|
if (applicationProperties.getSystem().getEnableAnalytics() != null) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -41,7 +43,7 @@ public class SplitPDFController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/split-pages")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/split-pages")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Split a PDF file into separate documents",
|
summary = "Split a PDF file into separate documents",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@ -117,7 +119,7 @@ public class SplitPdfByChaptersController {
|
|||||||
return bookmarks;
|
return bookmarks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/split-pdf-by-chapters", consumes = "multipart/form-data")
|
@AutoJobPostMapping(value = "/split-pdf-by-chapters", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Split PDFs by Chapters",
|
summary = "Split PDFs by Chapters",
|
||||||
description = "Splits a PDF into chapters and returns a ZIP file.")
|
description = "Splits a PDF into chapters and returns a ZIP file.")
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -43,7 +45,7 @@ public class SplitPdfBySectionsController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
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(
|
@Operation(
|
||||||
summary = "Split PDF pages into smaller sections",
|
summary = "Split PDF pages into smaller sections",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -39,7 +41,7 @@ public class SplitPdfBySizeController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
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(
|
@Operation(
|
||||||
summary = "Auto split PDF pages into separate documents based on size or count",
|
summary = "Auto split PDF pages into separate documents based on size or count",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.AffineTransform;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -33,7 +35,7 @@ public class ToSinglePageController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
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(
|
@Operation(
|
||||||
summary = "Convert a multi-page PDF into a single long page PDF",
|
summary = "Convert a multi-page PDF into a single long page PDF",
|
||||||
description =
|
description =
|
||||||
|
@ -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<HomeData> 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<LicensesData> 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<String, List<Dependency>> 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<PipelineData> getPipelineData() {
|
||||||
|
PipelineData data = new PipelineData();
|
||||||
|
List<String> pipelineConfigs = new ArrayList<>();
|
||||||
|
List<Map<String, String>> pipelineConfigsWithNames = new ArrayList<>();
|
||||||
|
|
||||||
|
if (new java.io.File(runtimePathConfig.getPipelineDefaultWebUiConfigs()).exists()) {
|
||||||
|
try (Stream<Path> paths =
|
||||||
|
Files.walk(Paths.get(runtimePathConfig.getPipelineDefaultWebUiConfigs()))) {
|
||||||
|
List<Path> 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<String, Object> jsonContent =
|
||||||
|
new ObjectMapper()
|
||||||
|
.readValue(config, new TypeReference<Map<String, Object>>() {});
|
||||||
|
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<String, String> 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<String, String> 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<SignData> getSignData() {
|
||||||
|
String username = "";
|
||||||
|
if (userService != null) {
|
||||||
|
username = userService.getCurrentUsername();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SignatureFile> signatures = signatureService.getAvailableSignatures(username);
|
||||||
|
List<FontResource> 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<OcrData> getOcrPdfData() {
|
||||||
|
List<String> languages = getAvailableTesseractLanguages();
|
||||||
|
|
||||||
|
OcrData data = new OcrData();
|
||||||
|
data.setLanguages(languages);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> 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<FontResource> getFontNames() {
|
||||||
|
List<FontResource> 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<FontResource> 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<Dependency> dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class PipelineData {
|
||||||
|
private List<Map<String, String>> pipelineConfigsWithNames;
|
||||||
|
private List<String> pipelineConfigs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class SignData {
|
||||||
|
private List<SignatureFile> signatures;
|
||||||
|
private List<FontResource> fonts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class OcrData {
|
||||||
|
private List<String> 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 "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
@ -38,7 +40,7 @@ public class ConvertEmlToPDF {
|
|||||||
private final RuntimePathConfig runtimePathConfig;
|
private final RuntimePathConfig runtimePathConfig;
|
||||||
private final TempFileManager tempFileManager;
|
private final TempFileManager tempFileManager;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/eml/pdf")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/eml/pdf")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Convert EML to PDF",
|
summary = "Convert EML to PDF",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@ -36,7 +38,7 @@ public class ConvertHtmlToPDF {
|
|||||||
|
|
||||||
private final TempFileManager tempFileManager;
|
private final TempFileManager tempFileManager;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/html/pdf")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/html/pdf")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF",
|
summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -51,7 +53,7 @@ public class ConvertImgPDFController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/img")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/img")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Convert PDF to image(s)",
|
summary = "Convert PDF to image(s)",
|
||||||
description =
|
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(
|
@Operation(
|
||||||
summary = "Convert images to a PDF file",
|
summary = "Convert images to a PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -45,7 +47,7 @@ public class ConvertMarkdownToPdf {
|
|||||||
|
|
||||||
private final TempFileManager tempFileManager;
|
private final TempFileManager tempFileManager;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/markdown/pdf")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/markdown/pdf")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Convert a Markdown file to PDF",
|
summary = "Convert a Markdown file to PDF",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -84,7 +86,7 @@ public class ConvertOfficeController {
|
|||||||
return fileExtension.matches(extensionPattern);
|
return fileExtension.matches(extensionPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/file/pdf")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/file/pdf")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Convert a file to a PDF using LibreOffice",
|
summary = "Convert a file to a PDF using LibreOffice",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@ -18,7 +20,7 @@ import stirling.software.common.util.PDFToFile;
|
|||||||
@RequestMapping("/api/v1/convert")
|
@RequestMapping("/api/v1/convert")
|
||||||
public class ConvertPDFToHtml {
|
public class ConvertPDFToHtml {
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/html")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/html")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Convert PDF to HTML",
|
summary = "Convert PDF to HTML",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
@ -34,7 +36,7 @@ public class ConvertPDFToOffice {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/presentation")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/presentation")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Convert PDF to Presentation format",
|
summary = "Convert PDF to Presentation format",
|
||||||
description =
|
description =
|
||||||
@ -49,7 +51,7 @@ public class ConvertPDFToOffice {
|
|||||||
return pdfToFile.processPdfToOfficeFormat(inputFile, outputFormat, "impress_pdf_import");
|
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(
|
@Operation(
|
||||||
summary = "Convert PDF to Text or RTF format",
|
summary = "Convert PDF to Text or RTF format",
|
||||||
description =
|
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(
|
@Operation(
|
||||||
summary = "Convert PDF to Word document",
|
summary = "Convert PDF to Word document",
|
||||||
description =
|
description =
|
||||||
@ -91,7 +93,7 @@ public class ConvertPDFToOffice {
|
|||||||
return pdfToFile.processPdfToOfficeFormat(inputFile, outputFormat, "writer_pdf_import");
|
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(
|
@Operation(
|
||||||
summary = "Convert PDF to XML",
|
summary = "Convert PDF to XML",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -78,7 +80,7 @@ import stirling.software.common.util.WebResponseUtils;
|
|||||||
@Tag(name = "Convert", description = "Convert APIs")
|
@Tag(name = "Convert", description = "Convert APIs")
|
||||||
public class ConvertPDFToPDFA {
|
public class ConvertPDFToPDFA {
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/pdfa")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/pdfa")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Convert a PDF to a PDF/A",
|
summary = "Convert a PDF to a PDF/A",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@ -40,7 +42,7 @@ public class ConvertWebsiteToPDF {
|
|||||||
private final RuntimePathConfig runtimePathConfig;
|
private final RuntimePathConfig runtimePathConfig;
|
||||||
private final ApplicationProperties applicationProperties;
|
private final ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/url/pdf")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/url/pdf")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Convert a URL to a PDF",
|
summary = "Convert a URL to a PDF",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
@ -46,7 +48,7 @@ public class ExtractCSVController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(value = "/pdf/csv", consumes = "multipart/form-data")
|
@AutoJobPostMapping(value = "/pdf/csv", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Extracts a CSV document from a PDF",
|
summary = "Extracts a CSV document from a PDF",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.filters;
|
package stirling.software.SPDF.controller.api.filters;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
@ -37,7 +39,7 @@ public class FilterController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/filter-contains-text")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-contains-text")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Checks if a PDF contains set text, returns true if does",
|
summary = "Checks if a PDF contains set text, returns true if does",
|
||||||
description = "Input:PDF Output:Boolean Type:SISO")
|
description = "Input:PDF Output:Boolean Type:SISO")
|
||||||
@ -55,7 +57,7 @@ public class FilterController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/filter-contains-image")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-contains-image")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Checks if a PDF contains an image",
|
summary = "Checks if a PDF contains an image",
|
||||||
description = "Input:PDF Output:Boolean Type:SISO")
|
description = "Input:PDF Output:Boolean Type:SISO")
|
||||||
@ -71,7 +73,7 @@ public class FilterController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/filter-page-count")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-count")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Checks if a PDF is greater, less or equal to a setPageCount",
|
summary = "Checks if a PDF is greater, less or equal to a setPageCount",
|
||||||
description = "Input:PDF Output:Boolean Type:SISO")
|
description = "Input:PDF Output:Boolean Type:SISO")
|
||||||
@ -104,7 +106,7 @@ public class FilterController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/filter-page-size")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-size")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Checks if a PDF is of a certain size",
|
summary = "Checks if a PDF is of a certain size",
|
||||||
description = "Input:PDF Output:Boolean Type:SISO")
|
description = "Input:PDF Output:Boolean Type:SISO")
|
||||||
@ -147,7 +149,7 @@ public class FilterController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/filter-file-size")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-file-size")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Checks if a PDF is a set file size",
|
summary = "Checks if a PDF is a set file size",
|
||||||
description = "Input:PDF Output:Boolean Type:SISO")
|
description = "Input:PDF Output:Boolean Type:SISO")
|
||||||
@ -180,7 +182,7 @@ public class FilterController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/filter-page-rotation")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-rotation")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Checks if a PDF is of a certain rotation",
|
summary = "Checks if a PDF is of a certain rotation",
|
||||||
description = "Input:PDF Output:Boolean Type:SISO")
|
description = "Input:PDF Output:Boolean Type:SISO")
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -34,7 +36,7 @@ public class AttachmentController {
|
|||||||
|
|
||||||
private final AttachmentServiceInterface pdfAttachmentService;
|
private final AttachmentServiceInterface pdfAttachmentService;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/add-attachments")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-attachments")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Add attachments to PDF",
|
summary = "Add attachments to PDF",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@ -38,7 +40,7 @@ public class AutoRenameController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/auto-rename")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/auto-rename")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Extract header from PDF file",
|
summary = "Extract header from PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.DataBufferByte;
|
import java.awt.image.DataBufferByte;
|
||||||
import java.awt.image.DataBufferInt;
|
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(
|
@Operation(
|
||||||
summary = "Auto split PDF pages into separate documents",
|
summary = "Auto split PDF pages into separate documents",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -69,7 +71,7 @@ public class BlankPageController {
|
|||||||
return whitePixelPercentage >= whitePercent;
|
return whitePixelPercentage >= whitePercent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-blanks")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-blanks")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Remove blank pages from a PDF file",
|
summary = "Remove blank pages from a PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayOutputStream;
|
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(
|
@Operation(
|
||||||
summary = "Optimize PDF file",
|
summary = "Optimize PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -110,14 +110,14 @@ public class ConfigController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/endpoint-enabled")
|
@GetMapping("/endpoint-enabled")
|
||||||
public ResponseEntity<Boolean> isEndpointEnabled(@RequestParam String endpoint) {
|
public ResponseEntity<Boolean> isEndpointEnabled(@RequestParam(name = "endpoint") String endpoint) {
|
||||||
boolean enabled = endpointConfiguration.isEndpointEnabled(endpoint);
|
boolean enabled = endpointConfiguration.isEndpointEnabled(endpoint);
|
||||||
return ResponseEntity.ok(enabled);
|
return ResponseEntity.ok(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/endpoints-enabled")
|
@GetMapping("/endpoints-enabled")
|
||||||
public ResponseEntity<Map<String, Boolean>> areEndpointsEnabled(
|
public ResponseEntity<Map<String, Boolean>> areEndpointsEnabled(
|
||||||
@RequestParam String endpoints) {
|
@RequestParam(name = "endpoints") String endpoints) {
|
||||||
Map<String, Boolean> result = new HashMap<>();
|
Map<String, Boolean> result = new HashMap<>();
|
||||||
String[] endpointArray = endpoints.split(",");
|
String[] endpointArray = endpoints.split(",");
|
||||||
for (String endpoint : endpointArray) {
|
for (String endpoint : endpointArray) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@ -38,7 +40,7 @@ public class DecompressPdfController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(value = "/decompress-pdf", consumes = "multipart/form-data")
|
@AutoJobPostMapping(value = "/decompress-pdf", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Decompress PDF streams",
|
summary = "Decompress PDF streams",
|
||||||
description = "Fully decompresses all PDF streams including text content")
|
description = "Fully decompresses all PDF streams including text content")
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -50,7 +52,7 @@ public class ExtractImageScansController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/extract-image-scans")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/extract-image-scans")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Extract image scans from an input file",
|
summary = "Extract image scans from an input file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.RenderedImage;
|
import java.awt.image.RenderedImage;
|
||||||
@ -54,7 +56,7 @@ public class ExtractImagesController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/extract-images")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/extract-images")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Extract images from a PDF file",
|
summary = "Extract images from a PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -38,7 +40,7 @@ public class FlattenController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/flatten")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/flatten")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Flatten PDF form fields or full page",
|
summary = "Flatten PDF form fields or full page",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@ -51,7 +53,7 @@ public class MetadataController {
|
|||||||
binder.registerCustomEditor(Map.class, "allRequestParams", new StringToMapPropertyEditor());
|
binder.registerCustomEditor(Map.class, "allRequestParams", new StringToMapPropertyEditor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/update-metadata")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/update-metadata")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Update metadata of a PDF file",
|
summary = "Update metadata of a PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -76,7 +78,7 @@ public class OCRController {
|
|||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/ocr-pdf")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/ocr-pdf")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Process a PDF file with OCR",
|
summary = "Process a PDF file with OCR",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@ -31,7 +33,7 @@ public class OverlayImageController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/add-image")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-image")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Overlay image onto a PDF file",
|
summary = "Overlay image onto a PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -37,7 +39,7 @@ public class PageNumbersController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(value = "/add-page-numbers", consumes = "multipart/form-data")
|
@AutoJobPostMapping(value = "/add-page-numbers", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Add page numbers to a PDF document",
|
summary = "Add page numbers to a PDF document",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.print.PageFormat;
|
import java.awt.print.PageFormat;
|
||||||
@ -37,7 +39,7 @@ import stirling.software.SPDF.model.api.misc.PrintFileRequest;
|
|||||||
public class PrintFileController {
|
public class PrintFileController {
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// @PostMapping(value = "/print-file", consumes = "multipart/form-data")
|
// @AutoJobPostMapping(value = "/print-file", consumes = "multipart/form-data")
|
||||||
// @Operation(
|
// @Operation(
|
||||||
// summary = "Prints PDF/Image file to a set printer",
|
// summary = "Prints PDF/Image file to a set printer",
|
||||||
// description =
|
// description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -46,7 +48,7 @@ public class RepairController {
|
|||||||
return endpointConfiguration.isGroupEnabled("qpdf");
|
return endpointConfiguration.isGroupEnabled("qpdf");
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/repair")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/repair")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Repair a PDF file",
|
summary = "Repair a PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.springframework.core.io.InputStreamResource;
|
import org.springframework.core.io.InputStreamResource;
|
||||||
@ -27,7 +29,7 @@ public class ReplaceAndInvertColorController {
|
|||||||
|
|
||||||
private final ReplaceAndInvertColorService replaceAndInvertColorService;
|
private final ReplaceAndInvertColorService replaceAndInvertColorService;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/replace-invert-pdf")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/replace-invert-pdf")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Replace-Invert Color PDF",
|
summary = "Replace-Invert Color PDF",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.RenderingHints;
|
import java.awt.RenderingHints;
|
||||||
@ -52,7 +54,7 @@ public class ScannerEffectController {
|
|||||||
private static final int MAX_IMAGE_HEIGHT = 8192;
|
private static final int MAX_IMAGE_HEIGHT = 8192;
|
||||||
private static final long MAX_IMAGE_PIXELS = 16_777_216; // 4096x4096
|
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(
|
@Operation(
|
||||||
summary = "Apply scanner effect to PDF",
|
summary = "Apply scanner effect to PDF",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -32,7 +34,7 @@ public class ShowJavascript {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/show-javascript")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/show-javascript")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Grabs all JS from a PDF and returns a single JS file with all code",
|
summary = "Grabs all JS from a PDF and returns a single JS file with all code",
|
||||||
description = "desc. Input:PDF Output:JS Type:SISO")
|
description = "desc. Input:PDF Output:JS Type:SISO")
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -52,7 +54,7 @@ public class StampController {
|
|||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
private final TempFileManager tempFileManager;
|
private final TempFileManager tempFileManager;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/add-stamp")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-stamp")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Add stamp to a PDF file",
|
summary = "Add stamp to a PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -37,7 +39,7 @@ public class UnlockPDFFormsController {
|
|||||||
this.pdfDocumentFactory = pdfDocumentFactory;
|
this.pdfDocumentFactory = pdfDocumentFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/unlock-pdf-forms")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/unlock-pdf-forms")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Remove read-only property from form fields",
|
summary = "Remove read-only property from form fields",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.pipeline;
|
package stirling.software.SPDF.controller.api.pipeline;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -46,7 +48,7 @@ public class PipelineController {
|
|||||||
|
|
||||||
private final PostHogService postHogService;
|
private final PostHogService postHogService;
|
||||||
|
|
||||||
@PostMapping(value = "/handleData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
@AutoJobPostMapping(value = "/handleData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||||
public ResponseEntity<byte[]> handleData(@ModelAttribute HandleDataRequest request)
|
public ResponseEntity<byte[]> handleData(@ModelAttribute HandleDataRequest request)
|
||||||
throws JsonMappingException, JsonProcessingException {
|
throws JsonMappingException, JsonProcessingException {
|
||||||
MultipartFile[] files = request.getFileInput();
|
MultipartFile[] files = request.getFileInput();
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.security;
|
package stirling.software.SPDF.controller.api.security;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.beans.PropertyEditorSupport;
|
import java.beans.PropertyEditorSupport;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@ -138,7 +140,7 @@ public class CertSignController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(
|
@AutoJobPostMapping(
|
||||||
consumes = {
|
consumes = {
|
||||||
MediaType.MULTIPART_FORM_DATA_VALUE,
|
MediaType.MULTIPART_FORM_DATA_VALUE,
|
||||||
MediaType.APPLICATION_FORM_URLENCODED_VALUE
|
MediaType.APPLICATION_FORM_URLENCODED_VALUE
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.security;
|
package stirling.software.SPDF.controller.api.security;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@ -188,7 +190,7 @@ public class GetInfoOnPDF {
|
|||||||
return false;
|
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")
|
@Operation(summary = "Summary here", description = "desc. Input:PDF Output:JSON Type:SISO")
|
||||||
public ResponseEntity<byte[]> getPdfInfo(@ModelAttribute PDFFile request) throws IOException {
|
public ResponseEntity<byte[]> getPdfInfo(@ModelAttribute PDFFile request) throws IOException {
|
||||||
MultipartFile inputFile = request.getFileInput();
|
MultipartFile inputFile = request.getFileInput();
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.security;
|
package stirling.software.SPDF.controller.api.security;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
@ -32,7 +34,7 @@ public class PasswordController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-password")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-password")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Remove password from a PDF file",
|
summary = "Remove password from a PDF file",
|
||||||
description =
|
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(
|
@Operation(
|
||||||
summary = "Add password to a PDF file",
|
summary = "Add password to a PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.security;
|
package stirling.software.SPDF.controller.api.security;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -56,7 +58,7 @@ public class RedactController {
|
|||||||
List.class, "redactions", new StringToArrayListPropertyEditor());
|
List.class, "redactions", new StringToArrayListPropertyEditor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/redact", consumes = "multipart/form-data")
|
@AutoJobPostMapping(value = "/redact", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Redacts areas and pages in a PDF document",
|
summary = "Redacts areas and pages in a PDF document",
|
||||||
description =
|
description =
|
||||||
@ -190,7 +192,7 @@ public class RedactController {
|
|||||||
return pageNumbers;
|
return pageNumbers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/auto-redact", consumes = "multipart/form-data")
|
@AutoJobPostMapping(value = "/auto-redact", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Redacts listOfText in a PDF document",
|
summary = "Redacts listOfText in a PDF document",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.security;
|
package stirling.software.SPDF.controller.api.security;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
@ -32,7 +34,7 @@ public class RemoveCertSignController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-cert-sign")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-cert-sign")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Remove digital signature from PDF",
|
summary = "Remove digital signature from PDF",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.security;
|
package stirling.software.SPDF.controller.api.security;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.pdfbox.cos.COSDictionary;
|
import org.apache.pdfbox.cos.COSDictionary;
|
||||||
@ -46,7 +48,7 @@ public class SanitizeController {
|
|||||||
|
|
||||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/sanitize-pdf")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/sanitize-pdf")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Sanitize a PDF file",
|
summary = "Sanitize a PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.security;
|
package stirling.software.SPDF.controller.api.security;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.beans.PropertyEditorSupport;
|
import java.beans.PropertyEditorSupport;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -69,7 +71,7 @@ public class ValidateSignatureController {
|
|||||||
description =
|
description =
|
||||||
"Validates the digital signatures in a PDF file against default or custom"
|
"Validates the digital signatures in a PDF file against default or custom"
|
||||||
+ " certificates. Input:PDF Output:JSON Type:SISO")
|
+ " 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<List<SignatureValidationResult>> validateSignature(
|
public ResponseEntity<List<SignatureValidationResult>> validateSignature(
|
||||||
@ModelAttribute SignatureValidationRequest request) throws IOException {
|
@ModelAttribute SignatureValidationRequest request) throws IOException {
|
||||||
List<SignatureValidationResult> results = new ArrayList<>();
|
List<SignatureValidationResult> results = new ArrayList<>();
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.security;
|
package stirling.software.SPDF.controller.api.security;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.beans.PropertyEditorSupport;
|
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(
|
@Operation(
|
||||||
summary = "Add watermark to a PDF file",
|
summary = "Add watermark to a PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.model.api.converters;
|
package stirling.software.SPDF.model.api.converters;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@ -18,7 +20,7 @@ import stirling.software.common.util.PDFToFile;
|
|||||||
@RequestMapping("/api/v1/convert")
|
@RequestMapping("/api/v1/convert")
|
||||||
public class ConvertPDFToMarkdown {
|
public class ConvertPDFToMarkdown {
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/markdown")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/markdown")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Convert PDF to Markdown",
|
summary = "Convert PDF to Markdown",
|
||||||
description =
|
description =
|
||||||
|
@ -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<AuditDashboardData> 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<LoginData> getLoginData() {
|
||||||
|
LoginData data = new LoginData();
|
||||||
|
Map<String, String> 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<AdminSettingsData> getAdminSettingsData(Authentication authentication) {
|
||||||
|
List<User> allUsers = userRepository.findAllWithTeam();
|
||||||
|
Iterator<User> iterator = allUsers.iterator();
|
||||||
|
Map<String, String> roleDetails = Role.getAllRoleDetails();
|
||||||
|
|
||||||
|
Map<String, Boolean> userSessions = new HashMap<>();
|
||||||
|
Map<String, Date> 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<SessionEntity> 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<User> 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<Team> 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<AccountData> 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> 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<TeamsData> getTeamsData() {
|
||||||
|
List<TeamWithUserCountDTO> allTeamsWithCounts = teamRepository.findAllTeamsWithUserCount();
|
||||||
|
List<TeamWithUserCountDTO> teamsWithCounts =
|
||||||
|
allTeamsWithCounts.stream()
|
||||||
|
.filter(team -> !team.getName().equals(TeamService.INTERNAL_TEAM_NAME))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
List<Object[]> teamActivities = sessionRepository.findLatestActivityByTeam();
|
||||||
|
Map<Long, Date> 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<TeamDetailsData> 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<User> teamUsers = userRepository.findAllByTeamId(id);
|
||||||
|
List<User> allUsers = userRepository.findAllWithTeam();
|
||||||
|
List<User> 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<Object[]> userSessions = sessionRepository.findLatestSessionByTeamId(id);
|
||||||
|
Map<String, Date> 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<DatabaseData> getDatabaseData() {
|
||||||
|
List<FileInfo> 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<String, String> providerList;
|
||||||
|
private String loginMethod;
|
||||||
|
private boolean altLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class AdminSettingsData {
|
||||||
|
private List<User> users;
|
||||||
|
private String currentUsername;
|
||||||
|
private Map<String, String> roleDetails;
|
||||||
|
private Map<String, Boolean> userSessions;
|
||||||
|
private Map<String, Date> userLastRequest;
|
||||||
|
private int totalUsers;
|
||||||
|
private int activeUsers;
|
||||||
|
private int disabledUsers;
|
||||||
|
private List<Team> 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<TeamWithUserCountDTO> teamsWithCounts;
|
||||||
|
private Map<Long, Date> teamLastRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class TeamDetailsData {
|
||||||
|
private Team team;
|
||||||
|
private List<User> teamUsers;
|
||||||
|
private List<User> availableUsers;
|
||||||
|
private Map<String, Date> userLastRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class DatabaseData {
|
||||||
|
private List<FileInfo> backupFiles;
|
||||||
|
private String databaseVersion;
|
||||||
|
private boolean versionUnknown;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.proprietary.security.controller.api;
|
package stirling.software.proprietary.security.controller.api;
|
||||||
|
|
||||||
|
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
@ -42,7 +44,7 @@ public class EmailController {
|
|||||||
* attachment.
|
* attachment.
|
||||||
* @return ResponseEntity with success or error message.
|
* @return ResponseEntity with success or error message.
|
||||||
*/
|
*/
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/send-email")
|
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/send-email")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Send an email with an attachment",
|
summary = "Send an email with an attachment",
|
||||||
description =
|
description =
|
||||||
|
@ -26,8 +26,6 @@ services:
|
|||||||
DISABLE_ADDITIONAL_FEATURES: "false"
|
DISABLE_ADDITIONAL_FEATURES: "false"
|
||||||
SECURITY_ENABLELOGIN: "false"
|
SECURITY_ENABLELOGIN: "false"
|
||||||
FAT_DOCKER: "true"
|
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
|
SYSTEM_DEFAULTLOCALE: en-US
|
||||||
UI_APPNAME: Stirling-PDF
|
UI_APPNAME: Stirling-PDF
|
||||||
UI_HOMEDESCRIPTION: Full-featured Stirling-PDF with all capabilities
|
UI_HOMEDESCRIPTION: Full-featured Stirling-PDF with all capabilities
|
||||||
|
@ -25,7 +25,6 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
DISABLE_ADDITIONAL_FEATURES: "true"
|
DISABLE_ADDITIONAL_FEATURES: "true"
|
||||||
SECURITY_ENABLELOGIN: "false"
|
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
|
SYSTEM_DEFAULTLOCALE: en-US
|
||||||
UI_APPNAME: Stirling-PDF
|
UI_APPNAME: Stirling-PDF
|
||||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest
|
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest
|
||||||
|
@ -52,6 +52,44 @@ http {
|
|||||||
proxy_request_buffering off;
|
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
|
# Cache static assets
|
||||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
expires 1y;
|
expires 1y;
|
||||||
|
@ -579,6 +579,10 @@
|
|||||||
"title": "Validate PDF Signature",
|
"title": "Validate PDF Signature",
|
||||||
"desc": "Verify digital signatures and certificates in PDF documents"
|
"desc": "Verify digital signatures and certificates in PDF documents"
|
||||||
},
|
},
|
||||||
|
"swagger": {
|
||||||
|
"title": "API Documentation",
|
||||||
|
"desc": "View API documentation and test endpoints"
|
||||||
|
},
|
||||||
"replaceColorPdf": {
|
"replaceColorPdf": {
|
||||||
"title": "Advanced Colour options",
|
"title": "Advanced Colour options",
|
||||||
"desc": "Replace colour for text and background in PDF and invert full colour of pdf to reduce file size"
|
"desc": "Replace colour for text and background in PDF and invert full colour of pdf to reduce file size"
|
||||||
@ -1563,6 +1567,12 @@
|
|||||||
},
|
},
|
||||||
"note": "Release notes are only available in English"
|
"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": {
|
"cookieBanner": {
|
||||||
"popUp": {
|
"popUp": {
|
||||||
"title": "How we use Cookies",
|
"title": "How we use Cookies",
|
||||||
|
@ -575,6 +575,10 @@
|
|||||||
"title": "Validate PDF Signature",
|
"title": "Validate PDF Signature",
|
||||||
"desc": "Verify digital signatures and certificates in PDF documents"
|
"desc": "Verify digital signatures and certificates in PDF documents"
|
||||||
},
|
},
|
||||||
|
"swagger": {
|
||||||
|
"title": "API Documentation",
|
||||||
|
"desc": "View API documentation and test endpoints"
|
||||||
|
},
|
||||||
"replaceColorPdf": {
|
"replaceColorPdf": {
|
||||||
"title": "Replace and Invert Color",
|
"title": "Replace and Invert Color",
|
||||||
"desc": "Replace color for text and background in PDF and invert full color of pdf to reduce file size"
|
"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"
|
"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": {
|
"cookieBanner": {
|
||||||
"popUp": {
|
"popUp": {
|
||||||
"title": "How we use Cookies",
|
"title": "How we use Cookies",
|
||||||
|
@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import ContentCutIcon from "@mui/icons-material/ContentCut";
|
import ContentCutIcon from "@mui/icons-material/ContentCut";
|
||||||
import ZoomInMapIcon from "@mui/icons-material/ZoomInMap";
|
import ZoomInMapIcon from "@mui/icons-material/ZoomInMap";
|
||||||
import SwapHorizIcon from "@mui/icons-material/SwapHoriz";
|
import SwapHorizIcon from "@mui/icons-material/SwapHoriz";
|
||||||
|
import ApiIcon from "@mui/icons-material/Api";
|
||||||
import { useMultipleEndpointsEnabled } from "./useEndpointConfig";
|
import { useMultipleEndpointsEnabled } from "./useEndpointConfig";
|
||||||
import { Tool, ToolDefinition, BaseToolProps, ToolRegistry } from "../types/tool";
|
import { Tool, ToolDefinition, BaseToolProps, ToolRegistry } from "../types/tool";
|
||||||
|
|
||||||
@ -36,6 +37,15 @@ const toolDefinitions: Record<string, ToolDefinition> = {
|
|||||||
description: "Change to and from PDF and other formats",
|
description: "Change to and from PDF and other formats",
|
||||||
endpoints: ["pdf-to-img", "img-to-pdf", "pdf-to-word", "pdf-to-presentation", "pdf-to-text", "pdf-to-html", "pdf-to-xml", "html-to-pdf", "markdown-to-pdf", "file-to-pdf"]
|
endpoints: ["pdf-to-img", "img-to-pdf", "pdf-to-word", "pdf-to-presentation", "pdf-to-text", "pdf-to-html", "pdf-to-xml", "html-to-pdf", "markdown-to-pdf", "file-to-pdf"]
|
||||||
},
|
},
|
||||||
|
swagger: {
|
||||||
|
id: "swagger",
|
||||||
|
icon: <ApiIcon />,
|
||||||
|
component: React.lazy(() => import("../tools/SwaggerUI")),
|
||||||
|
maxFiles: 0,
|
||||||
|
category: "utility",
|
||||||
|
description: "Open API documentation",
|
||||||
|
endpoints: ["swagger-ui"]
|
||||||
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
18
frontend/src/tools/SwaggerUI.tsx
Normal file
18
frontend/src/tools/SwaggerUI.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { BaseToolProps } from '../types/tool';
|
||||||
|
|
||||||
|
const SwaggerUI: React.FC<BaseToolProps> = () => {
|
||||||
|
useEffect(() => {
|
||||||
|
// Redirect to Swagger UI
|
||||||
|
window.open('/swagger-ui/5.21.0/index.html', '_blank');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ textAlign: 'center', padding: '2rem' }}>
|
||||||
|
<p>Opening Swagger UI in a new tab...</p>
|
||||||
|
<p>If it didn't open automatically, <a href="/swagger-ui/5.21.0/index.html" target="_blank" rel="noopener noreferrer">click here</a></p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SwaggerUI;
|
@ -25,7 +25,7 @@ Feature: API Validation
|
|||||||
| password | wrongPassword |
|
| password | wrongPassword |
|
||||||
When I send the API request to the endpoint "/api/v1/security/remove-password"
|
When I send the API request to the endpoint "/api/v1/security/remove-password"
|
||||||
Then the response status code should be 500
|
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
|
@positive @info
|
||||||
Scenario: Get info
|
Scenario: Get info
|
||||||
|
Loading…
x
Reference in New Issue
Block a user