Skip to content

[Customer Portal] Implement User Phone Number Update Functionality - #69

Merged
shayanmalinda merged 9 commits into
wso2-open-operations:customer-portal-milestone-1from
Rashmika998:customer-portal-milestone-1-dev-1
Jan 27, 2026
Merged

shayanmalinda merged 9 commits into
wso2-open-operations:customer-portal-milestone-1from
Rashmika998:customer-portal-milestone-1-dev-1

Conversation

@Rashmika998

@Rashmika998 Rashmika998 commented Jan 27, 2026 •

Copy link
Copy Markdown
Contributor

Description

This PR introduces support for updating user phone numbers through the SCIM module, enabling standardized and secure profile updates.

The implementation follows SCIM specifications and ensures that phone number changes are properly validated, processed, and synchronized with the identity provider.


Changes

  • Implemented phone number update functionality via the SCIM module
  • Added support for updating mobile numbers in user profiles
  • Integrated validation and error handling for update requests

Example Endpoint

Both fields are optional,

{
    "phoneNmber": "",
    "timeZone": ""
}

Related Issues

Summary by CodeRabbit

  • New Features

    • Profile update endpoint: users can patch phone number and timezone; GET /users/me now returns timeZone.
    • SCIM-backed user update flow to persist phone changes.
  • Improvements

    • Structured update payloads and phone types introduced.
    • International phone validation (E.164) enforced.
    • userId included in returned user data.
    • Centralized phone processing and consistent error-message extraction.
  • Chores

    • Added generic unexpected-error and phone-pattern constants.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Jan 27, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@Rashmika998 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 4 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

Adds profile-update capability: new constants and phone regex, authorization now maps JWT userid to userId, SCIM updateUser function, a PATCH /users/me endpoint for phone/timeZone updates, phone-processing and error-extraction helpers, and related public types.

Changes

Cohort / File(s) Summary
Constants
apps/customer-portal/backend/constants.bal
Added public constants: UNEXPECTED_ERROR_MSG, PHONE_PATTERN_STRING, ERR_BODY.
Authorization
apps/customer-portal/backend/modules/authorization/authorization.bal, apps/customer-portal/backend/modules/authorization/types.bal
Mapped private JWT userid into public UserDataPayload.userId; added userid in private payload type and userId in public payload type.
SCIM module & types
apps/customer-portal/backend/modules/scim/scim.bal, apps/customer-portal/backend/modules/scim/types.bal
Added public isolated function updateUser(UserUpdatePayload, string email, string uuid) that PATCHes SCIM /organizations/[org]/users/[uuid]; added UserUpdatePayload and Phone types (password?, phoneNumber?).
Service & public types
apps/customer-portal/backend/service.bal, apps/customer-portal/backend/types.bal
Added resource function patch users/me(...) to accept UserUpdatePayload, call SCIM for phone updates, handle 400 vs other errors; User now composes entity:UserResponse; added UserUpdatePayload and UpdatedUser; GET /users/me includes timeZone.
Utilities
apps/customer-portal/backend/utils.bal
Added public isolated function processPhoneNumber(scim:User) returns string? to extract mobile phone, and public isolated function getErrorMessage(error err) returns string; getPhoneNumber delegates to processPhoneNumber.

Sequence Diagram

sequenceDiagram
    participant Client as HTTP Client
    participant Service as Service
    participant Auth as Authorization
    participant SCIM as SCIM Module
    participant API as SCIM API

    Client->>Service: PATCH /users/me (UserUpdatePayload)
    Service->>Auth: extract user from header
    Auth-->>Service: UserDataPayload (includes userId)
    alt phoneNumber provided
        Service->>SCIM: updateUser(payload, email, uuid)
        SCIM->>SCIM: determine organization from email
        SCIM->>API: PATCH /organizations/[org]/users/[uuid]
        alt API success
            API-->>SCIM: updated User
            SCIM-->>Service: User
            Service->>Service: processPhoneNumber(scim:User)
            Service-->>Client: 200 UpdatedUser
        else API 400
            API-->>SCIM: 400 error
            SCIM-->>Service: error
            Service-->>Client: 400 BadRequest
        else API other error
            API-->>SCIM: error
            SCIM-->>Service: error
            Service-->>Client: 500 InternalServerError
        end
    else timeZone provided
        Service->>Service: (TODO) timezone update logic
        Service-->>Client: 200 UpdatedUser
    else
        Service-->>Client: 400 BadRequest
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

Type/Improvement

Suggested reviewers

  • cloby99
  • shayanmalinda

Poem

🐰 I hop through claims and stitch a new id,
I nudge a phone-string, tidy regex wide,
SCIM patches hum, a tiny carrot cheer,
Timezones wait while I nibble near,
Hooray — a quick update, done with a ear twitch.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description lacks most required template sections including Purpose, Goals, Approach, User Stories, Release Notes, Documentation, Training, Certification, Marketing, Testing, Security, Samples, Migrations, and Test Environment. Only Description and Related Issues are partially provided. Complete the PR description using the repository template by adding Purpose, Goals, Approach, test coverage details, security checks, and documentation links required for proper code review and release tracking.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: implementing user phone number update functionality in the customer portal backend, which aligns with the SCIM module additions and patch endpoint.
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.


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: 2

🤖 Fix all issues with AI agents
In `@apps/customer-portal/backend/service.bal`:
- Line 164: The current statement `return http:BAD_REQUEST;` returns a status
constant instead of an HTTP response record; replace it with a proper response
object consistent with other error returns (e.g., return { status:
http:BAD_REQUEST, body: { error: "<brief message>" } };) so callers receive a
full http:Response-like record; update the code in the same function where
`http:BAD_REQUEST` is used and match the existing error-response shape used
elsewhere in the file.
- Around line 137-158: After a successful scim:updateUser call in the PATCH
handler (the block that checks payload.phoneNumber, calls scim:updateUser and
returns processPhoneNumber(updatedUser)), invalidate the cached "GET users/me"
entry for this user before returning; call a cache invalidation function (e.g.,
invalidateUserCache(userInfo.userId) or cache:remove(userInfo.userId)) right
after the update succeeds and before the final return, or implement such a
function if missing so subsequent GET users/me requests won't return stale data.
🧹 Nitpick comments (5)
apps/customer-portal/backend/modules/scim/types.bal (1)

60-72: Verify SCIM update payload shape for phone numbers.
UserUpdatePayload models phoneNumber with a nested mobile field, while SCIM typically uses phoneNumbers arrays of {type, value}. Please confirm the SCIM operations service accepts this custom shape; otherwise map to the SCIM schema before PATCHing.

♻️ If SCIM expects the standard `phoneNumbers` schema
 public type UserUpdatePayload record {|
     # Password
     string password?;
     # Phone numbers
-    Phone phoneNumber?;
+    PhoneNumber[]? phoneNumbers?;
 |};
-
-# Phone number.
-public type Phone record {|
-    # Mobile number
-    string mobile?;
-|};
apps/customer-portal/backend/constants.bal (1)

19-20: Confirm the phone regex matches the intended format.
The pattern currently enforces a leading + with 10–14 digits. If full E.164 coverage is expected (up to 15 digits), consider widening the range.

🔧 Possible adjustment for E.164 max length
-public const PHONE_PATTERN_STRING = "^\\+\\d{10,14}$";
+public const PHONE_PATTERN_STRING = "^\\+\\d{10,15}$";

Also applies to: 27-28

apps/customer-portal/backend/types.bal (2)

106-118: Consider adding timezone validation.

The phoneNumber field has proper E.164 format validation, which is good. However, the timezone field accepts any string without validation. Invalid timezone values could cause issues downstream when processing user preferences.

Consider adding a constraint to validate against known timezone identifiers (e.g., IANA timezone database format like "America/New_York").


120-124: Response type may need to include timezone for consistency.

The UpdatedUser type only contains phoneNumber, but UserUpdatePayload also accepts timezone. Once the timezone update functionality is implemented (currently a TODO in service.bal), the response type should be extended to include the updated timezone as well.

apps/customer-portal/backend/service.bal (1)

160-162: TODO implementation needs a return statement to avoid falling through to BAD_REQUEST.

When the timezone update logic is implemented, ensure it returns an appropriate response. Currently, even after adding timezone update code here, the function would fall through to return BAD_REQUEST on line 164 unless a return statement is added.

Additionally, consider handling the case where both phoneNumber and timezone are provided in a single request.

Would you like me to help design the control flow for handling both fields together, or open an issue to track the timezone implementation?

Comment thread apps/customer-portal/backend/service.bal Outdated
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: 2

🤖 Fix all issues with AI agents
In `@apps/customer-portal/backend/service.bal`:
- Around line 170-172: The payload.timezone branch is unimplemented causing
valid requests to fall through; implement the timezone update by validating
payload.timezone (ensure non-empty and matches allowed timezone format/list),
then call the existing user update flow (e.g., invoke the repository/DAO method
such as Users.updateTimezone or the service function that updates user fields)
to persist the timezone for the target userId, handle and log DB errors, and
return the appropriate success response; if no update helper exists, add a small
repository method to update only the timezone and wire it into the handler that
checks payload.timezone so the request does not return BAD_REQUEST when timezone
is provided.
- Around line 147-168: The early return after handling payload.phoneNumber
causes payload.timezone to be ignored; modify the logic in the block that
references payload.phoneNumber and payload.timezone so both fields are processed
before returning: if both are present, either call scim:updateUser once with a
combined update object (e.g., include phoneNumber and timezone) or perform two
updates sequentially (first phone via scim:updateUser as currently done and then
timezone with scim:updateUser using userInfo.userId), propagate and handle
errors using the existing getStatusCode/getErrorMessage flow, and finally return
a combined response that includes both processPhoneNumber(updatedUser) and the
updated timezone value instead of returning immediately after the phone update.

Comment thread apps/customer-portal/backend/service.bal Outdated
Comment thread apps/customer-portal/backend/service.bal Outdated
@Rashmika998
Rashmika998 force-pushed the customer-portal-milestone-1-dev-1 branch from cc303bb to 62bcc31 Compare January 27, 2026 07:22
@Rashmika998 Rashmika998 changed the title [Customer Portal] Implement User Phone number Functionality [Customer Portal] Implement User Phone Number Update Functionality Jan 27, 2026
@Rashmika998
Rashmika998 force-pushed the customer-portal-milestone-1-dev-1 branch from b053980 to 70899e9 Compare January 27, 2026 08:58

@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: 2

🤖 Fix all issues with AI agents
In `@apps/customer-portal/backend/modules/scim/types.bal`:
- Around line 60-66: The SCIM UserUpdatePayload type contains an unused password
field; remove the password?: string; property from the public type
UserUpdatePayload in types.bal so the SCIM payload matches the actual PATCH
handling (which only uses Phone phoneNumber and timezone from the backend
payload) and update any related documentation/comments referencing
UserUpdatePayload/password to avoid stale API contract descriptions.

In `@apps/customer-portal/backend/types.bal`:
- Around line 106-126: The types UserUpdatePayload and UpdatedUser have
inconsistent field names: UserUpdatePayload declares timezone while UpdatedUser
declares timeZone; align them to a single naming convention (prefer camelCase:
timeZone) by renaming the timezone property in UserUpdatePayload to timeZone and
updating any references/validation (including the `@constraint` on phoneNumber) so
both record types use the identical field name (timeZone) and consumers map
consistently.

Comment thread apps/customer-portal/backend/modules/scim/types.bal
Comment thread apps/customer-portal/backend/types.bal
@Rashmika998 Rashmika998 moved this from Todo to In Progress in Customer Portal Development Jan 27, 2026
Comment thread apps/customer-portal/backend/service.bal Outdated
Comment thread apps/customer-portal/backend/service.bal Outdated
Comment thread apps/customer-portal/backend/service.bal Outdated
@Rashmika998
Rashmika998 force-pushed the customer-portal-milestone-1-dev-1 branch from fff8342 to a2aa1ae Compare January 27, 2026 16:14
Comment thread apps/customer-portal/backend/types.bal
Comment thread apps/customer-portal/backend/utils.bal Outdated
Comment thread apps/customer-portal/backend/utils.bal Outdated
Comment thread apps/customer-portal/backend/modules/authorization/types.bal
@shayanmalinda
shayanmalinda merged commit e8c5f02 into wso2-open-operations:customer-portal-milestone-1 Jan 27, 2026
1 check passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Customer Portal Development Jan 27, 2026
@Rashmika998 Rashmika998 moved this from Done to Staging Deployed in Customer Portal Development Jan 28, 2026
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/Task General task that does not fit into other categories

Projects

Status: Staging Deployed

Development

Successfully merging this pull request may close these issues.

2 participants