Skip to content

Conversation

@spbolton
Copy link
Contributor

@spbolton spbolton commented Jul 15, 2025

Summary

Progressive implementation of Swagger/OpenAPI annotations for REST endpoints - Batch 3

This PR adds comprehensive Swagger annotations to 14 REST resource classes focused on site architecture, templates, and file management APIs.

⚠️ IMPORTANT: Batch Rollout Process

This PR is part of a progressive 8-batch rollout strategy.

  • Batch 1: Must be merged first
  • 🔄 Batch 2: Must be merged before this PR
  • 🔄 Batch 3: Remove draft state ONLY after Batch 2 is merged (this PR)
  • Batch 4-8: Keep in draft until previous batch is merged
  • Batch 9: Keep in draft until Batch 8 is merged

⚠️ Do not remove draft state from this PR until Batch 2 (#32657) has been successfully merged.

Batch 3: Site Architecture & Templates (14 classes)

Theme: Site structure, templates, and file management APIs

Site & Page Resources (3 classes)

  • SiteResource - Site management
  • PageResource - Page management
  • NavResource - Navigation management

Template & Container Resources (3 classes)

  • TemplateResource - Template management
  • ContainerResource - Container management
  • ThemeResource - Theme management

File & Asset Management (3 classes)

  • FolderResource - Folder management
  • FileAssetsResource - File asset handling
  • WebAssetResource - Web asset management

Browser & Navigation (3 classes)

  • BrowserResource - File browser
  • BrowserTreeResource - Browser tree view
  • TempFileResource - Temporary file handling

Variants & Versioning (2 classes)

  • VariantResource - Content variants
  • VersionableResource - Version management

Testing

Progressive testing approach using the @SwaggerCompliant annotation system:

# Test Batches 1-3 (cumulative)
./mvnw test -pl :dotcms-core -Dtest=RestEndpointAnnotationComplianceTest -Dtest.batch.max=3

# Test annotation validation
./mvnw test -pl :dotcms-core -Dtest=RestEndpointAnnotationValidationTest -Dtest.batch.max=3

Impact

  • ✅ Improves API documentation for site architecture workflows
  • ✅ Enables better developer experience with template and asset APIs
  • ✅ Maintains backward compatibility
  • ✅ Follows established annotation patterns and standards

Dependencies

🤖 Generated with Claude Code

Co-Authored-By: Claude [email protected]

@semgrep-code-dotcms-test
Copy link

Semgrep found 1 spring-tainted-path-traversal finding:

  • dotCMS/src/main/java/com/dotcms/rest/ContentResource.java

The application builds a file path from potentially untrusted data, which can lead to a path traversal vulnerability. An attacker can manipulate the path which the application uses to access files. If the application does not validate user input and sanitize file paths, sensitive files such as configuration or user data can be accessed, potentially creating or overwriting files. To prevent this vulnerability, validate and sanitize any input that is used to create references to file paths. Also, enforce strict file access controls. For example, choose privileges allowing public-facing applications to access only the required files. In Java, you may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path.

View Dataflow Graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>dotCMS/src/main/java/com/dotcms/rest/ContentResource.java</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1362 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1362] multipart</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1362 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1362] multipart</a>"]

            v3["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1366 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1366] multipartPUTandPOST</a>"]

            v4["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1415 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1415] multipart</a>"]

            v5["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1430 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1430] part</a>"]

            v6["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1430 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1430] part</a>"]

            v7["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1510 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1510] processFile</a>"]

            v8["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1542 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1542] part</a>"]

            v9["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1545 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1545] badFileName</a>"]

            v10["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1546 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1546] filename</a>"]
        end
            v2 --> v3
            v3 --> v4
            v4 --> v5
            v5 --> v6
            v6 --> v7
            v7 --> v8
            v8 --> v9
            v9 --> v10
        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1561 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1561] tmpFolder.getAbsolutePath() + File.separator + filename</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    Traces0:::invis
    File0:::invis

    %% Connections

    Source --> Traces0
    Traces0 --> Sink

Loading

If this is a critical or high severity finding, please also link this issue in the #security channel in Slack.

Semgrep found 1 tainted-file-path finding:

Detected user input controlling a file path. An attacker could control the location of this file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path.

View Dataflow Graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>dotCMS/src/main/java/com/dotcms/rest/ContentResource.java</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1362 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1362] multipart</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1362 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1362] multipart</a>"]

            v3["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1366 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1366] multipartPUTandPOST</a>"]

            v4["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1415 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1415] multipart</a>"]

            v5["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1430 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1430] part</a>"]

            v6["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1430 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1430] part</a>"]

            v7["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1510 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1510] processFile</a>"]

            v8["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1542 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1542] part</a>"]

            v9["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1545 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1545] badFileName</a>"]

            v10["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1546 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1546] filename</a>"]
        end
            v2 --> v3
            v3 --> v4
            v4 --> v5
            v5 --> v6
            v6 --> v7
            v7 --> v8
            v8 --> v9
            v9 --> v10
        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/dotCMS/core/blob/2dc53b4c82247ea9a55c4cadfbfa1de20210c539/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1560 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1560] new File(<br>                    tmpFolder.getAbsolutePath() + File.separator + filename)</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    Traces0:::invis
    File0:::invis

    %% Connections

    Source --> Traces0
    Traces0 --> Sink

Loading

If this is a critical or high severity finding, please also link this issue in the #security channel in Slack.

spbolton and others added 8 commits July 23, 2025 15:09
- Modified SwaggerCompliantAnnotationTest to skip resources without @SwaggerCompliant
- Updated SwaggerCompliantBatchTest to handle missing annotations gracefully
- Enhanced RestEndpointAnnotationComplianceTest with better error handling
- Improved SwaggerCompliantCumulativeTest exception handling for class loading
- Tests now log warnings for unannotated resources instead of failing
- Supports progressive rollout where annotation infrastructure is introduced first

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Removed SwaggerCompliantCumulativeTest as it's not needed for progressive rollout
- Test was expecting specific batch counts that don't exist yet
- Simplified approach: only test what is actually annotated

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@spbolton spbolton force-pushed the issue-32529-batch-3 branch from 2dc53b4 to b55504d Compare July 24, 2025 13:32
github-merge-queue bot pushed a commit that referenced this pull request Jul 24, 2025
…32561)

## Summary
This PR establishes the progressive testing infrastructure for
Swagger/OpenAPI annotations implementation across 115 REST endpoints in
dotCMS.

***Note for reviewers.*** Most of the files in this PR add new view
classes that are not yet used in this PR but are added in preparation
and use of the individual Resource classes that we change in upcoming
batches. We do not need to deeply review these new classes at this time
as they will have no impact on functionality at this time.

In these batches we can also look at the openapi.yml that now gets
generated and included in the commit for any resource changes. In this
PR it confirms we are only changing and adding tag descriptions
providing the categories for the upcoming batch changes. The main part
of this PR is the additional test changes which are set to identify
using an annotation the upcoming changed resource files and will test
them when updated. In this PR these will essentially skip and do
nothing.

## 🎯 Progressive Rollout Strategy
This PR creates the foundation for a **9-batch progressive rollout** of
Swagger annotations. The annotations will be added incrementally to make
the large change manageable and allow for thorough testing at each
stage.

This first PR does not actually modify any or the resources. It provides
the testing framework that will pick up the updated resources when they
are added. It also adds a few underlying fixes and additional View
classes that will be used by the updated Resource classes when they are
added but on their own will have no impact.

## 🔧 Infrastructure Components

### 1. @SwaggerCompliant Annotation System
- **File**:
`dotCMS/src/main/java/com/dotcms/rest/annotation/SwaggerCompliant.java`
- **Purpose**: Marks REST resource classes that have been updated with
proper Swagger annotations
- **Features**: 
  - Batch numbering system (1-8)
  - Version tracking
  - Descriptive documentation

### 2. Progressive Testing Framework
- **Updated**: `RestEndpointAnnotationComplianceTest.java`
- **Updated**: `RestEndpointAnnotationValidationTest.java`
- **Feature**: Automatic class discovery based on `@SwaggerCompliant`
annotations
- **Benefit**: Tests automatically include newly annotated classes when
PRs are merged

### 3. Cumulative Testing Support
```bash
# Test only classes from batches 1-3 (cumulative)
./mvnw test -pl :dotcms-core -Dtest=RestEndpointAnnotationComplianceTest -Dtest.batch.max=3

# Test all annotated classes (when annotation is present)
./mvnw test -pl :dotcms-core -Dtest=RestEndpointAnnotationComplianceTest
```

## 📊 Batch Organization (115 REST Resources)

### Batch 1: Core Authentication & User Management (15 classes)
**PR**: [#32656](#32656) - **Ready
for review**
- Essential authentication and user management APIs
- Foundation for all other batches

### Batch 2: Content Management Core (14 classes)
**PR**: [#32657](#32657) - **Draft**
- Content CRUD operations, versioning, relationships
- Content types and field management

### Batch 3: Site Architecture & Templates (14 classes)
**PR**: [#32658](#32658) - **Draft**
- Site management, templates, containers
- File and asset management

### Batch 4: System Administration (15 classes)
**PR**: [#32659](#32659) - **Draft**
- System configuration and monitoring
- Infrastructure management

### Batch 5: Publishing & Distribution (13 classes)
**PR**: [#32660](#32660) - **Draft**
- Publishing workflows and bundle management
- Environment and maintenance operations

### Batch 6: Rules Engine & Business Logic (14 classes)
**PR**: [#32661](#32661) - **Draft**
- Rules engine components
- Business logic and application management

### Batch 7: Modern APIs & Specialized Services (17 classes)
**PR**: [#32662](#32662) - **Draft**
- AI services and modern APIs
- Specialized content and analytics

### Batch 8: Legacy & Utility Resources (13 classes)
**PR**: [#32663](#32663) - **Draft**
- Legacy APIs and utility functions
- Remaining miscellaneous resources

### Batch 9: Cleanup and Finalization
**PR**: [#32664](#32664) - **Draft**
- Remove temporary testing infrastructure
- Final cleanup and production readiness

## 🔄 Automatic Testing Integration

**Key Feature**: When annotations are added to REST resources, they
**automatically trigger testing** of those resources when the PRs are
merged.

- ✅ **Before annotation**: Resource is not tested by compliance tests
- ✅ **After annotation**: Resource is automatically discovered and
tested
- ✅ **Cumulative**: Tests run against all previously annotated resources
plus new ones

This ensures that:
1. No manual test configuration is needed
2. Tests grow organically as annotations are added
3. Full compliance is verified incrementally
4. No regression in previously annotated resources

## 📋 Rollout Process

### Phase 1: Foundation (This PR)
1. **Merge this PR first** - Establishes the infrastructure
2. Sets up progressive testing framework
3. Creates annotation system for batch management

### Phase 2: Progressive Rollout (Batches 1-8)
1. **Batch 1** (#32656) - Ready for review after this PR is merged
2. **Batch 2** (#32657) - Remove draft state ONLY after Batch 1 is
merged
3. **Batch 3** (#32658) - Remove draft state ONLY after Batch 2 is
merged
4. **Batch 4** (#32659) - Remove draft state ONLY after Batch 3 is
merged
5. **Batch 5** (#32660) - Remove draft state ONLY after Batch 4 is
merged
6. **Batch 6** (#32661) - Remove draft state ONLY after Batch 5 is
merged
7. **Batch 7** (#32662) - Remove draft state ONLY after Batch 6 is
merged
8. **Batch 8** (#32663) - Remove draft state ONLY after Batch 7 is
merged

### Phase 3: Finalization (Batch 9)
1. **Batch 9** (#32664) - Remove draft state ONLY after Batch 8 is
merged
2. Clean up temporary infrastructure
3. Complete the implementation

## 🧪 Testing Strategy

### During Rollout
Each batch PR includes comprehensive testing:
```bash
# Test cumulative batches (e.g., for Batch 3)
./mvnw test -pl :dotcms-core -Dtest=RestEndpointAnnotationComplianceTest -Dtest.batch.max=3
```

### After Completion
All tests run against all endpoints automatically:
```bash
# No batch filtering needed - all annotated resources tested
./mvnw test -pl :dotcms-core -Dtest=RestEndpointAnnotationComplianceTest
```

## 📝 Documentation

### Batch Documentation
- **File**: `SWAGGER_COMPLIANT_BATCHES.md`
- **Contains**: Detailed breakdown of all 115 resources across 8 batches
- **Usage**: Reference for understanding batch organization and testing

### Verification Tests
- **File**: `SwaggerCompliantAnnotationTest.java`
- **File**: `SwaggerCompliantBatchTest.java`
- **Purpose**: Validate annotation structure and batch organization

## 🎯 Benefits

1. **Manageable Change Size**: 115 resources split into 8 logical
batches
2. **Incremental Testing**: Tests automatically include new resources as
they're annotated
3. **Risk Reduction**: Progressive rollout allows for early detection of
issues
4. **Clear Dependencies**: Each batch builds on previous ones
5. **Automated Discovery**: No manual test configuration required

## ⚠️ Important Notes

- **Merge Order**: This PR must be merged before any batch PRs
- **Draft Management**: Batch PRs should remain in draft until
predecessor is merged
- **Testing**: Annotations automatically trigger testing when resources
are merged
- **Dependencies**: Each batch depends on all previous batches being
merged

## 🔗 Related PRs

| Batch | PR | Status | Dependencies |
|-------|----|---------|--------------| 
| Foundation | [#32561](#32561) |
**This PR** | None |
| Batch 1 | [#32656](#32656) | Ready
| This PR |
| Batch 2 | [#32657](#32657) | Draft
| Batch 1 |
| Batch 3 | [#32658](#32658) | Draft
| Batch 2 |
| Batch 4 | [#32659](#32659) | Draft
| Batch 3 |
| Batch 5 | [#32660](#32660) | Draft
| Batch 4 |
| Batch 6 | [#32661](#32661) | Draft
| Batch 5 |
| Batch 7 | [#32662](#32662) | Draft
| Batch 6 |
| Batch 8 | [#32663](#32663) | Draft
| Batch 7 |
| Batch 9 | [#32664](#32664) | Draft
| Batch 8 |

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>

---------

Co-authored-by: Claude <[email protected]>
@github-actions
Copy link

This PR is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.

@github-actions github-actions bot added the stale label Aug 24, 2025
@github-actions
Copy link

github-actions bot commented Sep 1, 2025

This PR was closed because it has been stalled with no activity.

@github-actions github-actions bot closed this Sep 1, 2025
@spbolton spbolton removed the stale label Sep 2, 2025
@spbolton spbolton reopened this Sep 2, 2025
@semgrep-code-dotcms-test
Copy link

Legal Risk

The following dependencies were released under a license that
has been flagged by your organization for consideration.

Recommendation

While merging is not directly blocked, it's best to pause and consider what it means to use this license before continuing. If you are unsure, reach out to your security team or Semgrep admin to address this issue.

EPL-2.0

MPL-2.0

@github-actions
Copy link

github-actions bot commented Oct 3, 2025

This PR is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.

@github-actions github-actions bot added the stale label Oct 3, 2025
@github-actions
Copy link

This PR was closed because it has been stalled with no activity.

@github-actions github-actions bot closed this Oct 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Swagger annotations to endpoints missing it

2 participants