Skip to content

feat(swagger): Add Swagger annotations to Batch 2 - Content Management Core#32657

Merged
jdcmsd merged 16 commits intomainfrom
issue-32529-batch-2
Mar 20, 2026
Merged

feat(swagger): Add Swagger annotations to Batch 2 - Content Management Core#32657
jdcmsd merged 16 commits intomainfrom
issue-32529-batch-2

Conversation

@spbolton
Copy link
Copy Markdown
Contributor

@spbolton spbolton commented Jul 15, 2025

Summary

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

This PR adds comprehensive Swagger annotations to 14 REST resource classes focused on primary content creation, editing, and 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: Remove draft state ONLY after Batch 1 is merged (this PR)
  • Batch 3-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 1 (#32656) has been successfully merged.

Batch 2: Content Management Core (14 classes)

Theme: Primary content creation, editing, and management APIs

Content Resources (6 classes)

  • ContentResource - Core content CRUD operations
  • ContentVersionResource - Content versioning
  • ContentRelationshipsResource - Content relationships
  • ContentReportResource - Content reporting
  • ResourceLinkResource - Resource linking
  • ContentImportResource - Content import functionality

Content Type Resources (4 classes)

  • ContentTypeResource - Content type management
  • FieldResource - Field management
  • FieldVariableResource - Field variable handling
  • FieldTypeResource - Field type definitions

Workflow Resources (1 class)

  • WorkflowResource - Workflow management

Categories & Tags (2 classes)

  • CategoriesResource - Category management
  • TagResource (v2) - Tag management

Legacy Content Resources (1 class)

  • ContentResource (legacy) - Legacy content operations

Testing

Progressive testing approach using the @SwaggerCompliant annotation system:

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

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

Impact

  • ✅ Improves API documentation for content management workflows
  • ✅ Enables better developer experience with content APIs
  • ✅ Maintains backward compatibility
  • ✅ Follows established annotation patterns and standards

Dependencies

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

This PR fixes: #32529

@semgrep-code-dotcms-test
Copy link
Copy Markdown

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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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/6947d76291bbc4057625c367785fc2abf4945a79/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 spbolton force-pushed the issue-32529-batch-2 branch from 6947d76 to ce3bed2 Compare July 24, 2025 13:30
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 <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
github-merge-queue Bot pushed a commit that referenced this pull request Aug 11, 2025
…on & User Management (#32656)

## Summary
Progressive implementation of Swagger/OpenAPI annotations for REST
endpoints - Batch 1

This PR adds comprehensive Swagger annotations to **15 REST resource
classes** focused on core authentication and user management APIs that
most applications depend on.

## 🔗 Foundation Dependency
**⚠️ This PR depends on the infrastructure established in PR #32561**

- **Foundation PR**: [#32561 - Progressive Swagger annotations
infrastructure](#32561)
- **Requirement**: PR #32561 must be merged before this PR can be
reviewed/merged
- **Why**: This PR uses the `@SwaggerCompliant` annotation and
progressive testing framework created in #32561

## ⚠️ IMPORTANT: Batch Rollout Process
**This PR is part of a progressive 8-batch rollout strategy established
in PR #32561.**

- 🔧 **Foundation**: [PR
#32561](#32561) - Must be merged
first
- ✅ **Batch 1**: Ready for review after foundation is merged (this PR)
- ⏳ **Batch 2**: [PR #32657](#32657)
- Keep in draft until Batch 1 is merged
- ⏳ **Batch 3-8**: Keep in draft until previous batch is merged
- ⏳ **Batch 9**: [PR #32664](#32664)
- Keep in draft until Batch 8 is merged

**Do not remove draft state from subsequent batches until the previous
batch has been successfully merged.**

## 🎯 Automatic Testing Integration
This PR leverages the infrastructure from #32561 to enable **automatic
testing**:

- ✅ **Before this PR**: These 15 resources are not tested by compliance
tests
- ✅ **After this PR**: Resources are automatically discovered and tested
via `@SwaggerCompliant` annotations
- ✅ **Cumulative**: Future batches will test these resources plus their
new ones

```bash
# Test only Batch 1 classes (using infrastructure from #32561)
./mvnw test -pl :dotcms-core -Dtest=RestEndpointAnnotationComplianceTest -Dtest.batch.max=1
```

## Batch 1: Core Authentication & User Management (15 classes)
**Theme**: Essential user and authentication APIs that most applications
depend on

### Authentication Resources (7 classes)
- `AuthenticationResource` - Core authentication endpoints
- `ApiTokenResource` - API token management  
- `LoginFormResource` - Login form handling
- `LogoutResource` - User logout functionality
- `CreateJsonWebTokenResource` - JWT token creation
- `ForgotPasswordResource` - Password reset requests
- `ResetPasswordResource` - Password reset completion

### User Management Resources (3 classes)
- `UserResource` - User CRUD operations
- `PersonaResource` - User persona management
- `PersonalizationResource` - User personalization settings

### System Role Resources (2 classes)
- `RoleResource` - Role management
- `PermissionResource` - Permission handling

### Legacy User Resources (3 classes)
- `UserResource` (legacy) - Legacy user operations
- `RoleResource` (legacy) - Legacy role operations
- `DotSamlResource` - SAML authentication

## 🧪 Testing Strategy
Uses the progressive testing framework established in #32561:

```bash
# Test only Batch 1 classes (after #32561 is merged)
./mvnw test -pl :dotcms-core -Dtest=RestEndpointAnnotationComplianceTest -Dtest.batch.max=1

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

## 📋 Example Annotation Usage
This PR adds `@SwaggerCompliant` annotations (from #32561) to mark
resources as properly documented:

```java
@SwaggerCompliant(value = "Core authentication and user management APIs", batch = 1)
@tag(name = "Authentication")
@path("/v1/authentication")
public class AuthenticationResource {
    // Properly annotated endpoints...
}
```

## 🎯 Impact
- ✅ Improves API documentation for core authentication flows
- ✅ Enables automatic testing of these 15 resources (via #32561
infrastructure)
- ✅ Enables better developer experience with OpenAPI spec generation
- ✅ Maintains backward compatibility
- ✅ Follows established annotation patterns and standards

## 📊 Progress Tracking
This PR is **Batch 1 of 8** in the progressive rollout:
- **Total Resources**: 115 across 8 batches
- **This Batch**: 15 resources (13% of total)
- **Next**: Batch 2 (Content Management Core) - 14 resources

## 🔗 Related PRs
- **Foundation**: [#32561 - Progressive Swagger annotations
infrastructure](#32561) ← **Must
merge first**
- **Next**: [#32657 - Batch 2 (Content Management
Core)](#32657)
- **Complete chain**: See PR #32561 for full rollout plan

## ⚠️ Merge Requirements
1. **Foundation PR #32561 must be merged first**
2. This PR can then be reviewed and merged
3. After this PR is merged, remove draft state from Batch 2 PR #32657
4. Continue sequential rollout through Batch 8

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

Co-Authored-By: Claude <noreply@anthropic.com>
@spbolton spbolton force-pushed the issue-32529-batch-2 branch from ce3bed2 to 645b0d3 Compare August 12, 2025 12:38
@spbolton spbolton force-pushed the issue-32529-batch-2 branch 2 times, most recently from 17d8280 to ff46483 Compare August 28, 2025 14:44
@github-actions
Copy link
Copy Markdown
Contributor

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 Sep 28, 2025
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Oct 6, 2025

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

@github-actions github-actions Bot closed this Oct 6, 2025
@jdcmsd jdcmsd reopened this Dec 9, 2025
@semgrep-code-dotcms-test

This comment was marked as outdated.

@jdcmsd jdcmsd marked this pull request as ready for review December 12, 2025 19:22
@jdcmsd jdcmsd force-pushed the issue-32529-batch-2 branch from 3ed2b6c to 2423045 Compare December 16, 2025 17:24
@jdcmsd
Copy link
Copy Markdown
Contributor

jdcmsd commented Dec 16, 2025

I was able to replace the merge with a rebase using git rebase --rebase-merges origin/main, confirmed updated version of relevant resource files, kept origin/main version of everything else, and did a --force-with-lease push. This should be much nicer than last week's attempt.

@jdcmsd jdcmsd force-pushed the issue-32529-batch-2 branch from 997199b to ecb310d Compare December 16, 2025 19:33
@spbolton spbolton removed the stale label Dec 17, 2025
@spbolton
Copy link
Copy Markdown
Contributor Author

Looks ok now by me after removing a couple of frontend files that got in with duplicated methods, but I cannot approve myself as I am set as the author.

Comment thread dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoriesResource.java Outdated
Comment thread dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoriesResource.java Outdated
Comment thread dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoriesResource.java Outdated
Comment thread dotCMS/src/main/java/com/dotcms/rest/ContentResource.java
@jdcmsd jdcmsd force-pushed the issue-32529-batch-2 branch from b27ea55 to 2c4e286 Compare March 17, 2026 13:39
@github-actions github-actions Bot removed Area : Frontend PR changes Angular/TypeScript frontend code Area : SDK PR changes SDK libraries Area : Documentation PR changes documentation files Area : CI/CD PR changes GitHub Actions/workflows labels Mar 17, 2026
jdcmsd added 10 commits March 17, 2026 10:45
…est needed a corresponding update to preserve the possibility of both outcomes
…existed) or 201 (at least one new tag created) result. This allows for success for all postman tests expecting 201, AND satisfies our separate Swagger Compliance 'must return 200' requirement.
… duplicateCount, updateTag needed to resolve through tag storage, and -- weirdly -- it complained that there's no bulk delete method/endpoint. So, uh, we added another endpoint. Way out of the expected scope, but this is apparently what the automated tests demanded. But hey, at least it's documented already. Oh, and then I did a sweep to make sure everything has unique operationIds.
…p, and the other involving silently continuing when a tag isn't found for deletion.
…l endpoint was already returning 201. When we first looked at it, the failing tests were integration tests and Postman tests that expected 200. Rather than changing the endpoint down to 200, we went the other direction — updating the tests up to 201 to match the endpoint behavior. Then the RestEndpointAnnotationComplianceTest failed because it requires every @SwaggerCompliant method to have a 200 @apiresponse documented. That test doesn't verify the actual response code — just that 200 is in the Swagger docs — but at the time we interpreted it as needing a real 200 code path. So we implemented the conditional: 201 for new tags, 200 when all duplicates already existed. That conditional turned out to be the problem. Tests in two other collections (Content Resource, and Tags' own 'Invalid Site ID' test) called the same endpoint in a context that always creates a fresh tag, and they'd always expected 200 without ever being updated. So we were chasing the 201 behavior through one set of tests while breaking another set that nobody had thought to check. In hindsight: the endpoint should have just always returned 200 from the start of our changes. The 201 was technically more REST-correct for a creation operation, but the project's existing test baseline was built around 200, and fighting that wasn't worth it.
@semgrep-code-dotcms-test
Copy link
Copy Markdown

Semgrep found 1 jax-rs-jax-rs-open-redirect-uri-params finding:

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

The application builds a URL using user-controlled input which can lead to an open redirect vulnerability. An attacker can manipulate the URL and redirect users to an arbitrary domain. Open redirect vulnerabilities can lead to issues such as Cross-site scripting (XSS) or redirecting to a malicious domain for activities such as phishing to capture users' credentials. To prevent this vulnerability perform strict input validation of the domain against an allowlist of approved domains. Notify a user in your application that they are leaving the website. Display a domain where they are redirected to the user. A user can then either accept or deny the redirect to an untrusted site.

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/8b69b601a443cc59fa3b244aca12fd9cddd01027/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1426 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1426] params</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/dotCMS/core/blob/8b69b601a443cc59fa3b244aca12fd9cddd01027/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1426 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1426] params</a>"]

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

            v4["<a href=https://github.com/dotCMS/core/blob/8b69b601a443cc59fa3b244aca12fd9cddd01027/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1484 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1484] params</a>"]

            v5["<a href=https://github.com/dotCMS/core/blob/8b69b601a443cc59fa3b244aca12fd9cddd01027/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1487 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1487] init</a>"]

            v6["<a href=https://github.com/dotCMS/core/blob/8b69b601a443cc59fa3b244aca12fd9cddd01027/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1607 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1607] saveContent</a>"]

            v7["<a href=https://github.com/dotCMS/core/blob/8b69b601a443cc59fa3b244aca12fd9cddd01027/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1831 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1831] init</a>"]

            v8["<a href=https://github.com/dotCMS/core/blob/8b69b601a443cc59fa3b244aca12fd9cddd01027/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1862 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1862] contentlet</a>"]

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

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/dotCMS/core/blob/8b69b601a443cc59fa3b244aca12fd9cddd01027/dotCMS/src/main/java/com/dotcms/rest/ContentResource.java#L1953 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 1953] Response.seeOther(new URI(&quot;content/inode/&quot; + contentlet.getInode()))</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.

…m annotations

The processImport() response was incorrectly changed to return
UtilMethods.isSet(unableToDeleteCats) instead of the actual successCount,
causing the Postman "Categories were imported" test to fail with
"expected +0 to be above +0".

Also simplified the @BeanParam parameter annotation to match the
established ContentImportResource pattern — moved @RequestBody Swagger
docs into the @operation annotation where they belong.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 20, 2026

Claude finished @spbolton's task in 2m 18s —— View job


Rollback Safety Analysis

  • Gather context
  • Read rollback-unsafe categories reference
  • Analyze PR diff against unsafe categories
  • Apply label

Verdict: ✅ Safe To Rollback

This PR consists entirely of Swagger/OpenAPI annotation additions, documentation improvements, and minor bug fixes. It does not touch any rollback-unsafe category:

Category Finding
C-1 Structural Data Model Change ✅ None — no runonce tasks, no schema changes
C-2 Elasticsearch Mapping Change ✅ None — no ESMapping* changes
C-3 JSON Model Version Bump ✅ None — no CURRENT_MODEL_VERSION changes
C-4 DROP TABLE / DROP COLUMN ✅ None
H-1 One-Way Data Migration ✅ None
H-2 RENAME TABLE / RENAME COLUMN ✅ None
H-3 PK Restructuring ✅ None
H-4 New Field Type ✅ None
H-5 Storage Provider Change ✅ None
H-6 DROP PROCEDURE/FUNCTION ✅ None
M-1 Non-Broadening Column Type Change ✅ None
M-2 Push Publishing Bundle Format ✅ None
M-3 REST API Contract Change ✅ No new contracts adopted by clients — only removals of deprecated application/javascript JSONP media type from @Produces on already-deprecated endpoints. Rolling back restores JSONP support (not harmful).
M-4 OSGi Plugin API Breakage ✅ None

Notable functional changes (not rollback-unsafe):

  • ContentResource.java: processJSON called twice on the same stream was refactored to read once and reuse — bug fix, no contract impact.
  • ContentResource.java / CategoriesResource.java / WorkflowResource.java: Removed application/javascript from @Produces on deprecated endpoints — a narrowing of accepted types, not a new contract clients depend on.
  • CategoriesResource.java: importCategories refactored from File + multiple @FormDataParam to @BeanParam CategoryImportData — external HTTP interface unchanged (same multipart form field names).

Label applied: AI: Safe To Rollback

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 20, 2026

Claude finished @spbolton's task in 3m 48s —— View job


PR Review

  • Gather context
  • Read changed files
  • Analyze security findings
  • Review code changes
  • Post final review

Summary: Mostly annotation-only work, but a few real issues.


Issues Found

1. String literal instead of constant — WorkflowResource.java:3445

content = @Content(mediaType = "MediaType.APPLICATION_JSON",

This passes the Java identifier name as a literal string. OpenAPI will display "MediaType.APPLICATION_JSON" instead of "application/json". Should be mediaType = MediaType.APPLICATION_JSON or mediaType = "application/json".

Fix this →


2. @ApiResponse(responseCode = "201") documented but never returned — TagResource.java:245

The createTags endpoint always calls Response.ok(...) (HTTP 200). The 201 response code is documented in Swagger but can never actually be returned. The commit history explains this was an intentional workaround after test suite conflicts, but documenting a status code the endpoint cannot emit is misleading API documentation.

If 201 is not achievable without breaking tests, remove the 201 @ApiResponse entry.


3. Functional changes bundled into an annotation PR

Two non-trivial functional changes are embedded:

  • ContentResource.java ~1513–1531: Changed to read JSON InputStream into a Map once to avoid a "Stream closed" error. This is a real behavior change (reads binary_fields from the parsed map rather than re-reading the stream). The change appears correct but it's riskier than pure annotation work.

  • CategoriesResource.java ~944–950: The importCategories method was refactored from explicit @FormDataParam parameters to @BeanParam CategoryImportData. jdcmsd confirmed this caused a NPE in December (the InputStream was always null). The latest commit message says the import fix is in — but the CategoryImportData class still has two @FormDataParam("file") setters binding to the same form field (one for InputStream, one for FormDataContentDisposition). Whether this works correctly in Jersey's @BeanParam injection depends on Jersey version behavior and should be integration-tested explicitly.


4. Semgrep findings are false positives

  • Path traversal / tainted-file-path (ContentResource.java ~1616–1632): FileUtil.sanitizeFileName() calls Paths.get(badFileName).getFileName().toString(), which strips all path components. Legitimate mitigation — no action needed.

  • Open redirect (ContentResource.java ~1953): Response.seeOther(new URI("content/inode/" + contentlet.getInode()))getInode() returns a system-generated UUID, not raw user input. A relative URI cannot redirect to an external domain. False positive.


5. Minor: @Produces(APPLICATION_OCTET_STREAM) — resolved

The annotation is still present at WorkflowResource.java:3432 as it should be. The @ApiResponse media type is documented separately as application/json, which aligns with what spbolton explained. No issue here.


jdcmsd added 3 commits March 20, 2026 11:25
… complaining about uncommitted changes to the yaml in the working directory.
…1 am EST). corrects the mediatype representation in workflow, and then dares to address the 'unnecessary' 201 annotation by making the small changes to the tests and method to ensure the endpoint CAN validly return a 201 code.
…it was only looking for 200. adjusted to accept the full range of 2xx, since the goal is 'must be successful'
@jdcmsd jdcmsd added this pull request to the merge queue Mar 20, 2026
Merged via the queue into main with commit b5098b3 Mar 20, 2026
55 of 77 checks passed
@jdcmsd jdcmsd deleted the issue-32529-batch-2 branch March 20, 2026 20:26
spbolton added a commit that referenced this pull request Mar 24, 2026
…t Core (#32657)

## Summary
Progressive implementation of Swagger/OpenAPI annotations for REST
endpoints - Batch 2

This PR adds comprehensive Swagger annotations to **14 REST resource
classes** focused on primary content creation, editing, and 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**: Remove draft state ONLY after Batch 1 is merged (this
PR)
- ⏳ **Batch 3-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 1 (#32656) has
been successfully merged.**

## Batch 2: Content Management Core (14 classes)
**Theme**: Primary content creation, editing, and management APIs

### Content Resources (6 classes)
- `ContentResource` - Core content CRUD operations
- `ContentVersionResource` - Content versioning
- `ContentRelationshipsResource` - Content relationships
- `ContentReportResource` - Content reporting
- `ResourceLinkResource` - Resource linking
- `ContentImportResource` - Content import functionality

### Content Type Resources (4 classes)
- `ContentTypeResource` - Content type management
- `FieldResource` - Field management
- `FieldVariableResource` - Field variable handling
- `FieldTypeResource` - Field type definitions

### Workflow Resources (1 class)
- `WorkflowResource` - Workflow management

### Categories & Tags (2 classes)
- `CategoriesResource` - Category management
- `TagResource` (v2) - Tag management

### Legacy Content Resources (1 class)
- `ContentResource` (legacy) - Legacy content operations

## Testing
Progressive testing approach using the `@SwaggerCompliant` annotation
system:

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

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

## Impact
- ✅ Improves API documentation for content management workflows
- ✅ Enables better developer experience with content APIs
- ✅ Maintains backward compatibility
- ✅ Follows established annotation patterns and standards

## Dependencies
- **Depends on**: Batch 1 (Core Authentication & User Management) -
#32656
- **Next**: Batch 3 (Site Architecture & Templates) - #32658

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

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Jamie Mauro <jameson.mauro@dotcms.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Safe To Rollback Area : Backend PR changes Java/Maven backend code

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Add Swagger annotations to endpoints missing it

5 participants