[Customer Portal][BE] Add case create endpoint and update case response - #114
Conversation
📝 WalkthroughWalkthroughAdds case-creation: new CaseCreate types and CreatedCase, replaces Case.'type with deployedProduct and issueType across types and mappings, adds entity.createCase and a POST /cases resource that authenticates and forwards requests, fixes an auth message spacing, and removes Changes
Sequence DiagramsequenceDiagram
participant Client as Client
participant Service as "Service Layer"
participant Entity as "Entity Module"
participant Backend as "Backend API"
Client->>Service: POST /cases (CaseCreatePayload)
Service->>Service: Extract auth token (HEADER_USER_INFO)
Service->>Entity: createCase(idToken, payload)
Entity->>Backend: POST /cases (with auth headers)
Backend-->>Entity: 201 Created / 401 / 403 / error
alt 201 Created
Entity-->>Service: CaseCreateResponse
Service-->>Client: 201 Created + case data
else 401 Unauthorized
Entity-->>Service: 401 Error
Service-->>Client: 401 Unauthorized
else 403 Forbidden
Entity-->>Service: 403 Error
Service-->>Client: 403 Forbidden
else Other Error
Entity-->>Service: Error
Service-->>Client: 500 Internal Server Error
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
No actionable comments were generated in the recent review. 🎉 🧹 Recent nitpick comments
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@apps/customer-portal/backend/modules/entity/entity.bal`:
- Around line 91-98: The doc comment for the function addCase is wrong: it
states "Nil or error" but the function returns CaseCreateResponse|error. Update
the doc comment for addCase to accurately describe parameters and the return
type (CaseCreateResponse|error) and adjust the "return" line to mention
CaseCreateResponse or error; ensure the parameter descriptions for idToken and
payload remain correct and consistent with the function signature.
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 119-138: The CaseCreatePayload definition is missing string
validation for title and description; update the record type (CaseCreatePayload)
to add `@constraint`:String {minLength: 1} annotations to the title and
description fields so they cannot be empty or blank, mirroring the existing
constraints on projectId, deploymentId, and productId.
🧹 Nitpick comments (2)
apps/customer-portal/backend/types.bal (1)
70-73: PublicCasetype updates are consistent with the entity layer.The
deployedProductandissueTypefields correctly useReferenceItem?(string-based id), aligning with theint→stringconversion done inutils.bal.Nit: Line 72 comment
# issueType of the caseshould be capitalized for consistency with other field comments (e.g.,# Deployed product information).Proposed fix
- # issueType of the case + # Issue type of the case ReferenceItem? issueType;apps/customer-portal/backend/service.bal (1)
641-642: Public endpoint directly exposesentity:CaseCreatePayload— inconsistent with other endpoints.Other endpoints (e.g., case search) define a public-facing payload type in
types.balthat maps to the entity type. Here,entity:CaseCreatePayloadis used directly as the API input, coupling the public API contract to the entity layer. If the entity API adds internal-only fields, they'd be exposed to clients.Consider introducing a public
CaseCreatePayloadintypes.bal(similar toCaseSearchPayload) and mapping it toentity:CaseCreatePayloadbefore callingentity:addCase.
|
|
||
| authorization:UserInfoPayload|error userInfo = ctx.getWithType(authorization:HEADER_USER_INFO); | ||
| if userInfo is error { | ||
| return <http:InternalServerError>{ |
There was a problem hiding this comment.
USER_INFO_HEADER_NOT_FOUND should not be 500. This is not a server error IMO it’s a client/auth issue. Should be;
<http:Unauthorized>
There was a problem hiding this comment.
We (@shayanmalinda, @sacheeramesh, and I) already had a discussion in the past about whether this should return <http:Unauthorized>. I think, all our backends currently use a http:InternalServerError error for this case.
Should we revisit this? I also personally believe this should be a <http:Unauthorized> as well(including few errors in authorization.bal file).
Adding @yuk7hi and @kasunsiyambalapitiya as well
There was a problem hiding this comment.
IMO, HEADER_USER_INFO is not a header passed from the consumer (e.g., the web app).
It is an internal attribute introduced in the request interceptor to pass logged-in user information (email, groups, idToken) to service.bal via the http:RequestContext.
If this attribute is missing, or if there is an issue deriving it in service.bal (for example, setting it with one name and reading it using a different name), it should be treated as an implementation issue and the correct response should be an InternalServerError.
Authorization is handled at the gateway level, not by the backend service.
If a request reaches the backend, it is already authorized. Therefore, the backend should not ideally return any Unauthorized responses.
There was a problem hiding this comment.
Thanks @shayanmalinda. Agree that HEADER_USER_INFO is an internal context attribute and should be treated as an implementation issue (500) if missing.
One clarification here is that this behavior is specific to our setup. In Choreo, the gateway validates the Authorization: Bearer header and converts it into x-jwt-assertion before forwarding the request to the backend.
This conversion is platform-specific and not something all API gateways do by default.
Because of this, the backend currently depends on this contract with the gateway. If x-jwt-assertion is missing, it usually indicates an issue with the authentication flow at the gateway level (missing/invalid bearer token or routing/config issue), rather than something the consumer can directly fix.
We can add a comment in the interceptor to document this dependency on the gateway behavior, so it’s clear why this is treated as an internal error and mapped accordingly.
However I believe I need to fix the error returned when the custom header(x-user-id-token) is not found while checking it. Currently it returns 500.
There was a problem hiding this comment.
Let's have a seperate revisit on this later. Will approve the PR due to the urgency.
| if userInfo is error { | ||
| return <http:InternalServerError>{ | ||
| body: { | ||
| message: ERR_MSG_USER_INFO_HEADER_NOT_FOUND |
There was a problem hiding this comment.
I think returning ERR_MSG_USER_INFO_HEADER_NOT_FOUND is incorrect, since the user has no control over fixing this issue. As per the previous reply, this is an internal implementation problem, so it would be more appropriate to return a generic error such as Something went wrong while processing the request.
There was a problem hiding this comment.
Shall we have an offline discussion regarding this? Anyway the fix will be in a separate PR.
0bc6761
into
wso2-open-operations:customer-portal-milestone-1
Description
This PR introduces a new endpoint for case creation and updates the case response structure.
Changes
POST /cases)Testing
Related Issues
Related PRs
Checklist
Summary by CodeRabbit
New Features
Bug Fixes
Updates