Skip to content

[Customer Portal][BE] Add endpoints to create comments on cases - #122

Merged
Rashmika998 merged 8 commits into
wso2-open-operations:customer-portal-milestone-1from
Rashmika998:customer-portal-milestone-1-case-attachment
Feb 11, 2026
Merged

Rashmika998 merged 8 commits into
wso2-open-operations:customer-portal-milestone-1from
Rashmika998:customer-portal-milestone-1-case-attachment

Conversation

@Rashmika998

@Rashmika998 Rashmika998 commented Feb 11, 2026 •

Copy link
Copy Markdown
Contributor

Description

This PR adds a new API endpoint to allow users to create comments on cases.

Changes

  • Added endpoint for creating case comments
  • Implemented validation for comment content
  • Stored author and timestamp information
  • Updated models and DTOs
  • Enhanced response structure (if required)
  • Update case search payload

Reason

Cases currently lack an API for adding comments, limiting collaboration and tracking. This change enables proper discussion and documentation within cases.

Testing

  • Tested comment creation with valid and invalid payloads
  • Verified persistence and retrieval of comments
  • Checked authorization and access control

Related Issues

Related PRs

Summary by CodeRabbit

  • New Features
    • Post comments and work notes on cases with user attribution and timestamps.
    • Upload attachments to cases with metadata, size/download links, and created-by info.
    • Enhanced case search with a text-based query to find cases by number, title, or description.

@coderabbitai

coderabbitai Bot commented Feb 11, 2026 •

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds comment and attachment creation: new enums and payload/response types, two public entity functions (createComment, createAttachment) that POST to external endpoints, two POST resources under cases/{id} that validate user and map errors, and an optional searchQuery filter propagated into case searches.

Changes

Cohort / File(s) Summary
Entity types & payloads
apps/customer-portal/backend/modules/entity/types.bal
Added ReferenceType, CommentType enums and new records: CommentCreatePayload, CreatedComment, CommentCreateResponse, CreatedAttachment, AttachmentCreateResponse, AttachmentPayload.
Entity functions
apps/customer-portal/backend/modules/entity/entity.bal
Added public isolated function createComment(string idToken, CommentCreatePayload payload) and public isolated function createAttachment(string idToken, AttachmentPayload payload) that POST to /comments and /attachments including headers and token.
Service endpoints
apps/customer-portal/backend/service.bal
Added resources POST cases/[string id]/comments and POST cases/[string id]/attachments; extract user token, validate case id, call entity functions, map Unauthorized/Forbidden/InternalServerError, and return created resources.
App-level types & search propagation
apps/customer-portal/backend/types.bal, apps/customer-portal/backend/utils.bal
Added CommentCreatePayload and AttachmentPayload app types; added optional searchQuery? to CaseSearchFilters and propagated it into the case search payload.
Dependencies
apps/customer-portal/backend/Dependencies.toml
Added module entry {org = "wso2", packageName = "customer_portal", moduleName = "customer_portal.updates"}.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client
    participant Service as Service
    participant Entity as Entity
    participant External as ExternalAPI

    Client->>Service: POST /cases/{id}/comments (payload)
    activate Service
    Service->>Service: extract user token, validate id
    Service->>Entity: createComment(idToken, payload)
    activate Entity
    Entity->>External: POST /comments (payload + headers)
    activate External
    External-->>Entity: CommentCreateResponse
    deactivate External
    Entity-->>Service: CommentCreateResponse
    deactivate Entity
    Service-->>Client: CreatedComment (200)
    deactivate Service
Loading
sequenceDiagram
    participant Client as Client
    participant Service as Service
    participant Entity as Entity
    participant External as ExternalAPI

    Client->>Service: POST /cases/{id}/attachments (payload)
    activate Service
    Service->>Service: extract user token, validate id
    Service->>Entity: createAttachment(idToken, payload)
    activate Entity
    Entity->>External: POST /attachments (payload + headers)
    activate External
    External-->>Entity: AttachmentCreateResponse
    deactivate External
    Entity-->>Service: AttachmentCreateResponse
    deactivate Entity
    Service-->>Client: CreatedAttachment (200)
    deactivate Service
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

Type/New Feature

Suggested reviewers

  • cloby99
  • shayanmalinda

Poem

🐰 I hopped through types and endpoints bright,
I stitched payloads and headers in the night,
Comments and files now take their flight,
Cases humbly grow, all tucked in tight,
Hoppy code — a tiny feature delight!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers key sections (Purpose, Goals, Reason, Testing, Related Issues) but is missing several required template sections including Approach, User stories, Release note, Documentation, Training, Certification, Marketing, and Security checks. Complete the PR description by adding all required template sections. At minimum, add Approach (implementation details), Documentation (impact analysis), and Security checks sections.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding endpoints to create comments on cases, which aligns with the substantial implementation of comment and attachment creation functionality.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@apps/customer-portal/backend/modules/entity/entity.bal`:
- Around line 137-143: The createAttachment function currently ignores the case
ID and sends an empty payload; update it to accept the case identifier and
attachment payload from the API handler and forward them to
csEntityClient->/attachments.post (instead of posting {}), e.g., add parameters
for the case id and attachment metadata/file content to public isolated function
createAttachment(string idToken, string caseId, AttachmentPayload payload) and
include caseId (and payload fields) in the POST body, ensuring the API endpoint
that extracts the path `id` passes that id into entity:createAttachment and that
generateHeaders(idToken) remains used for auth.

In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 545-553: AttachmentCreateResponse currently lacks the permissive
rest field used elsewhere (e.g., CommentCreateResponse) so extra fields from the
upstream API will break deserialization; update the AttachmentCreateResponse
record type to include the open rest field (json...;) so the record tolerates
additional JSON properties, matching the pattern used by CommentCreateResponse.

In `@apps/customer-portal/backend/service.bal`:
- Around line 1046-1097: The post cases/[string id]/attachments resource
validates the path parameter id but calls entity:createAttachment only with
userInfo.idToken, so the attachment won’t be linked to the case; change the call
to entity:createAttachment to forward the case id (e.g., pass id as a second
argument or as referenceId) so the entity layer receives both userInfo.idToken
and the case id (update the entity:createAttachment usage/signature accordingly
if needed), mirroring how the comment endpoint forwards id as referenceId.
🧹 Nitpick comments (2)
apps/customer-portal/backend/types.bal (1)

289-298: Consider adding @constraint validation on content.

The content field has no length constraints, unlike CaseCreatePayload which validates title (maxLength: 500) and description (maxLength: 65000). An empty or excessively large comment payload could reach the downstream entity API unchecked.

💡 Proposed constraint addition
 # Payload for creating a comment.
 public type CommentCreatePayload record {|
     # Reference type
     entity:ReferenceType referenceType;
     # Comment content
+    `@constraint`:String {
+        minLength: 1,
+        maxLength: 65000
+    }
     string content;
     # Comment type
     entity:CommentType 'type;
 |};
apps/customer-portal/backend/service.bal (1)

983-1040: Missing case access verification before creating the comment.

The GET cases/[id]/comments endpoint (Line 867) verifies case access by calling entity:getCase before fetching comments. The POST endpoint skips this step, relying solely on the downstream entity API for authorization. If the entity API doesn't enforce case-level access control on comment creation, a user could comment on a case they don't have access to.

Consider adding the same case access verification pattern used in the GET endpoint for consistency and defense-in-depth.

Comment thread apps/customer-portal/backend/modules/entity/entity.bal
Comment thread apps/customer-portal/backend/modules/entity/types.bal
Comment thread apps/customer-portal/backend/service.bal Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/customer-portal/backend/types.bal`:
- Around line 301-313: AttachmentPayload currently exposes a client-sent
referenceId that gets ignored by the attachment endpoint (payload.referenceId is
overridden by the path param id), causing confusion; remove the unused field
from the public type AttachmentPayload to match CommentCreatePayload's pattern,
update any compile-time references/usages to stop expecting payload.referenceId,
and ensure the service handler continues to use the path parameter id as the
authoritative reference; alternatively, if you prefer to accept client-provided
IDs, remove the override in the attachment handler and document the behavior
consistently—pick one approach and update API docs/tests accordingly.
🧹 Nitpick comments (2)
apps/customer-portal/backend/service.bal (2)

1003-1039: Misleading variable name createdCaseResponse for a comment creation result.

The variable at Line 1003 is named createdCaseResponse but holds a CommentCreateResponse. This appears to be a copy-paste artifact from the case creation endpoint. Rename it for clarity.

Proposed rename
-        entity:CommentCreateResponse|error createdCaseResponse = entity:createComment(userInfo.idToken,
+        entity:CommentCreateResponse|error createdCommentResponse = entity:createComment(userInfo.idToken,
                 {
                     referenceId: id,
                     referenceType: payload.referenceType,
                     content: payload.content,
                     'type: payload.'type
                 });
-        if createdCaseResponse is error {
-            if getStatusCode(createdCaseResponse) == http:STATUS_UNAUTHORIZED {
+        if createdCommentResponse is error {
+            if getStatusCode(createdCommentResponse) == http:STATUS_UNAUTHORIZED {
                 log:printWarn(string `User: ${userInfo.userId} is not authorized to access the customer portal!`);
                 return <http:Unauthorized>{
                     body: {
                         message: ERR_MSG_UNAUTHORIZED_ACCESS
                     }
                 };
             }
 
-            if getStatusCode(createdCaseResponse) == http:STATUS_FORBIDDEN {
+            if getStatusCode(createdCommentResponse) == http:STATUS_FORBIDDEN {
                 log:printWarn(string `User: ${userInfo.userId} is forbidden to comment on case with ID: ${id}!`);
                 return <http:Forbidden>{
                     body: {
                         message: "You're not authorized to comment on the requested case. " +
                         "Please check your access permissions or contact support."
                     }
                 };
             }
 
             string customError = "Failed to create a new comment.";
-            log:printError(customError, createdCaseResponse);
+            log:printError(customError, createdCommentResponse);
             return <http:InternalServerError>{
                 body: {
                     message: customError
                 }
             };
         }
 
-        return createdCaseResponse.comment;
+        return createdCommentResponse.comment;

1042-1047: Doc comment is missing the payload parameter description.

Line 1042–1045: the doc comment for the attachment endpoint documents id but omits payload.

Proposed fix
     # Create a new attachment for a specific case.
     #
     # + id - ID of the case
+    # + payload - Attachment creation payload
     # + return - Created attachment or error response

Comment thread apps/customer-portal/backend/types.bal

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/customer-portal/backend/service.bal`:
- Around line 978-1040: The POST resource function post cases/[string
id]/comments currently returns entity:CreatedComment (from entity:createComment)
directly, risking exposure of sensitive fields like referenceId; update this to
map the createdCaseResponse.comment into a public DTO before returning—either
define a public CreatedComment type (omitting referenceId) and construct/convert
the entity:CommentCreateResponse.comment into that type, or reuse the existing
mapCommentsResponse pattern to filter fields; ensure the mapping happens after
successful entity:createComment and return the mapped public comment instead of
createdCaseResponse.comment.
🧹 Nitpick comments (2)
apps/customer-portal/backend/types.bal (1)

301-311: AttachmentPayload lacks input validation on name and content.

Unlike CommentCreatePayload which constrains content, AttachmentPayload accepts arbitrary strings for name and content with no length or format validation. An empty file name or an unbounded base64 content string could cause issues downstream or allow excessively large payloads.

Consider adding constraints — at minimum a minLength: 1 on name and a maxLength on content to bound upload size.

Suggested constraints
 public type AttachmentPayload record {|
     # Reference type
     entity:ReferenceType referenceType;
     # File name
+    `@constraint`:String {minLength: 1, maxLength: 255}
     string name;
     # MIME type of the file
+    `@constraint`:String {minLength: 1}
     string 'type;
     # Base 64 encoded content
+    `@constraint`:String {minLength: 1}
     string content;
 |};
apps/customer-portal/backend/service.bal (1)

1042-1045: Missing + payload parameter in doc comment.

The doc comment documents id but omits the payload parameter, unlike the comment endpoint above which documents both.

Suggested fix
 # Create a new attachment for a specific case.
 #
 # + id - ID of the case
+# + payload - Attachment creation payload
 # + return - Created attachment or error response

Comment thread apps/customer-portal/backend/service.bal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

App/Customer Portal Area/Backend Type/Improvement Marks enhancements or improvements to existing features

Projects

Status: Staging Deployed

Development

Successfully merging this pull request may close these issues.

3 participants