diff --git a/app/common/src/main/java/stirling/software/common/annotations/AutoJobPostMapping.java b/app/common/src/main/java/stirling/software/common/annotations/AutoJobPostMapping.java index 8fb729560..48ea489d6 100644 --- a/app/common/src/main/java/stirling/software/common/annotations/AutoJobPostMapping.java +++ b/app/common/src/main/java/stirling/software/common/annotations/AutoJobPostMapping.java @@ -6,6 +6,8 @@ import org.springframework.core.annotation.AliasFor; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import io.swagger.v3.oas.annotations.parameters.RequestBody; + /** * Shortcut for a POST endpoint that is executed through the Stirling "auto‑job" framework. * @@ -29,6 +31,7 @@ import org.springframework.web.bind.annotation.RequestMethod; @Retention(RetentionPolicy.RUNTIME) @Documented @RequestMapping(method = RequestMethod.POST) +@RequestBody(required = true) public @interface AutoJobPostMapping { /** Alias for {@link RequestMapping#value} – the path mapping of the endpoint. */ diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/AccountSecurityApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/AccountSecurityApi.java new file mode 100644 index 000000000..34680febf --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/AccountSecurityApi.java @@ -0,0 +1,48 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Account Security API controllers. + * Includes @RestController, @RequestMapping("/api/v1/account"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/account") +@Tag( + name = "Account Security", + description = + """ + Account security and protection services for user safety and organizational compliance. + + This endpoint group provides account security capabilities for organizations requiring + enhanced protection against unauthorized access, security threats, and compliance violations. + + Common use cases: + • Corporate security policy compliance and SOX, HIPAA, GDPR requirements + • Fraud prevention, identity theft protection, and account compromise recovery + • Multi-factor authentication implementation and insider threat mitigation + • Account recovery and emergency access procedures + + Business applications: + • Enterprise risk management, security governance, and customer trust protection + • Legal liability reduction and insurance requirement fulfillment + • Audit preparation, compliance reporting, and business continuity management + + Operational scenarios: + • Security incident response, forensic investigation, and user training + • Emergency account lockdown, suspicious activity monitoring, and compliance documentation + + Target users: Security administrators, compliance officers, and organizations + prioritizing account security and regulatory compliance. + """) +public @interface AccountSecurityApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/AdminApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/AdminApi.java new file mode 100644 index 000000000..3469d1a20 --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/AdminApi.java @@ -0,0 +1,48 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Admin Settings API controllers. + * Includes @RestController, @RequestMapping("/api/v1/admin/settings"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/admin/settings") +@Tag( + name = "Admin Settings", + description = + """ + System administration and configuration management for enterprise deployments. + + This endpoint group provides administrative control for organizations deploying + Stirling PDF in production environments with multi-user scenarios. + + Common use cases: + • Enterprise deployment configuration and multi-tenant environment management + • Security policy enforcement, compliance monitoring, and capacity planning + • Operational maintenance, troubleshooting, and enterprise infrastructure integration + • Disaster recovery and business continuity preparation + + Business applications: + • Corporate IT governance, policy enforcement, and compliance reporting + • Cost optimization, SLA monitoring, and vendor management oversight + • Risk management and security incident response + + Operational scenarios: + • 24/7 production monitoring, scheduled maintenance, and system updates + • Emergency response, change management, and performance optimization + + Target users: IT administrators, system engineers, and operations teams + responsible for enterprise-grade document processing infrastructure. + """) +public @interface AdminApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/AdminServerCertificateApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/AdminServerCertificateApi.java new file mode 100644 index 000000000..34bbe5f42 --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/AdminServerCertificateApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Admin Server Certificate API controllers. + * Includes @RestController, @RequestMapping("/api/v1/admin/server-certificate"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/admin/server-certificate") +@Tag( + name = "Admin - Server Certificate", + description = + """ + Server certificate management for secure enterprise deployments and encrypted communications. + + This endpoint group provides certificate lifecycle management for organizations + requiring secure communications in document processing infrastructure. + + Common use cases: + • Corporate security compliance and encrypted communications for healthcare/finance + • Customer data protection, internal audits, and multi-environment standardization + • Third-party security assessments and disaster recovery security measures + + Business applications: + • Enterprise security governance, client trust protection, and secure B2B exchange + • Legal requirement fulfillment, liability reduction, and M&A security preparation + + Operational scenarios: + • Certificate renewal, emergency replacement, and security incident response + • Multi-site deployment coordination and cloud migration preparation + + Target users: Security administrators, compliance officers, and IT infrastructure + teams requiring enterprise-grade security for document processing systems. + """) +public @interface AdminServerCertificateApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/AnalysisApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/AnalysisApi.java new file mode 100644 index 000000000..31de4c8d2 --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/AnalysisApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Analysis API controllers. + * Includes @RestController, @RequestMapping("/api/v1/analysis"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/analysis") +@Tag( + name = "Analysis", + description = + """ + Document analysis and information extraction services for content intelligence and insights. + + This endpoint group provides analytical capabilities to understand document structure, + extract information, and generate insights from PDF content for automated processing. + + Common use cases: + • Document inventory management and content audit for compliance verification + • Quality assurance workflows and business intelligence analytics + • Migration planning, accessibility evaluation, and document forensics + + Business applications: + • Legal discovery, financial document review, and healthcare records analysis + • Academic research, government processing, and publishing optimization + + Operational scenarios: + • Large-scale profiling, migration assessment, and performance optimization + • Automated quality control and content strategy development + + Target users: Data analysts, QA teams, administrators, and business intelligence + professionals requiring detailed document insights. + """) +public @interface AnalysisApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/ConfigApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/ConfigApi.java new file mode 100644 index 000000000..85175adc4 --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/ConfigApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Configuration API controllers. + * Includes @RestController, @RequestMapping("/api/v1/config"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/config") +@Tag( + name = "Config", + description = + """ + System configuration management for deployment optimization and operational control. + + This endpoint group provides system configuration capabilities for organizations + deploying and operating Stirling PDF in various environments. + + Common use cases: + • Environment-specific deployment and performance tuning for varying workloads + • Resource optimization, cost management, and infrastructure integration + • Compliance configuration, disaster recovery, and multi-environment standardization + + Business applications: + • Operational cost optimization, SLA compliance, and risk management + • Vendor integration, change management, and capacity planning + + Operational scenarios: + • System deployment, performance troubleshooting, and emergency changes + • Planned maintenance and multi-site deployment coordination + + Target users: System administrators, DevOps engineers, and IT operations teams + responsible for deployment configuration and system optimization. + """) +public @interface ConfigApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/ConvertApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/ConvertApi.java new file mode 100644 index 000000000..9d9d85bd7 --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/ConvertApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Convert API controllers. + * Includes @RestController, @RequestMapping("/api/v1/convert"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/convert") +@Tag( + name = "Convert", + description = + """ + Document format transformation services for cross-platform compatibility and workflow integration. + + This endpoint group enables transformation between various formats, supporting + diverse business workflows and system integrations for mixed document ecosystems. + + Common use cases: + • Legacy system integration, document migration, and cross-platform sharing + • Archive standardization, publishing preparation, and content adaptation + • Accessibility compliance and mobile-friendly document preparation + + Business applications: + • Enterprise content management, digital publishing, and educational platforms + • Legal document processing, healthcare interoperability, and government standardization + + Integration scenarios: + • API-driven pipelines, automated workflow preparation, and batch conversions + • Real-time format adaptation for user requests + + Target users: System integrators, content managers, digital archivists, and + organizations requiring flexible document format interoperability. + """) +public @interface ConvertApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/DatabaseApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/DatabaseApi.java new file mode 100644 index 000000000..23c1ff41f --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/DatabaseApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Database Management API controllers. + * Includes @RestController, @RequestMapping("/api/v1/database"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/database") +@Tag( + name = "Database", + description = + """ + Database operations for data protection and business continuity management. + + This endpoint group provides essential database operations for organizations requiring + reliable data protection and recovery capabilities. + + Common use cases: + • Regular data backup, disaster recovery, and business continuity planning + • System migration, compliance management, and development environment support + • Operational troubleshooting and scheduled maintenance operations + + Business applications: + • Risk management, regulatory compliance, and operational resilience + • Data governance, change management, and quality assurance support + + Operational scenarios: + • Routine backup, emergency recovery, and system maintenance preparation + • Data migration projects and performance monitoring + + Target users: Operations teams, system administrators, and organizations requiring + reliable data protection and operational database management. + """) +public @interface DatabaseApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/DatabaseManagementApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/DatabaseManagementApi.java new file mode 100644 index 000000000..7da55c3bc --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/DatabaseManagementApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Database Management API controllers. + * Includes @RestController, @RequestMapping("/api/v1/admin/database"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/admin/database") +@Tag( + name = "Database Management", + description = + """ + Enterprise database administration for production data management and business continuity. + + This endpoint group provides database administration capabilities for organizations + operating Stirling PDF in production environments. + + Common use cases: + • Business continuity, disaster recovery, and regulatory compliance requirements + • Performance optimization, data security, and system migration projects + • Audit preparation, compliance reporting, and cost optimization + + Business applications: + • Enterprise risk management, regulatory compliance, and SLA monitoring + • Data retention policies, security incident response, and vendor oversight + + Operational scenarios: + • Scheduled maintenance, emergency recovery, and capacity planning + • Performance troubleshooting and multi-environment deployment coordination + + Target users: Database administrators, IT operations teams, and enterprise + administrators responsible for production data management and system reliability. + """) +public @interface DatabaseManagementApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/FilterApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/FilterApi.java new file mode 100644 index 000000000..2c925609e --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/FilterApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Filter API controllers. + * Includes @RestController, @RequestMapping("/api/v1/filter"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/filter") +@Tag( + name = "Filter", + description = + """ + Document content filtering and search operations for information discovery and organization. + + This endpoint group enables intelligent content discovery and organization within + document collections for content-based processing and information extraction. + + Common use cases: + • Legal discovery, research organization, and compliance auditing + • Content moderation, academic research, and business intelligence + • Quality assurance and content validation workflows + + Business applications: + • Contract analysis, financial review, and healthcare records organization + • Government processing, educational curation, and IP protection + + Workflow scenarios: + • Large-scale processing, automated classification, and information extraction + • Document preparation for further processing or analysis + + Target users: Legal professionals, researchers, compliance officers, and + organizations requiring intelligent document content discovery and organization. + """) +public @interface FilterApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/GeneralApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/GeneralApi.java new file mode 100644 index 000000000..535f47773 --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/GeneralApi.java @@ -0,0 +1,42 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for General PDF processing API controllers. + * Includes @RestController, @RequestMapping("/api/v1/general"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/general") +@Tag( + name = "General", + description = + """ + Core PDF processing operations for fundamental document manipulation workflows. + + This endpoint group provides essential PDF functionality that forms the foundation + of most document processing workflows across various industries. + + Common use cases: + • Document preparation for archival systems and content organization + • File preparation for distribution, accessibility compliance, and batch processing + • Document consolidation for reporting and legal compliance workflows + + Typical applications: + • Content management, publishing workflows, and educational content distribution + • Business process automation and archive management + + Target users: Content managers, document processors, and organizations requiring + reliable foundational PDF manipulation capabilities. + """) +public @interface GeneralApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/InfoApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/InfoApi.java new file mode 100644 index 000000000..9fb5022ce --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/InfoApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Info API controllers. + * Includes @RestController, @RequestMapping("/api/v1/info"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/info") +@Tag( + name = "Info", + description = + """ + System information and operational insights for monitoring and performance management. + + This endpoint group provides system information and operational metrics for organizations + operating Stirling PDF in production environments. + + Common use cases: + • System health monitoring, performance optimization, and capacity planning + • Troubleshooting, compliance monitoring, and SLA reporting + • Cost optimization, usage analysis, and security monitoring + + Business applications: + • Operational cost management, business continuity monitoring, and vendor management + • Compliance reporting, strategic planning, and customer service tracking + + Operational scenarios: + • 24/7 monitoring, scheduled maintenance, and emergency response coordination + • System upgrade planning and capacity scaling decisions + + Target users: Operations teams, system administrators, and management teams requiring + operational insights and system performance visibility. + """) +public @interface InfoApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/MiscApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/MiscApi.java new file mode 100644 index 000000000..ee9cf62bf --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/MiscApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Miscellaneous API controllers. + * Includes @RestController, @RequestMapping("/api/v1/misc"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/misc") +@Tag( + name = "Misc", + description = + """ + Specialized utilities and supplementary tools for enhanced document processing workflows. + + This endpoint group provides utility operations that support core document processing + tasks and address specific workflow needs in real-world scenarios. + + Common use cases: + • Document optimization for bandwidth-limited environments and storage cost management + • Document repair, content extraction, and validation for quality assurance + • Accessibility improvement and custom processing for specialized needs + + Business applications: + • Web publishing optimization, email attachment management, and archive efficiency + • Mobile compatibility, print production, and legacy document recovery + + Operational scenarios: + • Batch processing, quality control, and performance optimization + • Troubleshooting and recovery of problematic documents + + Target users: System administrators, document specialists, and organizations requiring + specialized document processing and optimization tools. + """) +public @interface MiscApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/PipelineApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/PipelineApi.java new file mode 100644 index 000000000..38407b6a0 --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/PipelineApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Pipeline API controllers. + * Includes @RestController, @RequestMapping("/api/v1/pipeline"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/pipeline") +@Tag( + name = "Pipeline", + description = + """ + Automated document processing workflows for complex multi-stage business operations. + + This endpoint group enables organizations to create sophisticated document processing + workflows that combine multiple operations into streamlined, repeatable processes. + + Common use cases: + • Invoice processing, legal document review, and healthcare records standardization + • Government processing, educational content preparation, and publishing automation + • Contract lifecycle management and approval processes + + Business applications: + • Automated compliance reporting, large-scale migration, and quality assurance + • Archive preparation, content delivery, and document approval workflows + + Operational scenarios: + • Scheduled batch processing and event-driven document processing + • Multi-department coordination and business system integration + + Target users: Business process managers, IT automation specialists, and organizations + requiring consistent, repeatable document processing workflows. + """) +public @interface PipelineApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/ProprietaryUiDataApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/ProprietaryUiDataApi.java new file mode 100644 index 000000000..06f03ccd4 --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/ProprietaryUiDataApi.java @@ -0,0 +1,47 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Proprietary UI Data API controllers. + * Includes @RestController, @RequestMapping("/api/v1/proprietary/ui-data"), and OpenAPI @Tag. Note: + * Controllers using this annotation should also add @EnterpriseEndpoint. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/proprietary/ui-data") +@Tag( + name = "Proprietary UI Data", + description = + """ + Enterprise user interface data services for commercial deployments and advanced business features. + + This endpoint group provides enhanced data services for commercial and enterprise features, + supporting advanced business workflows and professional-grade functionality. + + Common use cases: + • Enterprise-grade dashboards, multi-tenant deployment, and business intelligence + • Organizational hierarchy management and commercial feature licensing + • Professional support integration and advanced workflow automation + + Business applications: + • ERP integration, CRM development, and executive reporting dashboards + • Multi-subsidiary management, professional service delivery, and compliance interfaces + + Operational scenarios: + • Large-scale deployment management and white-label solution development + • Advanced system integration and commercial feature rollout + + Target users: Enterprise administrators, business analysts, and organizations utilizing + commercial features and advanced business capabilities. + """) +public @interface ProprietaryUiDataApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/SecurityApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/SecurityApi.java new file mode 100644 index 000000000..fe9756d3f --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/SecurityApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Security API controllers. + * Includes @RestController, @RequestMapping("/api/v1/security"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/security") +@Tag( + name = "Security", + description = + """ + Document security and protection services for confidential and sensitive content. + + This endpoint group provides essential security operations for organizations handling + sensitive documents and materials requiring controlled access. + + Common use cases: + • Legal confidentiality, healthcare privacy (HIPAA), and financial regulatory compliance + • Government classified handling, corporate IP protection, and educational privacy (FERPA) + • Contract security for business transactions + + Business applications: + • Document authentication, confidential sharing, and secure archiving + • Content watermarking, access control, and privacy protection through redaction + + Industry scenarios: + • Legal discovery, medical records exchange, financial audit documentation + • Enterprise policy enforcement and data governance + + Target users: Legal professionals, healthcare administrators, compliance officers, + government agencies, and enterprises handling sensitive content. + """) +public @interface SecurityApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/SettingsApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/SettingsApi.java new file mode 100644 index 000000000..614419aaa --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/SettingsApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Settings API controllers. + * Includes @RestController, @RequestMapping("/api/v1/settings"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/settings") +@Tag( + name = "Settings", + description = + """ + User preferences and application customization for personalized workflow optimization. + + This endpoint group provides preference management capabilities for users and + organizations to customize their document processing experience. + + Common use cases: + • Workflow optimization, accessibility compliance, and corporate branding + • Multi-language support, user personalization, and business system integration + • Organizational policy compliance + + Business applications: + • Corporate branding, productivity optimization, and accessibility compliance + • Change management facilitation and training efficiency improvement + + Operational scenarios: + • User onboarding, department-specific customization, and system migration + • Multi-tenant customization and project-based configuration adjustments + + Target users: End users, department managers, and organizations focused on optimizing + user experience and workflow efficiency through personalization. + """) +public @interface SettingsApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/TeamApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/TeamApi.java new file mode 100644 index 000000000..07e87a70e --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/TeamApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for Team Management API controllers. + * Includes @RestController, @RequestMapping("/api/v1/team"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/team") +@Tag( + name = "Team", + description = + """ + Team management and collaboration services for organized document processing workflows. + + This endpoint group enables organizations to structure collaborative document processing + activities through team-based organization and resource management. + + Common use cases: + • Department-based processing, project collaboration, and cross-functional coordination + • Client-specific team isolation, temporary project teams, and training coordination + • Compliance team coordination for regulatory processing + + Business applications: + • Matrix organization support, client service delivery, and cost center allocation + • Scalable collaboration, knowledge management, and team-based quality assurance + + Operational scenarios: + • Large-scale processing coordination and temporary team formation + • M&A integration, remote collaboration, and knowledge transfer management + + Target users: Team leaders, project managers, and organizations requiring structured + collaborative environments for document processing activities. + """) +public @interface TeamApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/UiDataApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/UiDataApi.java new file mode 100644 index 000000000..920946aed --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/UiDataApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for UI Data API controllers. + * Includes @RestController, @RequestMapping("/api/v1/ui-data"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/ui-data") +@Tag( + name = "UI Data", + description = + """ + User interface data services for dynamic frontend applications and user experience customization. + + This endpoint group provides data services for frontend applications to render personalized + interfaces and deliver optimized experiences based on system configuration. + + Common use cases: + • Dynamic UI customization, multi-language support, and feature configuration + • Real-time status delivery, corporate branding, and mobile optimization + • Progressive web application (PWA) configuration + + Business applications: + • Brand customization, user experience optimization, and accessibility compliance + • Multi-tenant customization, training support, and performance optimization + + Operational scenarios: + • Frontend deployment, UI A/B testing, and system integration + • Mobile synchronization and offline capability enhancement + + Target users: Frontend developers, UI/UX designers, and organizations requiring + customizable user interfaces and optimized user experiences. + """) +public @interface UiDataApi {} diff --git a/app/common/src/main/java/stirling/software/common/annotations/api/UserApi.java b/app/common/src/main/java/stirling/software/common/annotations/api/UserApi.java new file mode 100644 index 000000000..d1bf070b6 --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/annotations/api/UserApi.java @@ -0,0 +1,46 @@ +package stirling.software.common.annotations.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; + +/** + * Combined annotation for User Management API controllers. + * Includes @RestController, @RequestMapping("/api/v1/user"), and OpenAPI @Tag. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@RestController +@RequestMapping("/api/v1/user") +@Tag( + name = "User", + description = + """ + User management and authentication services for multi-user and enterprise environments. + + This endpoint group provides user lifecycle management capabilities for organizations + deploying Stirling PDF in multi-user scenarios. + + Common use cases: + • Employee onboarding/offboarding and corporate access control + • Department-based permissions, regulatory compliance, and SSO integration + • Multi-tenant deployment and guest user access management + + Business applications: + • Enterprise IAM integration, security governance, and cost allocation + • Compliance reporting, workflow management, and partner collaboration + + Operational scenarios: + • Large-scale provisioning, automated HR integration, and emergency access + • User migration and self-service profile maintenance + + Target users: IT administrators, HR departments, and organizations requiring + structured user management and enterprise identity integration. + """) +public @interface UserApi {} diff --git a/app/common/src/main/java/stirling/software/common/model/api/PDFFile.java b/app/common/src/main/java/stirling/software/common/model/api/PDFFile.java index cc564f81e..aa811da1e 100644 --- a/app/common/src/main/java/stirling/software/common/model/api/PDFFile.java +++ b/app/common/src/main/java/stirling/software/common/model/api/PDFFile.java @@ -4,6 +4,8 @@ import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.AssertTrue; + import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -11,15 +13,18 @@ import lombok.NoArgsConstructor; @Data @NoArgsConstructor @EqualsAndHashCode +@Schema(description = "PDF file input - either upload a file or provide a server-side file ID") public class PDFFile { - @Schema( - description = "The input PDF file", - contentMediaType = "application/pdf", - format = "binary") + @Schema(description = "The input PDF file", format = "binary") private MultipartFile fileInput; - @Schema( - description = "File ID for server-side files (can be used instead of fileInput)", - example = "a1b2c3d4-5678-90ab-cdef-ghijklmnopqr") + @Schema(description = "File ID for server-side files (can be used instead of fileInput if job was previously done on file in async mode)") private String fileId; + + @AssertTrue(message = "Either fileInput or fileId must be provided") + @Schema(hidden = true) + private boolean isValid() { + return (fileInput != null && (fileId == null || fileId.trim().isEmpty())) + || (fileId != null && !fileId.trim().isEmpty() && fileInput == null); + } } diff --git a/app/core/src/main/java/stirling/software/SPDF/config/GlobalErrorResponseCustomizer.java b/app/core/src/main/java/stirling/software/SPDF/config/GlobalErrorResponseCustomizer.java new file mode 100644 index 000000000..d0b02fc46 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/GlobalErrorResponseCustomizer.java @@ -0,0 +1,188 @@ +package stirling.software.SPDF.config; + +import org.springdoc.core.customizers.GlobalOpenApiCustomizer; +import org.springframework.stereotype.Component; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.media.Content; +import io.swagger.v3.oas.models.media.MediaType; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.responses.ApiResponse; + +/** + * Global OpenAPI customizer that adds standard error responses (400, 413, 422, 500) to all API + * operations under /api/v1/** paths. + */ +@Component +public class GlobalErrorResponseCustomizer implements GlobalOpenApiCustomizer { + + @Override + public void customise(OpenAPI openApi) { + if (openApi.getPaths() == null) { + return; + } + + openApi.getPaths() + .forEach( + (path, pathItem) -> { + if (path.startsWith("/api/v1/")) { + addErrorResponsesToPathItem(pathItem); + } + }); + } + + private void addErrorResponsesToPathItem(PathItem pathItem) { + if (pathItem.getPost() != null) { + addStandardErrorResponses(pathItem.getPost()); + } + if (pathItem.getPut() != null) { + addStandardErrorResponses(pathItem.getPut()); + } + if (pathItem.getPatch() != null) { + addStandardErrorResponses(pathItem.getPatch()); + } + if (pathItem.getDelete() != null) { + addStandardErrorResponses(pathItem.getDelete()); + } + if (pathItem.getGet() != null) { + addStandardErrorResponses(pathItem.getGet()); + } + } + + private void addStandardErrorResponses(Operation operation) { + if (operation.getResponses() == null) { + return; + } + + // Only add error responses if they don't already exist + if (!operation.getResponses().containsKey("400")) { + operation.getResponses().addApiResponse("400", create400Response()); + } + if (!operation.getResponses().containsKey("413")) { + operation.getResponses().addApiResponse("413", create413Response()); + } + if (!operation.getResponses().containsKey("422")) { + operation.getResponses().addApiResponse("422", create422Response()); + } + if (!operation.getResponses().containsKey("500")) { + operation.getResponses().addApiResponse("500", create500Response()); + } + } + + private ApiResponse create400Response() { + return new ApiResponse() + .description( + "Bad request - Invalid input parameters, unsupported format, or corrupted file") + .content( + new Content() + .addMediaType( + "application/json", + new MediaType() + .schema( + createErrorSchema( + 400, + "Invalid input parameters or corrupted file", + "/api/v1/example/endpoint")) + .example( + createErrorExample( + 400, + "Invalid input parameters or corrupted file", + "/api/v1/example/endpoint")))); + } + + private ApiResponse create413Response() { + return new ApiResponse() + .description("Payload too large - File exceeds maximum allowed size") + .content( + new Content() + .addMediaType( + "application/json", + new MediaType() + .schema( + createErrorSchema( + 413, + "File size exceeds maximum allowed limit", + "/api/v1/example/endpoint")) + .example( + createErrorExample( + 413, + "File size exceeds maximum allowed limit", + "/api/v1/example/endpoint")))); + } + + private ApiResponse create422Response() { + return new ApiResponse() + .description("Unprocessable entity - File is valid but cannot be processed") + .content( + new Content() + .addMediaType( + "application/json", + new MediaType() + .schema( + createErrorSchema( + 422, + "File is valid but cannot be processed", + "/api/v1/example/endpoint")) + .example( + createErrorExample( + 422, + "File is valid but cannot be processed", + "/api/v1/example/endpoint")))); + } + + private ApiResponse create500Response() { + return new ApiResponse() + .description("Internal server error - Unexpected error during processing") + .content( + new Content() + .addMediaType( + "application/json", + new MediaType() + .schema( + createErrorSchema( + 500, + "Unexpected error during processing", + "/api/v1/example/endpoint")) + .example( + createErrorExample( + 500, + "Unexpected error during processing", + "/api/v1/example/endpoint")))); + } + + private Schema createErrorSchema(int status, String message, String path) { + return new Schema<>() + .type("object") + .addProperty("status", new Schema<>().type("integer").example(status)) + .addProperty("error", new Schema<>().type("string").example(getErrorType(status))) + .addProperty("message", new Schema<>().type("string").example(message)) + .addProperty( + "timestamp", + new Schema<>() + .type("string") + .format("date-time") + .example("2024-01-15T10:30:00Z")) + .addProperty("path", new Schema<>().type("string").example(path)); + } + + private Object createErrorExample(int status, String message, String path) { + return java.util.Map.of( + "status", status, + "error", getErrorType(status), + "message", message, + "timestamp", "2024-01-15T10:30:00Z", + "path", path); + } + + private String getErrorType(int status) { + return switch (status) { + case 400 -> "Bad Request"; + case 413 -> "Payload Too Large"; + case 422 -> "Unprocessable Entity"; + case 500 -> "Internal Server Error"; + default -> "Error"; + }; + } +} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java b/app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java index c0a0b6b55..a25287c4d 100644 --- a/app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java @@ -1,5 +1,8 @@ package stirling.software.SPDF.config; +import java.util.List; + +import org.springdoc.core.customizers.OpenApiCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -8,6 +11,10 @@ import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; +import io.swagger.v3.oas.models.media.ComposedSchema; +import io.swagger.v3.oas.models.media.ObjectSchema; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.servers.Server; @@ -42,8 +49,7 @@ public class OpenApiConfig { new License() .name("MIT") .url( - "https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/LICENSE") - .identifier("MIT")) + "https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/LICENSE")) .termsOfService("https://www.stirlingpdf.com/terms") .contact( new Contact() @@ -52,7 +58,7 @@ public class OpenApiConfig { .email("contact@stirlingpdf.com")) .description(DEFAULT_DESCRIPTION); - OpenAPI openAPI = new OpenAPI().info(info); + OpenAPI openAPI = new OpenAPI().info(info).openapi("3.0.3"); // Add server configuration from environment variable String swaggerServerUrl = System.getenv("SWAGGER_SERVER_URL"); @@ -61,16 +67,83 @@ public class OpenApiConfig { openAPI.addServersItem(server); } + // Add ErrorResponse schema to components + Schema errorResponseSchema = + new Schema<>() + .type("object") + .addProperty( + "timestamp", + new Schema<>() + .type("string") + .format("date-time") + .description("Error timestamp")) + .addProperty( + "status", + new Schema<>().type("integer").description("HTTP status code")) + .addProperty( + "error", new Schema<>().type("string").description("Error type")) + .addProperty( + "message", + new Schema<>().type("string").description("Error message")) + .addProperty( + "path", new Schema<>().type("string").description("Request path")) + .description("Standard error response format"); + + Components components = new Components().addSchemas("ErrorResponse", errorResponseSchema); + if (!applicationProperties.getSecurity().getEnableLogin()) { - return openAPI.components(new Components()); + return openAPI.components(components); } else { SecurityScheme apiKeyScheme = new SecurityScheme() .type(SecurityScheme.Type.APIKEY) .in(SecurityScheme.In.HEADER) .name("X-API-KEY"); - return openAPI.components(new Components().addSecuritySchemes("apiKey", apiKeyScheme)) + components.addSecuritySchemes("apiKey", apiKeyScheme); + return openAPI.components(components) .addSecurityItem(new SecurityRequirement().addList("apiKey")); } } + + @Bean + OpenApiCustomizer pdfFileOneOfCustomizer() { + return openApi -> { + var components = openApi.getComponents(); + var schemas = components.getSchemas(); + + // Define the two shapes + var upload = + new ObjectSchema() + .name("PDFFileUpload") + .description("Upload a PDF file") + .addProperty("fileInput", new StringSchema().format("binary")) + .addRequiredItem("fileInput"); + + var ref = + new ObjectSchema() + .name("PDFFileRef") + .description("Reference a server-side file") + .addProperty( + "fileId", + new StringSchema() + .example("a1b2c3d4-5678-90ab-cdef-ghijklmnopqr")) + .addRequiredItem("fileId"); + + schemas.put("PDFFileUpload", upload); + schemas.put("PDFFileRef", ref); + + // Create the oneOf schema + var pdfFileOneOf = + new ComposedSchema() + .oneOf( + List.of( + new Schema<>() + .$ref("#/components/schemas/PDFFileUpload"), + new Schema<>().$ref("#/components/schemas/PDFFileRef"))) + .description("Either upload a file or provide a server-side file ID"); + + // Replace PDFFile schema + schemas.put("PDFFile", pdfFileOneOf); + }; + } } diff --git a/app/core/src/main/java/stirling/software/SPDF/config/SpringDocConfig.java b/app/core/src/main/java/stirling/software/SPDF/config/SpringDocConfig.java new file mode 100644 index 000000000..cdde38d48 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/SpringDocConfig.java @@ -0,0 +1,83 @@ +package stirling.software.SPDF.config; + +import org.springdoc.core.customizers.OpenApiCustomizer; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SpringDocConfig { + + @Bean + public GroupedOpenApi pdfProcessingApi( + @Qualifier("pdfFileOneOfCustomizer") OpenApiCustomizer pdfFileOneOfCustomizer) { + return GroupedOpenApi.builder() + .group("file-processing") + .displayName("File Processing") + .pathsToMatch("/api/v1/**") + .pathsToExclude( + "/api/v1/admin/**", + "/api/v1/user/**", + "/api/v1/settings/**", + "/api/v1/team/**", + "/api/v1/ui-data/**", + "/api/v1/proprietary/ui-data/**", + "/api/v1/info/**", + "/api/v1/general/job/**", + "/api/v1/general/files/**") + .addOpenApiCustomizer(pdfFileOneOfCustomizer) + .addOpenApiCustomizer( + openApi -> { + openApi.info( + openApi.getInfo() + .title("Stirling PDF - Processing API") + .description( + "API documentation for PDF processing operations including conversion, manipulation, security, and utilities.")); + }) + .build(); + } + + @Bean + public GroupedOpenApi adminApi() { + return GroupedOpenApi.builder() + .group("management") + .displayName("Management") + .pathsToMatch( + "/api/v1/admin/**", + "/api/v1/user/**", + "/api/v1/settings/**", + "/api/v1/team/**") + .addOpenApiCustomizer( + openApi -> { + openApi.info( + openApi.getInfo() + .title("Stirling PDF - Admin API") + .description( + "API documentation for administrative functions, user management, and system configuration.")); + }) + .build(); + } + + @Bean + public GroupedOpenApi systemApi() { + return GroupedOpenApi.builder() + .group("system") + .displayName("System & UI API") + .pathsToMatch( + "/api/v1/ui-data/**", + "/api/v1/proprietary/ui-data/**", + "/api/v1/info/**", + "/api/v1/general/job/**", + "/api/v1/general/files/**") + .addOpenApiCustomizer( + openApi -> { + openApi.info( + openApi.getInfo() + .title("Stirling PDF - System API") + .description( + "API documentation for system information, UI data, and utility endpoints.")); + }) + .build(); + } +} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/swagger/CsvConversionResponse.java b/app/core/src/main/java/stirling/software/SPDF/config/swagger/CsvConversionResponse.java new file mode 100644 index 000000000..042d09d8b --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/swagger/CsvConversionResponse.java @@ -0,0 +1,58 @@ +package stirling.software.SPDF.config.swagger; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +/** + * API response annotation for PDF to CSV conversions. Use for endpoints that convert PDF tables to + * CSV format. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "PDF tables extracted successfully to CSV format", + content = { + @Content( + mediaType = "text/csv", + schema = + @Schema( + type = "string", + format = "binary", + description = + "CSV file containing extracted table data")), + @Content( + mediaType = "application/zip", + schema = + @Schema( + type = "string", + format = "binary", + description = + "ZIP archive containing multiple CSV files when multiple tables are extracted")) + }), + @ApiResponse( + responseCode = "400", + description = "Invalid PDF file or no tables found for extraction", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "204", description = "No tables found in the PDF"), + @ApiResponse( + responseCode = "500", + description = "Internal server error during table extraction", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))) + }) +public @interface CsvConversionResponse {} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/swagger/ErrorResponse.java b/app/core/src/main/java/stirling/software/SPDF/config/swagger/ErrorResponse.java new file mode 100644 index 000000000..6d125535b --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/swagger/ErrorResponse.java @@ -0,0 +1,30 @@ +package stirling.software.SPDF.config.swagger; + +import io.swagger.v3.oas.annotations.media.Schema; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "Standard error response") +public class ErrorResponse { + + @Schema(description = "HTTP status code", example = "400") + private int status; + + @Schema( + description = "Error message describing what went wrong", + example = "Invalid PDF file or corrupted data") + private String message; + + @Schema(description = "Timestamp when the error occurred", example = "2024-01-15T10:30:00Z") + private String timestamp; + + @Schema( + description = "Request path where the error occurred", + example = "/api/v1/{endpoint-path}") + private String path; +} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/swagger/FilterResponse.java b/app/core/src/main/java/stirling/software/SPDF/config/swagger/FilterResponse.java new file mode 100644 index 000000000..72834a8e4 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/swagger/FilterResponse.java @@ -0,0 +1,67 @@ +package stirling.software.SPDF.config.swagger; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +/** + * API response annotation for filter operations that conditionally return the original file. Use + * for operations like text filters, page count filters, size filters, etc. Returns the original PDF + * if condition is met, otherwise returns no content (204). + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "Filter condition met - returns the original PDF file", + content = + @Content( + mediaType = "application/pdf", + schema = + @Schema( + type = "string", + format = "binary", + description = "The original PDF file"))), + @ApiResponse( + responseCode = "204", + description = "Filter condition not met - no content returned", + content = @Content()), + @ApiResponse( + responseCode = "400", + description = "Bad request - Invalid filter parameters or corrupted PDF", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "413", + description = "Payload too large - File exceeds maximum allowed size", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "422", + description = + "Unprocessable entity - PDF is valid but cannot be analyzed for filtering", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "Internal server error - Unexpected error during PDF analysis", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))) + }) +public @interface FilterResponse {} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/swagger/HtmlConversionResponse.java b/app/core/src/main/java/stirling/software/SPDF/config/swagger/HtmlConversionResponse.java new file mode 100644 index 000000000..69b43aa81 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/swagger/HtmlConversionResponse.java @@ -0,0 +1,33 @@ +package stirling.software.SPDF.config.swagger; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +/** + * API response annotation for PDF to HTML conversions. Use for endpoints that convert PDF to HTML + * format. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "PDF converted successfully to HTML format", + content = + @Content( + mediaType = "text/html", + schema = + @Schema( + type = "string", + format = "binary", + description = "HTML file converted from PDF"))) + }) +public @interface HtmlConversionResponse {} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/swagger/JavaScriptResponse.java b/app/core/src/main/java/stirling/software/SPDF/config/swagger/JavaScriptResponse.java new file mode 100644 index 000000000..cec6857c8 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/swagger/JavaScriptResponse.java @@ -0,0 +1,34 @@ +package stirling.software.SPDF.config.swagger; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +/** + * API response annotation for JavaScript extraction from PDFs. Use for endpoints that extract + * JavaScript code from PDF documents. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "JavaScript extracted successfully from PDF", + content = + @Content( + mediaType = "text/plain", + schema = + @Schema( + type = "string", + format = "binary", + description = + "JavaScript code extracted from PDF"))) + }) +public @interface JavaScriptResponse {} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/swagger/JsonDataResponse.java b/app/core/src/main/java/stirling/software/SPDF/config/swagger/JsonDataResponse.java new file mode 100644 index 000000000..0aa6d1fcf --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/swagger/JsonDataResponse.java @@ -0,0 +1,47 @@ +package stirling.software.SPDF.config.swagger; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +/** + * API response annotation for operations that return JSON data or analysis results. Use for + * analysis operations, metadata extraction, info operations, etc. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "Analysis or data extraction completed successfully", + content = + @Content( + mediaType = "application/json", + schema = + @Schema( + type = "object", + description = + "JSON object containing the requested data or analysis results"))), + @ApiResponse( + responseCode = "400", + description = "Invalid PDF file or request parameters", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "Internal server error during processing", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))) + }) +public @interface JsonDataResponse {} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/swagger/MarkdownConversionResponse.java b/app/core/src/main/java/stirling/software/SPDF/config/swagger/MarkdownConversionResponse.java new file mode 100644 index 000000000..744c7878a --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/swagger/MarkdownConversionResponse.java @@ -0,0 +1,34 @@ +package stirling.software.SPDF.config.swagger; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +/** + * API response annotation for PDF to Markdown conversions. Use for endpoints that convert PDF to + * Markdown format. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "PDF converted successfully to Markdown format", + content = + @Content( + mediaType = "text/markdown", + schema = + @Schema( + type = "string", + format = "binary", + description = + "Markdown file converted from PDF"))) + }) +public @interface MarkdownConversionResponse {} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/swagger/MultiFileResponse.java b/app/core/src/main/java/stirling/software/SPDF/config/swagger/MultiFileResponse.java new file mode 100644 index 000000000..c8f232c63 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/swagger/MultiFileResponse.java @@ -0,0 +1,71 @@ +package stirling.software.SPDF.config.swagger; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +/** + * API response annotation for operations that may return multiple files or a ZIP archive. Use for + * operations like PDF to images, split PDF, or multiple file conversions. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = + "Files processed successfully. Returns single file or ZIP archive containing multiple files.", + content = { + @Content( + mediaType = "application/pdf", + schema = + @Schema( + type = "string", + format = "binary", + description = "Single PDF file result")), + @Content( + mediaType = "application/zip", + schema = + @Schema( + type = "string", + format = "binary", + description = + "ZIP archive containing multiple output files")), + @Content( + mediaType = "image/png", + schema = + @Schema( + type = "string", + format = "binary", + description = "Single image file (PNG)")), + @Content( + mediaType = "image/jpeg", + schema = + @Schema( + type = "string", + format = "binary", + description = "Single image file (JPEG)")) + }), + @ApiResponse( + responseCode = "400", + description = "Invalid PDF file or request parameters", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "Internal server error during processing", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))) + }) +public @interface MultiFileResponse {} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/swagger/PowerPointConversionResponse.java b/app/core/src/main/java/stirling/software/SPDF/config/swagger/PowerPointConversionResponse.java new file mode 100644 index 000000000..f7e676537 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/swagger/PowerPointConversionResponse.java @@ -0,0 +1,66 @@ +package stirling.software.SPDF.config.swagger; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +/** + * API response annotation for PDF to PowerPoint presentation conversions. Use for endpoints that + * convert PDF to PPTX format. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "PDF converted successfully to PowerPoint presentation", + content = + @Content( + mediaType = + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + schema = + @Schema( + type = "string", + format = "binary", + description = + "Microsoft PowerPoint presentation (PPTX)"))), + @ApiResponse( + responseCode = "400", + description = + "Bad request - Invalid input parameters, unsupported format, or corrupted PDF", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "413", + description = "Payload too large - File exceeds maximum allowed size", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "422", + description = + "Unprocessable entity - PDF is valid but cannot be converted to PowerPoint format", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = + "Internal server error - Unexpected error during PowerPoint conversion", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))) + }) +public @interface PowerPointConversionResponse {} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/swagger/StandardPdfResponse.java b/app/core/src/main/java/stirling/software/SPDF/config/swagger/StandardPdfResponse.java new file mode 100644 index 000000000..a4d41e8d3 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/swagger/StandardPdfResponse.java @@ -0,0 +1,47 @@ +package stirling.software.SPDF.config.swagger; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +/** + * Standard API response annotation for PDF operations that take PDF input and return PDF output. + * Use for single PDF input → single PDF output (SISO) operations like rotate, compress, etc. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "PDF processed successfully", + content = + @Content( + mediaType = "application/pdf", + schema = + @Schema( + type = "string", + format = "binary", + description = "The processed PDF file"))), + @ApiResponse( + responseCode = "400", + description = "Invalid PDF file or request parameters", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "Internal server error during processing", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))) + }) +public @interface StandardPdfResponse {} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/swagger/TextPlainConversionResponse.java b/app/core/src/main/java/stirling/software/SPDF/config/swagger/TextPlainConversionResponse.java new file mode 100644 index 000000000..b6b07b17d --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/swagger/TextPlainConversionResponse.java @@ -0,0 +1,69 @@ +package stirling.software.SPDF.config.swagger; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +/** + * API response annotation for PDF to plain text conversions. Use for endpoints that extract text + * content from PDF. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "PDF text extracted successfully", + content = { + @Content( + mediaType = "text/plain", + schema = + @Schema( + type = "string", + description = + "Plain text content extracted from PDF")), + @Content( + mediaType = "application/rtf", + schema = + @Schema( + type = "string", + format = "binary", + description = "Rich Text Format document")) + }), + @ApiResponse( + responseCode = "400", + description = "Bad request - Invalid input parameters or corrupted PDF", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "413", + description = "Payload too large - File exceeds maximum allowed size", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "422", + description = "Unprocessable entity - PDF is valid but text extraction failed", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "Internal server error - Unexpected error during text extraction", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))) + }) +public @interface TextPlainConversionResponse {} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/swagger/WordConversionResponse.java b/app/core/src/main/java/stirling/software/SPDF/config/swagger/WordConversionResponse.java new file mode 100644 index 000000000..b1c6f91ec --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/swagger/WordConversionResponse.java @@ -0,0 +1,72 @@ +package stirling.software.SPDF.config.swagger; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +/** + * API response annotation for PDF to Word document conversions. Use for endpoints that convert PDF + * to DOCX/DOC formats. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "PDF converted successfully to Word document", + content = { + @Content( + mediaType = + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + schema = + @Schema( + type = "string", + format = "binary", + description = "Microsoft Word document (DOCX)")), + @Content( + mediaType = "application/msword", + schema = + @Schema( + type = "string", + format = "binary", + description = "Microsoft Word document (DOC)")) + }), + @ApiResponse( + responseCode = "400", + description = + "Bad request - Invalid input parameters, unsupported format, or corrupted PDF", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "413", + description = "Payload too large - File exceeds maximum allowed size", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "422", + description = + "Unprocessable entity - PDF is valid but cannot be converted to Word format", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "Internal server error - Unexpected error during Word conversion", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ErrorResponse.class))) + }) +public @interface WordConversionResponse {} diff --git a/app/core/src/main/java/stirling/software/SPDF/config/swagger/XmlConversionResponse.java b/app/core/src/main/java/stirling/software/SPDF/config/swagger/XmlConversionResponse.java new file mode 100644 index 000000000..49bfd9335 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/config/swagger/XmlConversionResponse.java @@ -0,0 +1,33 @@ +package stirling.software.SPDF.config.swagger; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +/** + * API response annotation for PDF to XML conversions. Use for endpoints that convert PDF to XML + * format. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "PDF converted successfully to XML format", + content = + @Content( + mediaType = "application/xml", + schema = + @Schema( + type = "string", + format = "binary", + description = "XML file converted from PDF"))) + }) +public @interface XmlConversionResponse {} diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java index fe1440d4a..7594e2ab4 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java @@ -14,23 +14,23 @@ import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; import org.springframework.web.bind.annotation.*; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.JsonDataResponse; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.AnalysisApi; import stirling.software.common.model.api.PDFFile; import stirling.software.common.service.CustomPDFDocumentFactory; -@RestController -@RequestMapping("/api/v1/analysis") -@Tag(name = "Analysis", description = "Analysis APIs") +@AnalysisApi @RequiredArgsConstructor public class AnalysisController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(value = "/page-count", consumes = "multipart/form-data") + @JsonDataResponse @Operation( summary = "Get PDF page count", description = "Returns total number of pages in PDF. Input:PDF Output:JSON Type:SISO") @@ -41,6 +41,7 @@ public class AnalysisController { } @AutoJobPostMapping(value = "/basic-info", consumes = "multipart/form-data") + @JsonDataResponse @Operation( summary = "Get basic PDF information", description = "Returns page count, version, file size. Input:PDF Output:JSON Type:SISO") @@ -55,6 +56,7 @@ public class AnalysisController { } @AutoJobPostMapping(value = "/document-properties", consumes = "multipart/form-data") + @JsonDataResponse @Operation( summary = "Get PDF document properties", description = "Returns title, author, subject, etc. Input:PDF Output:JSON Type:SISO") @@ -78,6 +80,7 @@ public class AnalysisController { } @AutoJobPostMapping(value = "/page-dimensions", consumes = "multipart/form-data") + @JsonDataResponse @Operation( summary = "Get page dimensions for all pages", description = "Returns width and height of each page. Input:PDF Output:JSON Type:SISO") @@ -98,6 +101,7 @@ public class AnalysisController { } @AutoJobPostMapping(value = "/form-fields", consumes = "multipart/form-data") + @JsonDataResponse @Operation( summary = "Get form field information", description = @@ -121,6 +125,7 @@ public class AnalysisController { } @AutoJobPostMapping(value = "/annotation-info", consumes = "multipart/form-data") + @JsonDataResponse @Operation( summary = "Get annotation information", description = "Returns count and types of annotations. Input:PDF Output:JSON Type:SISO") @@ -145,6 +150,7 @@ public class AnalysisController { } @AutoJobPostMapping(value = "/font-info", consumes = "multipart/form-data") + @JsonDataResponse @Operation( summary = "Get font information", description = @@ -167,6 +173,7 @@ public class AnalysisController { } @AutoJobPostMapping(value = "/security-info", consumes = "multipart/form-data") + @JsonDataResponse @Operation( summary = "Get security information", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java index 9a7f09c5e..df878fc64 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java @@ -12,28 +12,26 @@ import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.general.CropPdfForm; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/general") -@Tag(name = "General", description = "General APIs") +@GeneralApi @RequiredArgsConstructor public class CropController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(value = "/crop", consumes = "multipart/form-data") + @StandardPdfResponse @Operation( summary = "Crops a PDF document", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java index bce16e867..ae980c47a 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java @@ -14,30 +14,28 @@ import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlin import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; 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.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.JsonDataResponse; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.EditTableOfContentsRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/general") +@GeneralApi @Slf4j -@Tag(name = "General", description = "General APIs") @RequiredArgsConstructor public class EditTableOfContentsController { @@ -45,6 +43,7 @@ public class EditTableOfContentsController { private final ObjectMapper objectMapper; @AutoJobPostMapping(value = "/extract-bookmarks", consumes = "multipart/form-data") + @JsonDataResponse @Operation( summary = "Extract PDF Bookmarks", description = "Extracts bookmarks/table of contents from a PDF document as JSON.") @@ -153,6 +152,7 @@ public class EditTableOfContentsController { } @AutoJobPostMapping(value = "/edit-table-of-contents", consumes = "multipart/form-data") + @StandardPdfResponse @Operation( summary = "Edit Table of Contents", description = "Add or edit bookmarks/table of contents in a PDF document.") diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java index 23a03e59a..6f835d5ba 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java @@ -22,28 +22,25 @@ import org.apache.pdfbox.pdmodel.interactive.form.PDField; import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.general.MergePdfsRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.GeneralUtils; import stirling.software.common.util.PdfErrorUtils; import stirling.software.common.util.WebResponseUtils; -@RestController +@GeneralApi @Slf4j -@RequestMapping("/api/v1/general") -@Tag(name = "General", description = "General APIs") @RequiredArgsConstructor public class MergeController { @@ -155,6 +152,7 @@ public class MergeController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/merge-pdfs") + @StandardPdfResponse @Operation( summary = "Merge multiple PDF files into one", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java index 96b23f332..631e50db6 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java @@ -13,30 +13,28 @@ import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.util.Matrix; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.general.MergeMultiplePagesRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/general") -@Tag(name = "General", description = "General APIs") +@GeneralApi @RequiredArgsConstructor public class MultiPageLayoutController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(value = "/multi-page-layout", consumes = "multipart/form-data") + @StandardPdfResponse @Operation( summary = "Merge multiple pages of a PDF document into a single page", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java index c4dba6eb3..24d235282 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java @@ -6,16 +6,15 @@ import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.service.PdfImageRemovalService; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.model.api.PDFFile; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; @@ -24,9 +23,7 @@ import stirling.software.common.util.WebResponseUtils; * Controller class for handling PDF image removal requests. Provides an endpoint to remove images * from a PDF file to reduce its size. */ -@RestController -@RequestMapping("/api/v1/general") -@Tag(name = "General", description = "General APIs") +@GeneralApi @RequiredArgsConstructor public class PdfImageRemovalController { @@ -47,11 +44,12 @@ public class PdfImageRemovalController { * @throws IOException If an error occurs while processing the PDF file. */ @AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-image-pdf") + @StandardPdfResponse @Operation( summary = "Remove images from file to reduce the file size.", description = "This endpoint remove images from file to reduce the file size.Input:PDF" - + " Output:PDF Type:MISO") + + " Output:PDF Type:SISO") public ResponseEntity removeImages(@ModelAttribute PDFFile file) throws IOException { // Load the PDF document PDDocument document = pdfDocumentFactory.load(file); diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java index 12c267495..a71401a07 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java @@ -15,31 +15,29 @@ import org.apache.pdfbox.pdmodel.PDDocument; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.general.OverlayPdfsRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.GeneralUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/general") -@Tag(name = "General", description = "General APIs") +@GeneralApi @RequiredArgsConstructor public class PdfOverlayController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(value = "/overlay-pdfs", consumes = "multipart/form-data") + @StandardPdfResponse @Operation( summary = "Overlay PDF files in various modes", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java index 31274ac23..adeddc743 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java @@ -9,36 +9,34 @@ import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.SortTypes; import stirling.software.SPDF.model.api.PDFWithPageNums; import stirling.software.SPDF.model.api.general.RearrangePagesRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.GeneralUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/general") +@GeneralApi @Slf4j -@Tag(name = "General", description = "General APIs") @RequiredArgsConstructor public class RearrangePagesPDFController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-pages") + @StandardPdfResponse @Operation( summary = "Remove pages from a PDF file", description = @@ -238,6 +236,7 @@ public class RearrangePagesPDFController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/rearrange-pages") + @StandardPdfResponse @Operation( summary = "Rearrange pages in a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/RotationController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/RotationController.java index bc4062a34..0fc4c9324 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/RotationController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/RotationController.java @@ -7,31 +7,29 @@ import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageTree; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.general.RotatePDFRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/general") -@Tag(name = "General", description = "General APIs") +@GeneralApi @RequiredArgsConstructor public class RotationController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/rotate-pdf") + @StandardPdfResponse @Operation( summary = "Rotate a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java index 1638e1b24..2fad9d7cc 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java @@ -14,31 +14,29 @@ import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.util.Matrix; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.general.ScalePagesRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/general") -@Tag(name = "General", description = "General APIs") +@GeneralApi @RequiredArgsConstructor public class ScalePagesController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(value = "/scale-pages", consumes = "multipart/form-data") + @StandardPdfResponse @Operation( summary = "Change the size of a PDF page/document", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java index a1cedd540..3c2e6f33a 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java @@ -5,25 +5,21 @@ import java.util.Map; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; import io.swagger.v3.oas.annotations.Hidden; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import stirling.software.SPDF.config.EndpointConfiguration; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.SettingsApi; import stirling.software.common.configuration.InstallationPathConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.util.GeneralUtils; -@Controller -@Tag(name = "Settings", description = "Settings APIs") -@RequestMapping("/api/v1/settings") +@SettingsApi @RequiredArgsConstructor @Hidden public class SettingsController { diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java index e3a9e15c6..cb92cffac 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java @@ -15,33 +15,31 @@ import org.apache.pdfbox.pdmodel.PDPage; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.MultiFileResponse; import stirling.software.SPDF.model.api.PDFWithPageNums; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/general") +@GeneralApi @Slf4j -@Tag(name = "General", description = "General APIs") @RequiredArgsConstructor public class SplitPDFController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/split-pages") + @MultiFileResponse @Operation( summary = "Split a PDF file into separate documents", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java index e519344da..c58003d2a 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java @@ -15,13 +15,10 @@ import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlin import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; import lombok.Data; @@ -30,18 +27,18 @@ import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.MultiFileResponse; import stirling.software.SPDF.model.api.SplitPdfByChaptersRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.model.PdfMetadata; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.PdfMetadataService; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/general") +@GeneralApi @Slf4j -@Tag(name = "General", description = "General APIs") @RequiredArgsConstructor public class SplitPdfByChaptersController { @@ -118,6 +115,7 @@ public class SplitPdfByChaptersController { } @AutoJobPostMapping(value = "/split-pdf-by-chapters", consumes = "multipart/form-data") + @MultiFileResponse @Operation( summary = "Split PDFs by Chapters", description = "Splits a PDF into chapters and returns a ZIP file.") diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java index 6d3ae9efe..8835bbb74 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java @@ -20,30 +20,28 @@ import org.apache.pdfbox.util.Matrix; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.MultiFileResponse; import stirling.software.SPDF.model.api.SplitPdfBySectionsRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/general") -@Tag(name = "General", description = "General APIs") +@GeneralApi @RequiredArgsConstructor public class SplitPdfBySectionsController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(value = "/split-pdf-by-sections", consumes = "multipart/form-data") + @MultiFileResponse @Operation( summary = "Split PDF pages into smaller sections", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java index 5ff32f286..955ccf2ad 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java @@ -12,34 +12,32 @@ import org.apache.pdfbox.pdmodel.PDPage; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.MultiFileResponse; import stirling.software.SPDF.model.api.general.SplitPdfBySizeOrCountRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.GeneralUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/general") +@GeneralApi @Slf4j -@Tag(name = "General", description = "General APIs") @RequiredArgsConstructor public class SplitPdfBySizeController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(value = "/split-by-size-or-count", consumes = "multipart/form-data") + @MultiFileResponse @Operation( summary = "Auto split PDF pages into separate documents based on size or count", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java index 1b5f1a750..1350d3f77 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java @@ -12,28 +12,26 @@ import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.common.model.api.PDFFile; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/general") -@Tag(name = "General", description = "General APIs") +@GeneralApi @RequiredArgsConstructor public class ToSinglePageController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf-to-single-page") + @StandardPdfResponse @Operation( summary = "Convert a multi-page PDF into a single long page PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java index 0902cb1f4..ad2fead01 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java @@ -15,14 +15,11 @@ 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.extern.slf4j.Slf4j; @@ -30,6 +27,7 @@ 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.annotations.api.UiDataApi; import stirling.software.common.configuration.InstallationPathConfig; import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.model.ApplicationProperties; @@ -38,9 +36,7 @@ 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") +@UiDataApi public class UIDataController { private final ApplicationProperties applicationProperties; diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEmlToPDF.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEmlToPDF.java index f1aa76f37..c4f4d4305 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEmlToPDF.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEmlToPDF.java @@ -8,18 +8,17 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.ConvertApi; import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.model.api.converters.EmlToPdfRequest; import stirling.software.common.service.CustomPDFDocumentFactory; @@ -28,9 +27,7 @@ import stirling.software.common.util.EmlToPdf; import stirling.software.common.util.TempFileManager; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/convert") -@Tag(name = "Convert", description = "Convert APIs") +@ConvertApi @Slf4j @RequiredArgsConstructor public class ConvertEmlToPDF { @@ -41,6 +38,7 @@ public class ConvertEmlToPDF { private final CustomHtmlSanitizer customHtmlSanitizer; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/eml/pdf") + @StandardPdfResponse @Operation( summary = "Convert EML to PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java index 97cf2e620..f9f380dbc 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java @@ -2,17 +2,16 @@ package stirling.software.SPDF.controller.api.converters; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.ConvertApi; import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.model.api.converters.HTMLToPdfRequest; import stirling.software.common.service.CustomPDFDocumentFactory; @@ -22,9 +21,7 @@ import stirling.software.common.util.FileToPdf; import stirling.software.common.util.TempFileManager; import stirling.software.common.util.WebResponseUtils; -@RestController -@Tag(name = "Convert", description = "Convert APIs") -@RequestMapping("/api/v1/convert") +@ConvertApi @RequiredArgsConstructor public class ConvertHtmlToPDF { @@ -37,6 +34,7 @@ public class ConvertHtmlToPDF { private final CustomHtmlSanitizer customHtmlSanitizer; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/html/pdf") + @StandardPdfResponse @Operation( summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java index ba58d951f..db09833bf 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java @@ -19,20 +19,20 @@ import org.apache.pdfbox.rendering.ImageType; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.MultiFileResponse; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.converters.ConvertToImageRequest; import stirling.software.SPDF.model.api.converters.ConvertToPdfRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.ConvertApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.CheckProgramInstall; import stirling.software.common.util.ExceptionUtils; @@ -42,16 +42,15 @@ import stirling.software.common.util.ProcessExecutor; import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/convert") +@ConvertApi @Slf4j -@Tag(name = "Convert", description = "Convert APIs") @RequiredArgsConstructor public class ConvertImgPDFController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/img") + @MultiFileResponse @Operation( summary = "Convert PDF to image(s)", description = @@ -212,6 +211,7 @@ public class ConvertImgPDFController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/img/pdf") + @StandardPdfResponse @Operation( summary = "Convert images to a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java index 3c82c2844..3bacc7ce1 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java @@ -12,17 +12,16 @@ import org.commonmark.renderer.html.AttributeProvider; import org.commonmark.renderer.html.HtmlRenderer; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.ConvertApi; import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.model.api.GeneralFile; import stirling.software.common.service.CustomPDFDocumentFactory; @@ -32,9 +31,7 @@ import stirling.software.common.util.FileToPdf; import stirling.software.common.util.TempFileManager; import stirling.software.common.util.WebResponseUtils; -@RestController -@Tag(name = "Convert", description = "Convert APIs") -@RequestMapping("/api/v1/convert") +@ConvertApi @RequiredArgsConstructor public class ConvertMarkdownToPdf { @@ -46,6 +43,7 @@ public class ConvertMarkdownToPdf { private final CustomHtmlSanitizer customHtmlSanitizer; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/markdown/pdf") + @StandardPdfResponse @Operation( summary = "Convert a Markdown file to PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java index 339f184b3..95f4b36cb 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java @@ -13,17 +13,15 @@ import org.apache.commons.io.FilenameUtils; import org.apache.pdfbox.pdmodel.PDDocument; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.ConvertApi; import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.model.api.GeneralFile; import stirling.software.common.service.CustomPDFDocumentFactory; @@ -32,9 +30,7 @@ import stirling.software.common.util.ProcessExecutor; import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; import stirling.software.common.util.WebResponseUtils; -@RestController -@Tag(name = "Convert", description = "Convert APIs") -@RequestMapping("/api/v1/convert") +@ConvertApi @RequiredArgsConstructor public class ConvertOfficeController { diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java index 63c96d762..6d19052ab 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java @@ -2,20 +2,17 @@ package stirling.software.SPDF.controller.api.converters; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; +import stirling.software.SPDF.config.swagger.HtmlConversionResponse; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.ConvertApi; import stirling.software.common.model.api.PDFFile; import stirling.software.common.util.PDFToFile; -@RestController -@Tag(name = "Convert", description = "Convert APIs") -@RequestMapping("/api/v1/convert") +@ConvertApi public class ConvertPDFToHtml { @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/html") @@ -23,6 +20,7 @@ public class ConvertPDFToHtml { summary = "Convert PDF to HTML", description = "This endpoint converts a PDF file to HTML format. Input:PDF Output:HTML Type:SISO") + @HtmlConversionResponse public ResponseEntity processPdfToHTML(@ModelAttribute PDFFile file) throws Exception { MultipartFile inputFile = file.getFileInput(); PDFToFile pdfToFile = new PDFToFile(); diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java index ee1b6eaab..afab1ca62 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java @@ -7,34 +7,35 @@ import org.apache.pdfbox.text.PDFTextStripper; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.PowerPointConversionResponse; +import stirling.software.SPDF.config.swagger.TextPlainConversionResponse; +import stirling.software.SPDF.config.swagger.WordConversionResponse; +import stirling.software.SPDF.config.swagger.XmlConversionResponse; import stirling.software.SPDF.model.api.converters.PdfToPresentationRequest; import stirling.software.SPDF.model.api.converters.PdfToTextOrRTFRequest; import stirling.software.SPDF.model.api.converters.PdfToWordRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.ConvertApi; import stirling.software.common.model.api.PDFFile; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.PDFToFile; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/convert") -@Tag(name = "Convert", description = "Convert APIs") +@ConvertApi @RequiredArgsConstructor public class ConvertPDFToOffice { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/presentation") + @PowerPointConversionResponse @Operation( summary = "Convert PDF to Presentation format", description = @@ -50,6 +51,7 @@ public class ConvertPDFToOffice { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/text") + @TextPlainConversionResponse @Operation( summary = "Convert PDF to Text or RTF format", description = @@ -78,6 +80,7 @@ public class ConvertPDFToOffice { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/word") + @WordConversionResponse @Operation( summary = "Convert PDF to Word document", description = @@ -92,6 +95,7 @@ public class ConvertPDFToOffice { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/xml") + @XmlConversionResponse @Operation( summary = "Convert PDF to XML", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java index 0e5aeb1f6..a3fc0e5c7 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java @@ -55,30 +55,28 @@ import org.apache.xmpbox.xml.XmpSerializer; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.converters.PdfToPdfARequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.ConvertApi; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.ProcessExecutor; import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/convert") +@ConvertApi @Slf4j -@Tag(name = "Convert", description = "Convert APIs") public class ConvertPDFToPDFA { @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/pdfa") + @StandardPdfResponse @Operation( summary = "Convert a PDF to a PDF/A", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java index 182dc8a3e..f8c190856 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java @@ -9,17 +9,16 @@ import java.util.List; import org.apache.pdfbox.pdmodel.PDDocument; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.converters.UrlToPdfRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.ConvertApi; import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.service.CustomPDFDocumentFactory; @@ -29,10 +28,8 @@ import stirling.software.common.util.ProcessExecutor; import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; import stirling.software.common.util.WebResponseUtils; -@RestController -@Tag(name = "Convert", description = "Convert APIs") +@ConvertApi @Slf4j -@RequestMapping("/api/v1/convert") @RequiredArgsConstructor public class ConvertWebsiteToPDF { @@ -41,6 +38,7 @@ public class ConvertWebsiteToPDF { private final ApplicationProperties applicationProperties; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/url/pdf") + @StandardPdfResponse @Operation( summary = "Convert a URL to a PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java index 1ce2e6fc3..e787b22ee 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java @@ -18,18 +18,17 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.CsvConversionResponse; import stirling.software.SPDF.model.api.PDFWithPageNums; import stirling.software.SPDF.pdf.FlexibleCSVWriter; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.ConvertApi; import stirling.software.common.service.CustomPDFDocumentFactory; import technology.tabula.ObjectExtractor; @@ -37,9 +36,7 @@ import technology.tabula.Page; import technology.tabula.Table; import technology.tabula.extractors.SpreadsheetExtractionAlgorithm; -@RestController -@RequestMapping("/api/v1/convert") -@Tag(name = "Convert", description = "Convert APIs") +@ConvertApi @Slf4j @RequiredArgsConstructor public class ExtractCSVController { @@ -47,6 +44,7 @@ public class ExtractCSVController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(value = "/pdf/csv", consumes = "multipart/form-data") + @CsvConversionResponse @Operation( summary = "Extracts a CSV document from a PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java index 262c931df..0b130ac48 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java @@ -7,16 +7,14 @@ import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.FilterResponse; import stirling.software.SPDF.model.api.PDFComparisonAndCount; import stirling.software.SPDF.model.api.PDFWithPageNums; import stirling.software.SPDF.model.api.filter.ContainsTextRequest; @@ -24,20 +22,20 @@ import stirling.software.SPDF.model.api.filter.FileSizeRequest; import stirling.software.SPDF.model.api.filter.PageRotationRequest; import stirling.software.SPDF.model.api.filter.PageSizeRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.FilterApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.PdfUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/filter") -@Tag(name = "Filter", description = "Filter APIs") +@FilterApi @RequiredArgsConstructor public class FilterController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-contains-text") + @FilterResponse @Operation( summary = "Checks if a PDF contains set text, returns true if does", description = "Input:PDF Output:Boolean Type:SISO") @@ -56,6 +54,7 @@ public class FilterController { // TODO @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-contains-image") + @FilterResponse @Operation( summary = "Checks if a PDF contains an image", description = "Input:PDF Output:Boolean Type:SISO") @@ -72,6 +71,7 @@ public class FilterController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-count") + @FilterResponse @Operation( summary = "Checks if a PDF is greater, less or equal to a setPageCount", description = "Input:PDF Output:Boolean Type:SISO") @@ -105,6 +105,7 @@ public class FilterController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-size") + @FilterResponse @Operation( summary = "Checks if a PDF is of a certain size", description = "Input:PDF Output:Boolean Type:SISO") @@ -148,6 +149,7 @@ public class FilterController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-file-size") + @FilterResponse @Operation( summary = "Checks if a PDF is a set file size", description = "Input:PDF Output:Boolean Type:SISO") @@ -181,6 +183,7 @@ public class FilterController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-rotation") + @FilterResponse @Operation( summary = "Checks if a PDF is of a certain rotation", description = "Input:PDF Output:Boolean Type:SISO") diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AttachmentController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AttachmentController.java index c6a274f5c..b02dbb240 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AttachmentController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AttachmentController.java @@ -6,28 +6,25 @@ import java.util.List; import org.apache.pdfbox.pdmodel.PDDocument; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.misc.AddAttachmentRequest; import stirling.software.SPDF.service.AttachmentServiceInterface; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; +@MiscApi @Slf4j -@RestController @RequiredArgsConstructor -@RequestMapping("/api/v1/misc") -@Tag(name = "Misc", description = "Miscellaneous APIs") public class AttachmentController { private final CustomPDFDocumentFactory pdfDocumentFactory; @@ -35,6 +32,7 @@ public class AttachmentController { private final AttachmentServiceInterface pdfAttachmentService; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-attachments") + @StandardPdfResponse @Operation( summary = "Add attachments to PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java index 214d0870a..1545945f9 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java @@ -10,26 +10,22 @@ import org.apache.pdfbox.text.PDFTextStripper; import org.apache.pdfbox.text.TextPosition; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.misc.ExtractHeaderRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") +@MiscApi @Slf4j -@Tag(name = "Misc", description = "Miscellaneous APIs") @RequiredArgsConstructor public class AutoRenameController { diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java index 78518617a..ee8e3847e 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java @@ -19,8 +19,6 @@ import org.apache.pdfbox.rendering.PDFRenderer; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.google.zxing.*; @@ -28,20 +26,19 @@ import com.google.zxing.common.HybridBinarizer; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.MultiFileResponse; import stirling.software.SPDF.model.api.misc.AutoSplitPdfRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") +@MiscApi @Slf4j -@Tag(name = "Misc", description = "Miscellaneous APIs") @RequiredArgsConstructor public class AutoSplitPdfController { @@ -103,6 +100,7 @@ public class AutoSplitPdfController { } @AutoJobPostMapping(value = "/auto-split-pdf", consumes = "multipart/form-data") + @MultiFileResponse @Operation( summary = "Auto split PDF pages into separate documents", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java index f6f9f94ad..51f4aee68 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java @@ -17,27 +17,23 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.misc.RemoveBlankPagesRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.PdfUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") +@MiscApi @Slf4j -@Tag(name = "Misc", description = "Miscellaneous APIs") @RequiredArgsConstructor public class BlankPageController { diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java index 20a869c2c..37ee16271 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java @@ -34,13 +34,10 @@ import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; import lombok.Data; @@ -50,8 +47,10 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.config.EndpointConfiguration; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.misc.OptimizePdfRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.GeneralUtils; @@ -59,10 +58,8 @@ import stirling.software.common.util.ProcessExecutor; import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") +@MiscApi @Slf4j -@Tag(name = "Misc", description = "Miscellaneous APIs") @RequiredArgsConstructor public class CompressController { @@ -659,6 +656,7 @@ public class CompressController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/compress-pdf") + @StandardPdfResponse @Operation( summary = "Optimize PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java index bc9174476..f066cb82f 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java @@ -6,22 +6,18 @@ import java.util.Map; import org.springframework.context.ApplicationContext; 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.RequestParam; -import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Hidden; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import stirling.software.SPDF.config.EndpointConfiguration; +import stirling.software.common.annotations.api.ConfigApi; import stirling.software.common.configuration.AppConfig; import stirling.software.common.model.ApplicationProperties; -@RestController -@Tag(name = "Config", description = "Configuration APIs") -@RequestMapping("/api/v1/config") +@ConfigApi @RequiredArgsConstructor @Hidden public class ConfigController { diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java index 93dc8ee56..675d42acd 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java @@ -13,26 +13,22 @@ import org.apache.pdfbox.pdmodel.PDDocument; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.model.api.PDFFile; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") +@MiscApi @Slf4j -@Tag(name = "Misc", description = "Miscellaneous APIs") @RequiredArgsConstructor public class DecompressPdfController { diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java index d40a6a292..1fa04d5d6 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java @@ -19,18 +19,17 @@ import org.apache.pdfbox.rendering.PDFRenderer; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.MultiFileResponse; import stirling.software.SPDF.model.api.misc.ExtractImageScansRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.CheckProgramInstall; import stirling.software.common.util.ExceptionUtils; @@ -39,10 +38,8 @@ import stirling.software.common.util.ProcessExecutor; import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") +@MiscApi @Slf4j -@Tag(name = "Misc", description = "Miscellaneous APIs") @RequiredArgsConstructor public class ExtractImageScansController { @@ -51,6 +48,7 @@ public class ExtractImageScansController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/extract-image-scans") + @MultiFileResponse @Operation( summary = "Extract image scans from an input file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java index 026dd1b70..24f64f8ea 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java @@ -27,34 +27,32 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.MultiFileResponse; import stirling.software.SPDF.model.api.PDFExtractImagesRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.ImageProcessingUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") +@MiscApi @Slf4j -@Tag(name = "Misc", description = "Miscellaneous APIs") @RequiredArgsConstructor public class ExtractImagesController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/extract-images") + @MultiFileResponse @Operation( summary = "Extract images from a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java index 984871185..94d1c1598 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java @@ -13,32 +13,30 @@ import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.PDFRenderer; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.misc.FlattenRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") +@MiscApi @Slf4j -@Tag(name = "Misc", description = "Miscellaneous APIs") @RequiredArgsConstructor public class FlattenController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/flatten") + @StandardPdfResponse @Operation( summary = "Flatten PDF form fields or full page", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java index 0253ccdf4..5f45d3419 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java @@ -17,21 +17,20 @@ import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.misc.MetadataRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; import stirling.software.common.util.propertyeditor.StringToMapPropertyEditor; -@RestController -@RequestMapping("/api/v1/misc") +@MiscApi @Slf4j -@Tag(name = "Misc", description = "Miscellaneous APIs") @RequiredArgsConstructor public class MetadataController { @@ -53,6 +52,7 @@ public class MetadataController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/update-metadata") + @StandardPdfResponse @Operation( summary = "Update metadata of a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java index a1b2fa277..ce2a9c98f 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java @@ -18,20 +18,19 @@ import org.apache.pdfbox.text.PDFTextStripper; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.config.EndpointConfiguration; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.misc.ProcessPdfWithOcrRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; @@ -42,9 +41,7 @@ import stirling.software.common.util.TempFile; import stirling.software.common.util.TempFileManager; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") -@Tag(name = "Misc", description = "Miscellaneous APIs") +@MiscApi @Slf4j @RequiredArgsConstructor public class OCRController { @@ -77,6 +74,7 @@ public class OCRController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/ocr-pdf") + @StandardPdfResponse @Operation( summary = "Process a PDF file with OCR", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java index 8c9a99436..878d29af0 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java @@ -5,27 +5,23 @@ import java.io.IOException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.misc.OverlayImageRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.PdfUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") +@MiscApi @Slf4j -@Tag(name = "Misc", description = "Miscellaneous APIs") @RequiredArgsConstructor public class OverlayImageController { diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java index 864735880..ec1825b15 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java @@ -13,31 +13,29 @@ import org.apache.pdfbox.pdmodel.font.Standard14Fonts; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.misc.AddPageNumbersRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.GeneralUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") -@Tag(name = "Misc", description = "Miscellaneous APIs") +@MiscApi @RequiredArgsConstructor public class PageNumbersController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(value = "/add-page-numbers", consumes = "multipart/form-data") + @StandardPdfResponse @Operation( summary = "Add page numbers to a PDF document", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java index 5fc54a799..9ab553a6f 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java @@ -20,19 +20,14 @@ import org.apache.pdfbox.printing.PDFPageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import io.swagger.v3.oas.annotations.tags.Tag; - import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.misc.PrintFileRequest; +import stirling.software.common.annotations.api.MiscApi; -@RestController -@RequestMapping("/api/v1/misc") -@Tag(name = "Misc", description = "Miscellaneous APIs") +@MiscApi @Slf4j public class PrintFileController { diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java index a5c1d79cc..19dac9108 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java @@ -6,19 +6,18 @@ import java.util.List; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.config.EndpointConfiguration; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.model.api.PDFFile; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ProcessExecutor; @@ -27,9 +26,7 @@ import stirling.software.common.util.TempFile; import stirling.software.common.util.TempFileManager; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") -@Tag(name = "Misc", description = "Miscellaneous APIs") +@MiscApi @Slf4j @RequiredArgsConstructor public class RepairController { @@ -47,6 +44,7 @@ public class RepairController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/repair") + @StandardPdfResponse @Operation( summary = "Repair a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java index e8c864d5c..6fd1c9bf9 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java @@ -7,21 +7,17 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import stirling.software.SPDF.model.api.misc.ReplaceAndInvertColorRequest; import stirling.software.SPDF.service.misc.ReplaceAndInvertColorService; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; -@RestController -@RequestMapping("/api/v1/misc") -@Tag(name = "Misc", description = "Miscellaneous APIs") +@MiscApi @RequiredArgsConstructor public class ReplaceAndInvertColorController { diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ScannerEffectController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ScannerEffectController.java index f7fe0e837..71d51b1f3 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ScannerEffectController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ScannerEffectController.java @@ -19,13 +19,10 @@ import org.apache.pdfbox.rendering.PDFRenderer; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -34,12 +31,11 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.misc.ScannerEffectRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") -@Tag(name = "Misc", description = "Miscellaneous PDF APIs") +@MiscApi @RequiredArgsConstructor @Slf4j public class ScannerEffectController { diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java index 56f43ca41..6ed114616 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java @@ -9,30 +9,28 @@ import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.JavaScriptResponse; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.model.api.PDFFile; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") -@Tag(name = "Misc", description = "Miscellaneous APIs") +@MiscApi @RequiredArgsConstructor public class ShowJavascript { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/show-javascript") + @JavaScriptResponse @Operation( summary = "Grabs all JS from a PDF and returns a single JS file with all code", description = "desc. Input:PDF Output:JS Type:SISO") diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java index 590ace5d4..8b6aa09e7 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java @@ -26,26 +26,23 @@ import org.apache.pdfbox.util.Matrix; import org.springframework.core.io.ClassPathResource; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.misc.AddStampRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.TempFile; import stirling.software.common.util.TempFileManager; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") -@Tag(name = "Misc", description = "Miscellaneous APIs") +@MiscApi @RequiredArgsConstructor public class StampController { @@ -53,6 +50,7 @@ public class StampController { private final TempFileManager tempFileManager; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-stamp") + @StandardPdfResponse @Operation( summary = "Add stamp to a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java index d1394d366..32e81443f 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java @@ -12,24 +12,21 @@ import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; import org.apache.pdfbox.pdmodel.interactive.form.PDField; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.MiscApi; import stirling.software.common.model.api.PDFFile; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/misc") +@MiscApi @Slf4j -@Tag(name = "Misc", description = "Miscellaneous APIs") public class UnlockPDFFormsController { private final CustomPDFDocumentFactory pdfDocumentFactory; @@ -38,6 +35,7 @@ public class UnlockPDFFormsController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/unlock-pdf-forms") + @StandardPdfResponse @Operation( summary = "Remove read-only property from form fields", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java index ac034e287..bc1e77190 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java @@ -12,31 +12,29 @@ import org.springframework.core.io.Resource; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; -import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.MultiFileResponse; import stirling.software.SPDF.model.PipelineConfig; import stirling.software.SPDF.model.PipelineOperation; import stirling.software.SPDF.model.PipelineResult; import stirling.software.SPDF.model.api.HandleDataRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.PipelineApi; import stirling.software.common.service.PostHogService; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/pipeline") +@PipelineApi @Slf4j -@Tag(name = "Pipeline", description = "Pipeline APIs") @RequiredArgsConstructor public class PipelineController { @@ -47,6 +45,13 @@ public class PipelineController { private final PostHogService postHogService; @AutoJobPostMapping(value = "/handleData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @MultiFileResponse + @Operation( + summary = "Execute automated PDF processing pipeline", + description = + "This endpoint processes multiple PDF files through a configurable pipeline of operations. " + + "Users provide files and a JSON configuration defining the sequence of operations to perform. " + + "Input:PDF Output:PDF/ZIP Type:MIMO") public ResponseEntity handleData(@ModelAttribute HandleDataRequest request) throws JsonMappingException, JsonProcessingException { MultipartFile[] files = request.getFileInput(); diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java index 316311d87..c68cc073b 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java @@ -71,6 +71,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.security.SignPDFWithCertRequest; import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.service.CustomPDFDocumentFactory; @@ -144,6 +145,7 @@ public class CertSignController { MediaType.APPLICATION_FORM_URLENCODED_VALUE }, value = "/cert-sign") + @StandardPdfResponse @Operation( summary = "Sign PDF with a Digital Certificate", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java index 8d5f6fb37..d8c681e2e 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java @@ -46,8 +46,6 @@ import org.apache.xmpbox.xml.XmpSerializer; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.fasterxml.jackson.databind.ObjectMapper; @@ -55,21 +53,20 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.JsonDataResponse; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.SecurityApi; import stirling.software.common.model.api.PDFFile; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/security") +@SecurityApi @Slf4j -@Tag(name = "Security", description = "Security APIs") @RequiredArgsConstructor public class GetInfoOnPDF { @@ -189,6 +186,7 @@ public class GetInfoOnPDF { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/get-info-on-pdf") + @JsonDataResponse @Operation(summary = "Summary here", description = "desc. Input:PDF Output:JSON Type:SISO") public ResponseEntity getPdfInfo(@ModelAttribute PDFFile request) throws IOException { MultipartFile inputFile = request.getFileInput(); diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java index 566a1224a..7475f94c4 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java @@ -7,32 +7,30 @@ import org.apache.pdfbox.pdmodel.encryption.AccessPermission; import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.security.AddPasswordRequest; import stirling.software.SPDF.model.api.security.PDFPasswordRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.SecurityApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/security") -@Tag(name = "Security", description = "Security APIs") +@SecurityApi @RequiredArgsConstructor public class PasswordController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-password") + @StandardPdfResponse @Operation( summary = "Remove password from a PDF file", description = @@ -59,6 +57,7 @@ public class PasswordController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-password") + @StandardPdfResponse @Operation( summary = "Add password to a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java index d73381f19..5e481f93d 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java @@ -18,22 +18,21 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.PDFText; import stirling.software.SPDF.model.api.security.ManualRedactPdfRequest; import stirling.software.SPDF.model.api.security.RedactPdfRequest; import stirling.software.SPDF.pdf.TextFinder; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.SecurityApi; import stirling.software.common.model.api.security.RedactionArea; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.GeneralUtils; @@ -41,10 +40,8 @@ import stirling.software.common.util.PdfUtils; import stirling.software.common.util.WebResponseUtils; import stirling.software.common.util.propertyeditor.StringToArrayListPropertyEditor; -@RestController -@RequestMapping("/api/v1/security") +@SecurityApi @Slf4j -@Tag(name = "Security", description = "Security APIs") @RequiredArgsConstructor public class RedactController { @@ -57,13 +54,15 @@ public class RedactController { } @AutoJobPostMapping(value = "/redact", consumes = "multipart/form-data") + @StandardPdfResponse @Operation( + operationId = "redactPdfManual", summary = "Redacts areas and pages in a PDF document", description = "This operation takes an input PDF file with a list of areas, page" + " number(s)/range(s)/function(s) to redact. Input:PDF, Output:PDF," + " Type:SISO") - public ResponseEntity redactPDF(@ModelAttribute ManualRedactPdfRequest request) + public ResponseEntity redactPdfManual(@ModelAttribute ManualRedactPdfRequest request) throws IOException { MultipartFile file = request.getFileInput(); List redactionAreas = request.getRedactions(); @@ -191,7 +190,9 @@ public class RedactController { } @AutoJobPostMapping(value = "/auto-redact", consumes = "multipart/form-data") + @StandardPdfResponse @Operation( + operationId = "redactPdfAuto", summary = "Redacts listOfText in a PDF document", description = "This operation takes an input PDF file and redacts the provided listOfText." diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java index c07656d68..553de109c 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java @@ -9,30 +9,28 @@ import org.apache.pdfbox.pdmodel.interactive.form.PDField; import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.SecurityApi; import stirling.software.common.model.api.PDFFile; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/security") -@Tag(name = "Security", description = "Security APIs") +@SecurityApi @RequiredArgsConstructor public class RemoveCertSignController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-cert-sign") + @StandardPdfResponse @Operation( summary = "Remove digital signature from PDF", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java index af6b30a47..70a46a22e 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java @@ -23,30 +23,28 @@ import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; import org.apache.pdfbox.pdmodel.interactive.form.PDField; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.security.SanitizePdfRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.SecurityApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/security") -@Tag(name = "Security", description = "Security APIs") +@SecurityApi @RequiredArgsConstructor public class SanitizeController { private final CustomPDFDocumentFactory pdfDocumentFactory; @AutoJobPostMapping(consumes = "multipart/form-data", value = "/sanitize-pdf") + @StandardPdfResponse @Operation( summary = "Sanitize a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java index 7ce340fbc..d58706886 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java @@ -27,25 +27,22 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.JsonDataResponse; import stirling.software.SPDF.model.api.security.SignatureValidationRequest; import stirling.software.SPDF.model.api.security.SignatureValidationResult; import stirling.software.SPDF.service.CertificateValidationService; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.SecurityApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.ExceptionUtils; -@RestController -@RequestMapping("/api/v1/security") -@Tag(name = "Security", description = "Security APIs") +@SecurityApi @RequiredArgsConstructor public class ValidateSignatureController { @@ -64,6 +61,7 @@ public class ValidateSignatureController { }); } + @JsonDataResponse @Operation( summary = "Validate PDF Digital Signature", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java index e94559658..47fe17e93 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java @@ -28,25 +28,22 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.security.AddWatermarkRequest; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.SecurityApi; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.PdfUtils; import stirling.software.common.util.WebResponseUtils; -@RestController -@RequestMapping("/api/v1/security") -@Tag(name = "Security", description = "Security APIs") +@SecurityApi @RequiredArgsConstructor public class WatermarkController { @@ -65,6 +62,7 @@ public class WatermarkController { } @AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-watermark") + @StandardPdfResponse @Operation( summary = "Add watermark to a PDF file", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java index e82acaffa..5049d55b8 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java @@ -7,15 +7,12 @@ import java.util.*; import org.springframework.http.HttpStatus; 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.RequestParam; -import org.springframework.web.bind.annotation.RestController; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.PostConstruct; @@ -24,11 +21,10 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.config.EndpointInspector; import stirling.software.SPDF.config.StartupApplicationListener; +import stirling.software.common.annotations.api.InfoApi; import stirling.software.common.model.ApplicationProperties; -@RestController -@RequestMapping("/api/v1/info") -@Tag(name = "Info", description = "Info APIs") +@InfoApi @Slf4j @RequiredArgsConstructor public class MetricsController { diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java index 6ef6fc773..5c8fe550a 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java @@ -9,7 +9,6 @@ import org.springframework.ui.Model; import org.springframework.web.servlet.ModelAndView; import io.swagger.v3.oas.annotations.Hidden; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -17,7 +16,6 @@ import stirling.software.common.model.ApplicationProperties; import stirling.software.common.util.CheckProgramInstall; // @Controller // Disabled - Backend-only mode, no Thymeleaf UI -@Tag(name = "Misc", description = "Miscellaneous APIs") @RequiredArgsConstructor public class OtherWebController { diff --git a/app/core/src/main/java/stirling/software/SPDF/model/api/EditTableOfContentsRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/EditTableOfContentsRequest.java index 51e3bc159..312557b5e 100644 --- a/app/core/src/main/java/stirling/software/SPDF/model/api/EditTableOfContentsRequest.java +++ b/app/core/src/main/java/stirling/software/SPDF/model/api/EditTableOfContentsRequest.java @@ -13,8 +13,9 @@ public class EditTableOfContentsRequest extends PDFFile { @Schema( description = "Bookmark structure in JSON format", + type = "string", example = - "[{\"title\":\"Chapter 1\",\"pageNumber\":1,\"children\":[{\"title\":\"Section 1.1\",\"pageNumber\":2}]}]") + "[{\\\"title\\\":\\\"Chapter 1\\\",\\\"pageNumber\\\":1,\\\"children\\\":[{\\\"title\\\":\\\"Section 1.1\\\",\\\"pageNumber\\\":2}]}]") private String bookmarkData; @Schema( diff --git a/app/core/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java index 7f425dc04..8799980f5 100644 --- a/app/core/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java +++ b/app/core/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java @@ -15,8 +15,11 @@ public class HandleDataRequest { private MultipartFile[] fileInput; @Schema( - description = "JSON String", - defaultValue = "{}", + description = + "Pipeline configuration in JSON format containing name and operations list", + type = "string", + example = + "{\\\"name\\\":\\\"Prepare-pdfs-for-email\\\",\\\"pipeline\\\":[{\\\"operation\\\":\\\"/api/v1/misc/repair\\\",\\\"parameters\\\":{}},{\\\"operation\\\":\\\"/api/v1/security/sanitize-pdf\\\",\\\"parameters\\\":{\\\"removeJavaScript\\\":true,\\\"removeEmbeddedFiles\\\":false}},{\\\"operation\\\":\\\"/api/v1/misc/compress-pdf\\\",\\\"parameters\\\":{\\\"optimizeLevel\\\":2}}]}", requiredMode = Schema.RequiredMode.REQUIRED) private String json; } diff --git a/app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPDFToMarkdown.java b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPDFToMarkdown.java index e9b326a2a..5febf16d0 100644 --- a/app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPDFToMarkdown.java +++ b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPDFToMarkdown.java @@ -9,6 +9,7 @@ import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import stirling.software.SPDF.config.swagger.MarkdownConversionResponse; import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.model.api.PDFFile; import stirling.software.common.util.PDFToFile; @@ -19,6 +20,7 @@ import stirling.software.common.util.PDFToFile; public class ConvertPDFToMarkdown { @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/markdown") + @MarkdownConversionResponse @Operation( summary = "Convert PDF to Markdown", description = diff --git a/app/core/src/main/java/stirling/software/SPDF/model/api/general/MergeMultiplePagesRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/general/MergeMultiplePagesRequest.java index 6d9254023..972db7ce3 100644 --- a/app/core/src/main/java/stirling/software/SPDF/model/api/general/MergeMultiplePagesRequest.java +++ b/app/core/src/main/java/stirling/software/SPDF/model/api/general/MergeMultiplePagesRequest.java @@ -13,11 +13,10 @@ public class MergeMultiplePagesRequest extends PDFFile { @Schema( description = "The number of pages to fit onto a single sheet in the output PDF.", - type = "number", - defaultValue = "2", + type = "integer", requiredMode = Schema.RequiredMode.REQUIRED, allowableValues = {"2", "3", "4", "9", "16"}) - private int pagesPerSheet; + private int pagesPerSheet = 2; @Schema(description = "Boolean for if you wish to add border around the pages") private Boolean addBorder; diff --git a/app/core/src/main/java/stirling/software/SPDF/model/api/general/RotatePDFRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/general/RotatePDFRequest.java index aebc2b399..030a0df42 100644 --- a/app/core/src/main/java/stirling/software/SPDF/model/api/general/RotatePDFRequest.java +++ b/app/core/src/main/java/stirling/software/SPDF/model/api/general/RotatePDFRequest.java @@ -14,8 +14,8 @@ public class RotatePDFRequest extends PDFFile { @Schema( description = "The angle by which to rotate the PDF file. This should be a multiple of 90.", + type = "integer", requiredMode = Schema.RequiredMode.REQUIRED, - allowableValues = {"0", "90", "180", "270"}, - defaultValue = "90") - private Integer angle; + allowableValues = {"0", "90", "180", "270"}) + private Integer angle = 90; } diff --git a/app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddPageNumbersRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddPageNumbersRequest.java index 5f0f71695..bbf3602d1 100644 --- a/app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddPageNumbersRequest.java +++ b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddPageNumbersRequest.java @@ -37,10 +37,10 @@ public class AddPageNumbersRequest extends PDFWithPageNums { "Position: 1-9 representing positions on the page (1=top-left, 2=top-center," + " 3=top-right, 4=middle-left, 5=middle-center, 6=middle-right," + " 7=bottom-left, 8=bottom-center, 9=bottom-right)", + type = "integer", allowableValues = {"1", "2", "3", "4", "5", "6", "7", "8", "9"}, - defaultValue = "8", requiredMode = RequiredMode.REQUIRED) - private int position; + private int position = 8; @Schema( description = "Starting number for page numbering", diff --git a/app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddStampRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddStampRequest.java index 48d470a5a..d12104a79 100644 --- a/app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddStampRequest.java +++ b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddStampRequest.java @@ -54,10 +54,10 @@ public class AddStampRequest extends PDFWithPageNums { "Position for stamp placement based on a 1-9 grid (1: bottom-left, 2: bottom-center," + " 3: bottom-right, 4: middle-left, 5: middle-center, 6: middle-right," + " 7: top-left, 8: top-center, 9: top-right)", + type = "integer", allowableValues = {"1", "2", "3", "4", "5", "6", "7", "8", "9"}, - defaultValue = "5", requiredMode = Schema.RequiredMode.REQUIRED) - private int position; + private int position = 5; @Schema( description = diff --git a/app/core/src/main/java/stirling/software/SPDF/model/api/misc/OptimizePdfRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/OptimizePdfRequest.java index eafeeceaa..bf96dd217 100644 --- a/app/core/src/main/java/stirling/software/SPDF/model/api/misc/OptimizePdfRequest.java +++ b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/OptimizePdfRequest.java @@ -15,10 +15,10 @@ public class OptimizePdfRequest extends PDFFile { description = "The level of optimization to apply to the PDF file. Higher values indicate" + " greater compression but may reduce quality.", - defaultValue = "5", + type = "integer", requiredMode = Schema.RequiredMode.REQUIRED, allowableValues = {"1", "2", "3", "4", "5", "6", "7", "8", "9"}) - private Integer optimizeLevel; + private Integer optimizeLevel = 5; @Schema( description = "The expected output size, e.g. '100MB', '25KB', etc.", diff --git a/app/core/src/main/java/stirling/software/SPDF/model/api/security/AddPasswordRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/security/AddPasswordRequest.java index 666318a49..541a8717f 100644 --- a/app/core/src/main/java/stirling/software/SPDF/model/api/security/AddPasswordRequest.java +++ b/app/core/src/main/java/stirling/software/SPDF/model/api/security/AddPasswordRequest.java @@ -27,8 +27,8 @@ public class AddPasswordRequest extends PDFFile { @Schema( description = "The length of the encryption key", + type = "integer", allowableValues = {"40", "128", "256"}, - defaultValue = "256", requiredMode = Schema.RequiredMode.REQUIRED) private int keyLength = 256; diff --git a/app/core/src/main/resources/application.properties b/app/core/src/main/resources/application.properties index a631b8b14..1f4e831df 100644 --- a/app/core/src/main/resources/application.properties +++ b/app/core/src/main/resources/application.properties @@ -49,6 +49,8 @@ springdoc.api-docs.path=/v1/api-docs # Set the URL of the OpenAPI JSON for the Swagger UI springdoc.swagger-ui.url=/v1/api-docs springdoc.swagger-ui.path=/index.html +# Force OpenAPI 3.0 specification version +springdoc.api-docs.version=OPENAPI_3_0 posthog.api.key=phc_fiR65u5j6qmXTYL56MNrLZSWqLaDW74OrZH0Insd2xq posthog.host=https://eu.i.posthog.com diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java index f4eb114ef..5f321a89e 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java @@ -14,18 +14,16 @@ 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.annotations.api.ProprietaryUiDataApi; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; @@ -54,9 +52,7 @@ 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)") +@ProprietaryUiDataApi @EnterpriseEndpoint public class ProprietaryUIDataController { diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/model/Team.java b/app/proprietary/src/main/java/stirling/software/proprietary/model/Team.java index 5157b3233..119c90955 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/model/Team.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/model/Team.java @@ -4,6 +4,8 @@ import java.io.Serializable; import java.util.HashSet; import java.util.Set; +import com.fasterxml.jackson.annotation.JsonIgnore; + import jakarta.persistence.*; import lombok.*; @@ -30,6 +32,7 @@ public class Team implements Serializable { private String name; @OneToMany(mappedBy = "team", cascade = CascadeType.ALL, orphanRemoval = true) + @JsonIgnore private Set users = new HashSet<>(); public void addUser(User user) { diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminSettingsController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminSettingsController.java index ebe856b00..8282cf073 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminSettingsController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminSettingsController.java @@ -12,12 +12,10 @@ import java.util.regex.Pattern; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.util.HtmlUtils; @@ -26,22 +24,20 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.common.annotations.api.AdminApi; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.util.GeneralUtils; import stirling.software.proprietary.security.model.api.admin.SettingValueResponse; import stirling.software.proprietary.security.model.api.admin.UpdateSettingValueRequest; import stirling.software.proprietary.security.model.api.admin.UpdateSettingsRequest; -@Controller -@Tag(name = "Admin Settings", description = "Admin-only Settings Management APIs") -@RequestMapping("/api/v1/admin/settings") +@AdminApi @RequiredArgsConstructor @PreAuthorize("hasRole('ROLE_ADMIN')") @Slf4j diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java index dec64c46f..9a3bcf839 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java @@ -14,7 +14,6 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.support.RedirectAttributes; @@ -22,20 +21,18 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.common.annotations.api.DatabaseApi; import stirling.software.proprietary.security.database.H2SQLCondition; import stirling.software.proprietary.security.service.DatabaseService; @Slf4j -@Controller -@RequestMapping("/api/v1/database") +@DatabaseApi @PreAuthorize("hasRole('ROLE_ADMIN')") @Conditional(H2SQLCondition.class) -@Tag(name = "Database", description = "Database APIs for backup, import, and management") @RequiredArgsConstructor public class DatabaseController { diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java index e2a55e00e..174e96b82 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/EmailController.java @@ -5,11 +5,8 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.mail.MailSendException; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.mail.MessagingException; import jakarta.validation.Valid; @@ -18,6 +15,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.common.annotations.AutoJobPostMapping; +import stirling.software.common.annotations.api.GeneralApi; import stirling.software.proprietary.security.model.api.Email; import stirling.software.proprietary.security.service.EmailService; @@ -25,11 +23,9 @@ import stirling.software.proprietary.security.service.EmailService; * Controller for handling email-related API requests. This controller exposes an endpoint for * sending emails with attachments. */ -@RestController -@RequestMapping("/api/v1/general") +@GeneralApi @RequiredArgsConstructor @Slf4j -@Tag(name = "General", description = "General APIs") @ConditionalOnProperty(value = "mail.enabled", havingValue = "true", matchIfMissing = false) public class EmailController { private final EmailService emailService; diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/TeamController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/TeamController.java index fa8588e7b..84066ec69 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/TeamController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/TeamController.java @@ -3,17 +3,15 @@ package stirling.software.proprietary.security.controller.api; import java.util.Optional; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.view.RedirectView; -import io.swagger.v3.oas.annotations.tags.Tag; - import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.common.annotations.api.TeamApi; import stirling.software.proprietary.model.Team; import stirling.software.proprietary.security.config.PremiumEndpoint; import stirling.software.proprietary.security.database.repository.UserRepository; @@ -21,9 +19,7 @@ import stirling.software.proprietary.security.model.User; import stirling.software.proprietary.security.repository.TeamRepository; import stirling.software.proprietary.security.service.TeamService; -@Controller -@RequestMapping("/api/v1/team") -@Tag(name = "Team", description = "Team Management APIs") +@TeamApi @Slf4j @RequiredArgsConstructor @PremiumEndpoint diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java index 4401403c6..8e3aa818d 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java @@ -15,14 +15,11 @@ import org.springframework.security.core.session.SessionInformation; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; -import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.servlet.view.RedirectView; -import io.swagger.v3.oas.annotations.tags.Tag; - import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.transaction.Transactional; @@ -30,6 +27,7 @@ import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.common.annotations.api.UserApi; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.enumeration.Role; import stirling.software.common.model.exception.UnsupportedProviderException; @@ -44,9 +42,7 @@ import stirling.software.proprietary.security.service.TeamService; import stirling.software.proprietary.security.service.UserService; import stirling.software.proprietary.security.session.SessionPersistentRegistry; -@Controller -@Tag(name = "User", description = "User APIs") -@RequestMapping("/api/v1/user") +@UserApi @Slf4j @RequiredArgsConstructor public class UserController { diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/model/Authority.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/model/Authority.java index a32e7d7ca..9adcce1ad 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/model/Authority.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/model/Authority.java @@ -4,6 +4,8 @@ import java.io.Serializable; import org.springframework.security.core.GrantedAuthority; +import com.fasterxml.jackson.annotation.JsonIgnore; + import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -33,6 +35,7 @@ public class Authority implements GrantedAuthority, Serializable { @ManyToOne @JoinColumn(name = "user_id") + @JsonIgnore private User user; public Authority() {} diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java index 7d1b235cd..616067bed 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java @@ -9,6 +9,8 @@ import java.util.stream.Collectors; import org.springframework.security.core.userdetails.UserDetails; +import com.fasterxml.jackson.annotation.JsonIgnore; + import jakarta.persistence.*; import lombok.EqualsAndHashCode; @@ -62,6 +64,7 @@ public class User implements UserDetails, Serializable { @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "team_id") + @JsonIgnore private Team team; @ElementCollection diff --git a/frontend/public/locales/en-GB/translation.json b/frontend/public/locales/en-GB/translation.json index bf82fa8f4..ad726085f 100644 --- a/frontend/public/locales/en-GB/translation.json +++ b/frontend/public/locales/en-GB/translation.json @@ -104,6 +104,7 @@ "green": "Green", "blue": "Blue", "custom": "Custom...", + "comingSoon": "Coming soon", "WorkInProgess": "Work in progress, May not work or be buggy, Please report any problems!", "poweredBy": "Powered by", "yes": "Yes", @@ -382,7 +383,7 @@ "title": "Add image", "desc": "Adds a image onto a set location on the PDF" }, - "attachments": { + "addAttachments": { "title": "Add Attachments", "desc": "Add or remove embedded files (attachments) to/from a PDF" }, @@ -414,7 +415,7 @@ "title": "Extract Images", "desc": "Extracts all images from a PDF and saves them to zip" }, - "ScannerImageSplit": { + "scannerImageSplit": { "title": "Detect/Split Scanned photos", "desc": "Splits multiple photos from within a photo/PDF" }, @@ -458,15 +459,11 @@ "title": "Adjust page size/scale", "desc": "Change the size/scale of a page and/or its contents." }, - "pipeline": { - "title": "Pipeline", - "desc": "Run multiple actions on PDFs by defining pipeline scripts" - }, "addPageNumbers": { "title": "Add Page Numbers", "desc": "Add Page numbers throughout a document in a set location" }, - "auto-rename": { + "autoRename": { "title": "Auto Rename PDF File", "desc": "Auto renames a PDF file based on its detected header" }, @@ -502,15 +499,15 @@ "title": "Redact", "desc": "Redacts (blacks out) a PDF based on selected text, drawn shapes and/or selected page(s)" }, - "overlay-pdfs": { + "overlayPdfs": { "title": "Overlay PDFs", "desc": "Overlays PDFs on-top of another PDF" }, - "split-by-sections": { + "splitBySections": { "title": "Split PDF by Sections", "desc": "Divide each page of a PDF into smaller horizontal and vertical sections" }, - "AddStampRequest": { + "addStamp": { "title": "Add Stamp to PDF", "desc": "Add text or add image stamps at set locations" }, @@ -530,10 +527,6 @@ "title": "API Documentation", "desc": "View API documentation and test endpoints" }, - "replace-color": { - "title": "Advanced Colour options", - "desc": "Replace colour for text and background in PDF and invert full colour of pdf to reduce file size" - }, "fakeScan": { "title": "Fake Scan", "desc": "Create a PDF that looks like it was scanned" @@ -562,18 +555,10 @@ "title": "Remove Pages", "desc": "Remove specific pages from a PDF document" }, - "removeImagePdf": { - "title": "Remove Image", - "desc": "Remove images from PDF documents" - }, "autoSizeSplitPDF": { "title": "Auto Split by Size/Count", "desc": "Automatically split PDFs by file size or page count" }, - "adjust-contrast": { - "title": "Adjust Colours/Contrast", - "desc": "Adjust colours and contrast of PDF documents" - }, "replaceColorPdf": { "title": "Replace & Invert Colour", "desc": "Replace or invert colours in PDF documents" diff --git a/frontend/src/components/fileManager/CompactFileDetails.tsx b/frontend/src/components/fileManager/CompactFileDetails.tsx index fac16bb20..3656acee6 100644 --- a/frontend/src/components/fileManager/CompactFileDetails.tsx +++ b/frontend/src/components/fileManager/CompactFileDetails.tsx @@ -41,29 +41,29 @@ const CompactFileDetails: React.FC = ({ {/* Small preview */} {currentFile && thumbnail ? ( - {currentFile.name} ) : currentFile ? ( -
) : null}
- + {/* File info */} @@ -82,11 +82,11 @@ const CompactFileDetails: React.FC = ({ {/* Compact tool chain for mobile */} {currentFile?.toolHistory && currentFile.toolHistory.length > 0 && ( - {currentFile.toolHistory.map((tool: any) => tool.toolName).join(' → ')} + {currentFile.toolHistory.map((tool) => t(`home.${tool.toolId}.title`, tool.toolId)).join(' → ')} )} - + {/* Navigation arrows for multiple files */} {hasMultipleFiles && ( @@ -109,19 +109,19 @@ const CompactFileDetails: React.FC = ({ )} - + {/* Action Button */} - + + ); +}; + +const RippleStyles: React.FC = () => ( + +); + +// Main component +const LanguageSelector: React.FC = ({ position = 'bottom-start', offset = 8, compact = false }) => { const { i18n } = useTranslation(); const [opened, setOpened] = useState(false); const [animationTriggered, setAnimationTriggered] = useState(false); const [pendingLanguage, setPendingLanguage] = useState(null); - const [rippleEffect, setRippleEffect] = useState<{x: number, y: number, key: number} | null>(null); + const [rippleEffect, setRippleEffect] = useState(null); - const languageOptions = Object.entries(supportedLanguages) + const languageOptions: LanguageOption[] = Object.entries(supportedLanguages) .sort(([, nameA], [, nameB]) => nameA.localeCompare(nameB)) .map(([code, name]) => ({ value: code, @@ -65,15 +202,7 @@ const LanguageSelector = ({ position = 'bottom-start', offset = 8, compact = fal return ( <> - + - - {compact ? ( - + {compact ? ( + - - - ) : ( - - )} - + }} + > + + + ) : ( + + )} + - - -
- {languageOptions.map((option, index) => ( -
- -
- ))} -
-
-
+ + +
+ {languageOptions.map((option, index) => { + const isEnglishGB = option.value === 'en-GB'; // Currently only English GB has enough translations to use + const isDisabled = !isEnglishGB; + + return ( + handleLanguageChange(option.value, event)} + rippleEffect={rippleEffect} + pendingLanguage={pendingLanguage} + compact={compact} + disabled={isDisabled} + /> + ); + })} +
+
+
); }; export default LanguageSelector; +export type { LanguageSelectorProps, LanguageOption, RippleEffect }; diff --git a/frontend/src/components/shared/ToolChain.tsx b/frontend/src/components/shared/ToolChain.tsx index 5149bd776..b87b891a2 100644 --- a/frontend/src/components/shared/ToolChain.tsx +++ b/frontend/src/components/shared/ToolChain.tsx @@ -6,6 +6,8 @@ import React from 'react'; import { Text, Tooltip, Badge, Group } from '@mantine/core'; import { ToolOperation } from '../../types/file'; +import { useTranslation } from 'react-i18next'; +import { ToolId } from '../../types/toolId'; interface ToolChainProps { toolChain: ToolOperation[]; @@ -24,15 +26,21 @@ const ToolChain: React.FC = ({ }) => { if (!toolChain || toolChain.length === 0) return null; - const toolNames = toolChain.map(tool => tool.toolName); + const { t } = useTranslation(); + + const toolIds = toolChain.map(tool => tool.toolId); + + const getToolName = (toolId: ToolId) => { + return t(`home.${toolId}.title`, toolId); + } // Create full tool chain for tooltip const fullChainDisplay = displayStyle === 'badges' ? ( {toolChain.map((tool, index) => ( - + - {tool.toolName} + {getToolName(tool.toolId)} {index < toolChain.length - 1 && ( @@ -41,19 +49,19 @@ const ToolChain: React.FC = ({ ))} ) : ( - {toolNames.join(' → ')} + {toolIds.map(getToolName).join(' → ')} ); // Create truncated display based on available space const getTruncatedDisplay = () => { - if (toolNames.length <= 2) { + if (toolIds.length <= 2) { // Show all tools if 2 or fewer - return { text: toolNames.join(' → '), isTruncated: false }; + return { text: toolIds.map(getToolName).join(' → '), isTruncated: false }; } else { // Show first tool ... last tool for longer chains return { - text: `${toolNames[0]} → +${toolNames.length-2} → ${toolNames[toolNames.length - 1]}`, - isTruncated: true + text: `${getToolName(toolIds[0])} → +${toolIds.length-2} → ${getToolName(toolIds[toolIds.length - 1])}`, + isTruncated: true, }; } }; @@ -62,8 +70,8 @@ const ToolChain: React.FC = ({ // Compact style for very small spaces if (displayStyle === 'compact') { - const compactText = toolNames.length === 1 ? toolNames[0] : `${toolNames.length} tools`; - const isCompactTruncated = toolNames.length > 1; + const compactText = toolIds.length === 1 ? getToolName(toolIds[0]) : `${toolIds.length} tools`; + const isCompactTruncated = toolIds.length > 1; const compactElement = ( = ({
{toolChain.slice(0, 3).map((tool, index) => ( - + - {tool.toolName} + {getToolName(tool.toolId)} {index < Math.min(toolChain.length - 1, 2) && ( @@ -110,7 +118,7 @@ const ToolChain: React.FC = ({ <> ... - {toolChain[toolChain.length - 1].toolName} + {getToolName(toolChain[toolChain.length - 1].toolId)} )} @@ -119,7 +127,7 @@ const ToolChain: React.FC = ({ ); return isBadgesTruncated ? ( - + {badgesElement} ) : badgesElement; diff --git a/frontend/src/contexts/file/fileActions.ts b/frontend/src/contexts/file/fileActions.ts index 7903ec8a1..5c80d10b3 100644 --- a/frontend/src/contexts/file/fileActions.ts +++ b/frontend/src/contexts/file/fileActions.ts @@ -12,7 +12,7 @@ import { createStirlingFile, ProcessedFileMetadata, } from '../../types/fileContext'; -import { FileId } from '../../types/file'; +import { FileId, ToolOperation } from '../../types/file'; import { generateThumbnailWithMetadata } from '../../utils/thumbnailUtils'; import { FileLifecycleManager } from './lifecycle'; import { buildQuickKeySet } from './fileSelectors'; @@ -104,7 +104,7 @@ export async function generateProcessedFileMetadata(file: File): Promise, name: t("home.watermark.title", "Add Watermark"), component: AddWatermark, @@ -200,11 +200,11 @@ export function useFlatToolRegistry(): ToolRegistry { operationConfig: addWatermarkOperationConfig, settingsComponent: AddWatermarkSingleStepSettings, }, - "add-stamp": { + addStamp: { icon: , - name: t("home.AddStampRequest.title", "Add Stamp to PDF"), + name: t("home.addStamp.title", "Add Stamp to PDF"), component: null, - description: t("home.AddStampRequest.desc", "Add text or add image stamps at set locations"), + description: t("home.addStamp.desc", "Add text or add image stamps at set locations"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.DOCUMENT_SECURITY, }, @@ -232,7 +232,7 @@ export function useFlatToolRegistry(): ToolRegistry { operationConfig: flattenOperationConfig, settingsComponent: FlattenSettings, }, - "unlock-pdf-forms": { + unlockPDFForms: { icon: , name: t("home.unlockPDFForms.title", "Unlock PDF Forms"), component: UnlockPdfForms, @@ -244,7 +244,7 @@ export function useFlatToolRegistry(): ToolRegistry { operationConfig: unlockPdfFormsOperationConfig, settingsComponent: UnlockPdfFormsSettings, }, - "manage-certificates": { + manageCertificates: { icon: , name: t("home.manageCertificates.title", "Manage Certificates"), component: null, @@ -255,7 +255,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.DOCUMENT_SECURITY, }, - "change-permissions": { + changePermissions: { icon: , name: t("home.changePermissions.title", "Change Permissions"), component: ChangePermissions, @@ -269,7 +269,7 @@ export function useFlatToolRegistry(): ToolRegistry { }, // Verification - "get-all-info-on-pdf": { + getPdfInfo: { icon: , name: t("home.getPdfInfo.title", "Get ALL Info on PDF"), component: null, @@ -277,7 +277,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.VERIFICATION, }, - "validate-pdf-signature": { + validateSignature: { icon: , name: t("home.validateSignature.title", "Validate PDF Signature"), component: null, @@ -300,7 +300,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.DOCUMENT_REVIEW, }, - "change-metadata": { + changeMetadata: { icon: , name: t("home.changeMetadata.title", "Change Metadata"), component: ChangeMetadata, @@ -314,7 +314,7 @@ export function useFlatToolRegistry(): ToolRegistry { }, // Page Formatting - cropPdf: { + crop: { icon: , name: t("home.crop.title", "Crop PDF"), component: Crop, @@ -348,7 +348,7 @@ export function useFlatToolRegistry(): ToolRegistry { operationConfig: splitOperationConfig, settingsComponent: SplitSettings, }, - "reorganize-pages": { + reorganizePages: { icon: , name: t("home.reorganizePages.title", "Reorganize Pages"), component: null, @@ -360,7 +360,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.PAGE_FORMATTING, }, - "adjust-page-size-scale": { + scalePages: { icon: , name: t("home.scalePages.title", "Adjust page size/scale"), component: AdjustPageScale, @@ -381,7 +381,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.PAGE_FORMATTING, }, - "multi-page-layout": { + pageLayout: { icon: , name: t("home.pageLayout.title", "Multi-Page Layout"), component: null, @@ -390,7 +390,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.PAGE_FORMATTING, }, - "single-large-page": { + pdfToSinglePage: { icon: , name: t("home.pdfToSinglePage.title", "PDF to Single Large Page"), component: SingleLargePage, @@ -403,19 +403,19 @@ export function useFlatToolRegistry(): ToolRegistry { endpoints: ["pdf-to-single-page"], operationConfig: singleLargePageOperationConfig, }, - "add-attachments": { + addAttachments: { icon: , - name: t("home.attachments.title", "Add Attachments"), + name: t("home.addAttachments.title", "Add Attachments"), component: null, - description: t("home.attachments.desc", "Add or remove embedded files (attachments) to/from a PDF"), + description: t("home.addAttachments.desc", "Add or remove embedded files (attachments) to/from a PDF"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.PAGE_FORMATTING, }, // Extraction - "extract-page": { + extractPages: { icon: , name: t("home.extractPages.title", "Extract Pages"), component: null, @@ -423,7 +423,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.EXTRACTION, }, - "extract-images": { + extractImages: { icon: , name: t("home.extractImages.title", "Extract Images"), component: null, @@ -444,7 +444,7 @@ export function useFlatToolRegistry(): ToolRegistry { maxFiles: 1, endpoints: ["remove-pages"], }, - "remove-blank-pages": { + removeBlanks: { icon: , name: t("home.removeBlanks.title", "Remove Blank Pages"), component: RemoveBlanks, @@ -454,7 +454,7 @@ export function useFlatToolRegistry(): ToolRegistry { maxFiles: 1, endpoints: ["remove-blanks"], }, - "remove-annotations": { + removeAnnotations: { icon: , name: t("home.removeAnnotations.title", "Remove Annotations"), component: null, @@ -462,15 +462,15 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.REMOVAL, }, - "remove-image": { + removeImage: { icon: , - name: t("home.removeImagePdf.title", "Remove Image"), + name: t("home.removeImage.title", "Remove Image"), component: null, - description: t("home.removeImagePdf.desc", "Remove images from PDF documents"), + description: t("home.removeImage.desc", "Remove images from PDF documents"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.REMOVAL, }, - "remove-password": { + removePassword: { icon: , name: t("home.removePassword.title", "Remove Password"), component: RemovePassword, @@ -482,7 +482,7 @@ export function useFlatToolRegistry(): ToolRegistry { operationConfig: removePasswordOperationConfig, settingsComponent: RemovePasswordSettings, }, - "remove-certificate-sign": { + removeCertSign: { icon: , name: t("home.removeCertSign.title", "Remove Certificate Sign"), component: RemoveCertificateSign, @@ -510,18 +510,18 @@ export function useFlatToolRegistry(): ToolRegistry { supportedFormats: CONVERT_SUPPORTED_FORMATS, endpoints: ["handleData"], }, - "auto-rename-pdf-file": { + autoRename: { icon: , - name: t("home.auto-rename.title", "Auto Rename PDF File"), + name: t("home.autoRename.title", "Auto Rename PDF File"), component: AutoRename, maxFiles: -1, endpoints: ["remove-certificate-sign"], operationConfig: autoRenameOperationConfig, - description: t("home.auto-rename.desc", "Automatically rename PDF files based on their content"), + description: t("home.autoRename.desc", "Automatically rename PDF files based on their content"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.AUTOMATION, }, - "auto-split-pages": { + autoSplitPDF: { icon: , name: t("home.autoSplitPDF.title", "Auto Split Pages"), component: null, @@ -529,7 +529,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.AUTOMATION, }, - "auto-split-by-size-count": { + autoSizeSplitPDF: { icon: , name: t("home.autoSizeSplitPDF.title", "Auto Split by Size/Count"), component: null, @@ -540,7 +540,7 @@ export function useFlatToolRegistry(): ToolRegistry { // Advanced Formatting - "adjust-contrast": { + adjustContrast: { icon: , name: t("home.adjustContrast.title", "Adjust Colors/Contrast"), component: null, @@ -560,23 +560,23 @@ export function useFlatToolRegistry(): ToolRegistry { operationConfig: repairOperationConfig, settingsComponent: RepairSettings, }, - "detect-split-scanned-photos": { + scannerImageSplit: { icon: , - name: t("home.ScannerImageSplit.title", "Detect & Split Scanned Photos"), + name: t("home.scannerImageSplit.title", "Detect & Split Scanned Photos"), component: null, - description: t("home.ScannerImageSplit.desc", "Detect and split scanned photos into separate pages"), + description: t("home.scannerImageSplit.desc", "Detect and split scanned photos into separate pages"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.ADVANCED_FORMATTING, }, - "overlay-pdfs": { + overlayPdfs: { icon: , - name: t("home.overlay-pdfs.title", "Overlay PDFs"), + name: t("home.overlayPdfs.title", "Overlay PDFs"), component: null, - description: t("home.overlay-pdfs.desc", "Overlay one PDF on top of another"), + description: t("home.overlayPdfs.desc", "Overlay one PDF on top of another"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.ADVANCED_FORMATTING, }, - "replace-and-invert-color": { + replaceColorPdf: { icon: , name: t("home.replaceColorPdf.title", "Replace & Invert Color"), component: null, @@ -584,7 +584,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.ADVANCED_FORMATTING, }, - "add-image": { + addImage: { icon: , name: t("home.addImage.title", "Add Image"), component: null, @@ -592,7 +592,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.ADVANCED_FORMATTING, }, - "edit-table-of-contents": { + editTableOfContents: { icon: , name: t("home.editTableOfContents.title", "Edit Table of Contents"), component: null, @@ -600,7 +600,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.ADVANCED_FORMATTING, }, - "scanner-effect": { + fakeScan: { icon: , name: t("home.fakeScan.title", "Scanner Effect"), component: null, @@ -611,7 +611,7 @@ export function useFlatToolRegistry(): ToolRegistry { // Developer Tools - "show-javascript": { + showJS: { icon: , name: t("home.showJS.title", "Show JavaScript"), component: null, @@ -619,7 +619,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.DEVELOPER_TOOLS, }, - "dev-api": { + devApi: { icon: , name: t("home.devApi.title", "API"), component: null, @@ -628,7 +628,7 @@ export function useFlatToolRegistry(): ToolRegistry { subcategoryId: SubcategoryId.DEVELOPER_TOOLS, link: "https://stirlingpdf.io/swagger-ui/5.21.0/index.html", }, - "dev-folder-scanning": { + devFolderScanning: { icon: , name: t("home.devFolderScanning.title", "Automated Folder Scanning"), component: null, @@ -637,7 +637,7 @@ export function useFlatToolRegistry(): ToolRegistry { subcategoryId: SubcategoryId.DEVELOPER_TOOLS, link: "https://docs.stirlingpdf.com/Advanced%20Configuration/Folder%20Scanning/", }, - "dev-sso-guide": { + devSsoGuide: { icon: , name: t("home.devSsoGuide.title", "SSO Guide"), component: null, @@ -646,7 +646,7 @@ export function useFlatToolRegistry(): ToolRegistry { subcategoryId: SubcategoryId.DEVELOPER_TOOLS, link: "https://docs.stirlingpdf.com/Advanced%20Configuration/Single%20Sign-On%20Configuration", }, - "dev-airgapped": { + devAirgapped: { icon: , name: t("home.devAirgapped.title", "Air-gapped Setup"), component: null, @@ -705,7 +705,7 @@ export function useFlatToolRegistry(): ToolRegistry { operationConfig: convertOperationConfig, settingsComponent: ConvertSettings, }, - mergePdfs: { + merge: { icon: , name: t("home.merge.title", "Merge"), component: Merge, @@ -717,7 +717,7 @@ export function useFlatToolRegistry(): ToolRegistry { operationConfig: mergeOperationConfig, settingsComponent: MergeSettings }, - "multi-tool": { + multiTool: { icon: , name: t("home.multiTool.title", "Multi-Tool"), component: null, diff --git a/frontend/src/hooks/tools/adjustPageScale/useAdjustPageScaleOperation.ts b/frontend/src/hooks/tools/adjustPageScale/useAdjustPageScaleOperation.ts index 3d3ae3280..458e7fda1 100644 --- a/frontend/src/hooks/tools/adjustPageScale/useAdjustPageScaleOperation.ts +++ b/frontend/src/hooks/tools/adjustPageScale/useAdjustPageScaleOperation.ts @@ -14,7 +14,7 @@ export const buildAdjustPageScaleFormData = (parameters: AdjustPageScaleParamete export const adjustPageScaleOperationConfig = { toolType: ToolType.singleFile, buildFormData: buildAdjustPageScaleFormData, - operationType: 'adjustPageScale', + operationType: 'scalePages', endpoint: '/api/v1/general/scale-pages', defaultParameters, } as const; diff --git a/frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.test.ts b/frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.test.ts index fa942d2aa..b85f5533f 100644 --- a/frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.test.ts +++ b/frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.test.ts @@ -113,7 +113,7 @@ describe('useChangePermissionsOperation', () => { test.each([ { property: 'toolType' as const, expectedValue: ToolType.singleFile }, { property: 'endpoint' as const, expectedValue: '/api/v1/security/add-password' }, - { property: 'operationType' as const, expectedValue: 'change-permissions' } + { property: 'operationType' as const, expectedValue: 'changePermissions' } ])('should configure $property correctly', ({ property, expectedValue }) => { renderHook(() => useChangePermissionsOperation()); diff --git a/frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.ts b/frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.ts index 30feb3d25..89b6c07d8 100644 --- a/frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.ts +++ b/frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.ts @@ -26,7 +26,7 @@ export const buildChangePermissionsFormData = (parameters: ChangePermissionsPara export const changePermissionsOperationConfig = { toolType: ToolType.singleFile, buildFormData: buildChangePermissionsFormData, - operationType: 'change-permissions', + operationType: 'changePermissions', endpoint: '/api/v1/security/add-password', // Change Permissions is a fake endpoint for the Add Password tool defaultParameters, } as const; diff --git a/frontend/src/hooks/tools/removeBlanks/useRemoveBlanksOperation.ts b/frontend/src/hooks/tools/removeBlanks/useRemoveBlanksOperation.ts index 479132d6b..15cfe1724 100644 --- a/frontend/src/hooks/tools/removeBlanks/useRemoveBlanksOperation.ts +++ b/frontend/src/hooks/tools/removeBlanks/useRemoveBlanksOperation.ts @@ -17,7 +17,7 @@ export const buildRemoveBlanksFormData = (parameters: RemoveBlanksParameters, fi export const removeBlanksOperationConfig = { toolType: ToolType.singleFile, buildFormData: buildRemoveBlanksFormData, - operationType: 'remove-blanks', + operationType: 'removeBlanks', endpoint: '/api/v1/misc/remove-blanks', defaultParameters, } as const satisfies ToolOperationConfig; diff --git a/frontend/src/hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation.ts b/frontend/src/hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation.ts index 84aa9da3d..48ade3940 100644 --- a/frontend/src/hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation.ts +++ b/frontend/src/hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation.ts @@ -14,7 +14,7 @@ export const buildRemoveCertificateSignFormData = (_parameters: RemoveCertificat export const removeCertificateSignOperationConfig = { toolType: ToolType.singleFile, buildFormData: buildRemoveCertificateSignFormData, - operationType: 'remove-certificate-sign', + operationType: 'removeCertSign', endpoint: '/api/v1/security/remove-cert-sign', defaultParameters, } as const; diff --git a/frontend/src/hooks/tools/removePages/useRemovePagesOperation.ts b/frontend/src/hooks/tools/removePages/useRemovePagesOperation.ts index 95296fd07..aa9f5d574 100644 --- a/frontend/src/hooks/tools/removePages/useRemovePagesOperation.ts +++ b/frontend/src/hooks/tools/removePages/useRemovePagesOperation.ts @@ -15,7 +15,7 @@ export const buildRemovePagesFormData = (parameters: RemovePagesParameters, file export const removePagesOperationConfig = { toolType: ToolType.singleFile, buildFormData: buildRemovePagesFormData, - operationType: 'remove-pages', + operationType: 'removePages', endpoint: '/api/v1/general/remove-pages', defaultParameters, } as const satisfies ToolOperationConfig; diff --git a/frontend/src/hooks/tools/shared/useToolOperation.ts b/frontend/src/hooks/tools/shared/useToolOperation.ts index 0b7ba75b6..7735dd1a4 100644 --- a/frontend/src/hooks/tools/shared/useToolOperation.ts +++ b/frontend/src/hooks/tools/shared/useToolOperation.ts @@ -9,6 +9,8 @@ import { extractErrorMessage } from '../../../utils/toolErrorHandler'; import { StirlingFile, extractFiles, FileId, StirlingFileStub, createStirlingFile, createNewStirlingFileStub } from '../../../types/fileContext'; import { ResponseHandler } from '../../../utils/toolResponseProcessor'; import { createChildStub, generateProcessedFileMetadata } from '../../../contexts/file/fileActions'; +import { ToolOperation } from '../../../types/file'; +import { ToolId } from '../../../types/toolId'; // Re-export for backwards compatibility export type { ProcessingProgress, ResponseHandler }; @@ -29,7 +31,7 @@ export enum ToolType { */ interface BaseToolOperationConfig { /** Operation identifier for tracking and logging */ - operationType: string; + operationType: ToolId; /** * Prefix added to processed filenames (e.g., 'compressed_', 'split_'). @@ -274,8 +276,8 @@ export const useToolOperation = ( } // Create new tool operation - const newToolOperation = { - toolName: config.operationType, + const newToolOperation: ToolOperation = { + toolId: config.operationType, timestamp: Date.now() }; diff --git a/frontend/src/hooks/tools/singleLargePage/useSingleLargePageOperation.ts b/frontend/src/hooks/tools/singleLargePage/useSingleLargePageOperation.ts index 41a27a138..ab51c0cc4 100644 --- a/frontend/src/hooks/tools/singleLargePage/useSingleLargePageOperation.ts +++ b/frontend/src/hooks/tools/singleLargePage/useSingleLargePageOperation.ts @@ -14,7 +14,7 @@ export const buildSingleLargePageFormData = (_parameters: SingleLargePageParamet export const singleLargePageOperationConfig = { toolType: ToolType.singleFile, buildFormData: buildSingleLargePageFormData, - operationType: 'single-large-page', + operationType: 'pdfToSinglePage', endpoint: '/api/v1/general/pdf-to-single-page', defaultParameters, } as const; diff --git a/frontend/src/hooks/tools/split/useSplitOperation.ts b/frontend/src/hooks/tools/split/useSplitOperation.ts index 43b177edf..955149868 100644 --- a/frontend/src/hooks/tools/split/useSplitOperation.ts +++ b/frontend/src/hooks/tools/split/useSplitOperation.ts @@ -71,7 +71,7 @@ export const getSplitEndpoint = (parameters: SplitParameters): string => { export const splitOperationConfig = { toolType: ToolType.singleFile, buildFormData: buildSplitFormData, - operationType: 'splitPdf', + operationType: 'split', endpoint: getSplitEndpoint, defaultParameters, } as const; diff --git a/frontend/src/hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation.ts b/frontend/src/hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation.ts index 9d24a82ab..c60375a94 100644 --- a/frontend/src/hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation.ts +++ b/frontend/src/hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation.ts @@ -14,7 +14,7 @@ export const buildUnlockPdfFormsFormData = (_parameters: UnlockPdfFormsParameter export const unlockPdfFormsOperationConfig = { toolType: ToolType.singleFile, buildFormData: buildUnlockPdfFormsFormData, - operationType: 'unlock-pdf-forms', + operationType: 'unlockPDFForms', endpoint: '/api/v1/misc/unlock-pdf-forms', defaultParameters, } as const; diff --git a/frontend/src/types/file.ts b/frontend/src/types/file.ts index edbc4b364..7fb8d7132 100644 --- a/frontend/src/types/file.ts +++ b/frontend/src/types/file.ts @@ -3,6 +3,8 @@ * FileContext uses pure File objects with separate ID tracking */ +import { ToolId } from "./toolId"; + declare const tag: unique symbol; export type FileId = string & { readonly [tag]: 'FileId' }; @@ -11,7 +13,7 @@ export type FileId = string & { readonly [tag]: 'FileId' }; * Note: Parameters removed for security - sensitive data like passwords should not be stored in history */ export interface ToolOperation { - toolName: string; + toolId: ToolId; timestamp: number; } @@ -32,9 +34,5 @@ export interface BaseFileMetadata { originalFileId: string; // Root file ID for grouping versions versionNumber: number; // Version number in chain parentFileId?: FileId; // Immediate parent file ID - toolHistory?: Array<{ - toolName: string; - timestamp: number; - }>; // Tool chain for history tracking - + toolHistory?: ToolOperation[]; // Tool chain for history tracking } diff --git a/frontend/src/types/toolId.ts b/frontend/src/types/toolId.ts index be38bdf37..1877297e0 100644 --- a/frontend/src/types/toolId.ts +++ b/frontend/src/types/toolId.ts @@ -1,19 +1,60 @@ // Define all possible tool IDs as source of truth const TOOL_IDS = [ - 'certSign', 'sign', 'addPassword', 'remove-password', 'removePages', 'remove-blank-pages', 'remove-annotations', 'remove-image', - 'change-permissions', 'addWatermark', - 'sanitize', 'auto-split-pages', 'auto-split-by-size-count', 'split', 'mergePdfs', - 'convert', 'ocr', 'add-image', 'rotate', - 'detect-split-scanned-photos', - 'edit-table-of-contents', - 'scanner-effect', - 'auto-rename-pdf-file', 'multi-page-layout', 'adjust-page-size-scale', 'adjust-contrast', 'cropPdf', 'single-large-page', 'multi-tool', - 'repair', 'compare', 'addPageNumbers', 'redact', - 'flatten', 'remove-certificate-sign', - 'unlock-pdf-forms', 'compress', 'extract-page', 'reorganize-pages', 'extract-images', - 'add-stamp', 'add-attachments', 'change-metadata', 'overlay-pdfs', - 'manage-certificates', 'get-all-info-on-pdf', 'validate-pdf-signature', 'read', 'automate', 'replace-and-invert-color', - 'show-javascript', 'dev-api', 'dev-folder-scanning', 'dev-sso-guide', 'dev-airgapped' + 'certSign', + 'sign', + 'addPassword', + 'removePassword', + 'removePages', + 'removeBlanks', + 'removeAnnotations', + 'removeImage', + 'changePermissions', + 'watermark', + 'sanitize', + 'autoSplitPDF', + 'autoSizeSplitPDF', + 'split', + 'merge', + 'convert', + 'ocr', + 'addImage', + 'rotate', + 'scannerImageSplit', + 'editTableOfContents', + 'fakeScan', + 'autoRename', + 'pageLayout', + 'scalePages', + 'adjustContrast', + 'crop', + 'pdfToSinglePage', + 'multiTool', + 'repair', + 'compare', + 'addPageNumbers', + 'redact', + 'flatten', + 'removeCertSign', + 'unlockPDFForms', + 'compress', + 'extractPages', + 'reorganizePages', + 'extractImages', + 'addStamp', + 'addAttachments', + 'changeMetadata', + 'overlayPdfs', + 'manageCertificates', + 'getPdfInfo', + 'validateSignature', + 'read', + 'automate', + 'replaceColorPdf', + 'showJS', + 'devApi', + 'devFolderScanning', + 'devSsoGuide', + 'devAirgapped', ] as const; // Tool identity - what PDF operation we're performing (type-safe) diff --git a/frontend/src/utils/urlMapping.ts b/frontend/src/utils/urlMapping.ts index 918be3a1e..2fab4282d 100644 --- a/frontend/src/utils/urlMapping.ts +++ b/frontend/src/utils/urlMapping.ts @@ -4,7 +4,7 @@ import { ToolId } from '../types/toolId'; export const URL_TO_TOOL_MAP: Record = { '/split-pdfs': 'split', '/split': 'split', - '/merge-pdfs': 'mergePdfs', + '/merge-pdfs': 'merge', '/compress-pdf': 'compress', '/convert': 'convert', '/convert-pdf': 'convert', @@ -19,16 +19,16 @@ export const URL_TO_TOOL_MAP: Record = { '/pdf-to-word': 'convert', '/pdf-to-xml': 'convert', '/add-password': 'addPassword', - '/change-permissions': 'change-permissions', + '/change-permissions': 'changePermissions', '/sanitize-pdf': 'sanitize', '/ocr': 'ocr', '/ocr-pdf': 'ocr', - '/add-watermark': 'addWatermark', - '/remove-password': 'remove-password', - '/single-large-page': 'single-large-page', + '/add-watermark': 'watermark', + '/remove-password': 'removePassword', + '/single-large-page': 'pdfToSinglePage', '/repair': 'repair', '/rotate-pdf': 'rotate', - '/unlock-pdf-forms': 'unlock-pdf-forms', - '/remove-certificate-sign': 'remove-certificate-sign', - '/remove-cert-sign': 'remove-certificate-sign' + '/unlock-pdf-forms': 'unlockPDFForms', + '/remove-certificate-sign': 'removeCertSign', + '/remove-cert-sign': 'removeCertSign', };