Skip to content

Feat/update update profile dto#84

Merged
KietPham-VN merged 2 commits into
mainfrom
feat/update-update-profile-dto
May 15, 2026
Merged

Feat/update update profile dto#84
KietPham-VN merged 2 commits into
mainfrom
feat/update-update-profile-dto

Conversation

@EricN2907

@EricN2907 EricN2907 commented May 15, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Fixed authorization error handling in API responses to prevent potential issues
    • Profile update endpoint now returns complete user profile information instead of a basic success message
  • Improvements

    • Profile picture URLs are now properly resolved and included in profile update responses

Review Change Stack

EricN2907 added 2 commits May 14, 2026 21:19
- Remove problematic logic in EndpointExtensions that returned 404 for successful responses with null data.
- Update UpdateProfileHandler to return success message in the Data field.
@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The PR updates the user profile update endpoint to return a complete UserDto instead of a simple string response. The handler now loads user roles, resolves the profile picture URL from storage, and returns the full user data object, while endpoint serialization logic is adjusted to remove the null-data 404 check and guard authorization message null references.

Changes

Profile Update Response Type

Layer / File(s) Summary
UpdateProfileCommand contract
backend/Src/PIED_LMS.Contract/Services/Identity/Command.cs
UpdateProfileCommand return type changed from IRequest<ServiceResponse<string>> to IRequest<ServiceResponse<UserDto>>.
UpdateProfileHandler implementation
backend/Src/PIED_LMS.Application/UserCases/Commands/Identity/UpdateProfileHandler.cs
Constructor adds ILogger<UpdateProfileHandler> dependency. Handle method now returns ServiceResponse<UserDto>, loads user roles, fetches and resolves profile picture URL from storage with warning logging on failure, and constructs UserDto with updated user fields and resolved picture URL.
Endpoint response metadata and serialization
backend/Src/PIED_LMS.Presentation/APIs/AuthenticationEndpoints.cs, backend/Src/PIED_LMS.Presentation/Extensions/EndpointExtensions.cs
UpdateProfile endpoint OpenAPI metadata changed from string to UserDto. Response serialization no longer returns 404 NotFound when result data is null on success; authorization message checks now guard against null before calling Contains.

Sequence Diagram

sequenceDiagram
  participant Client
  participant UpdateProfile as UpdateProfile Endpoint
  participant UpdateProfileHandler
  participant UserManager
  participant FileStorageService
  participant Response as ToActionResult

  Client->>UpdateProfile: PUT /api/auth/profile
  UpdateProfile->>UpdateProfileHandler: Handle(UpdateProfileCommand)
  UpdateProfileHandler->>UserManager: FindByIdAsync(userId)
  alt User not found
    UpdateProfileHandler-->>UpdateProfile: ServiceResponse<UserDto> failure
  else User found
    UpdateProfileHandler->>UserManager: UpdateAsync(user)
    alt Update failed
      UpdateProfileHandler-->>UpdateProfile: ServiceResponse<UserDto> failure
    else Update succeeded
      UpdateProfileHandler->>UserManager: GetRolesAsync(user)
      UpdateProfileHandler->>FileStorageService: GetFileUrlAsync(profilePictureUrl)
      UpdateProfileHandler->>UpdateProfileHandler: Build UserDto with roles and picture URL
      UpdateProfileHandler-->>UpdateProfile: ServiceResponse<UserDto> success with UserDto
    end
  end
  UpdateProfile->>Response: ToActionResult<UserDto>(result)
  Response-->>Client: 200 OK with UserDto
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

Profile updates now shine so bright, ✨
UserDto returned, not just text in flight,
Roles and pictures fully resolved,
The API contract now evolved,
A proper response for each user's plight.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Feat/update update profile dto' is partially related to the changeset but lacks clarity and precision. It contains awkward phrasing ('update update') and does not clearly convey the primary change: returning UserDto instead of string from the UpdateProfile endpoint. Revise the title to be more specific and grammatically correct, such as 'Return UserDto from UpdateProfile instead of string' or 'Update UpdateProfile handler to return UserDto with profile data'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/update-update-profile-dto

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.

Comment on lines +74 to +78
catch (Exception ex)
{
logger.LogWarning(ex, "Failed to resolve profile picture URL for user {UserId}. Key: {Key}", user.Id,
user.ProfilePictureUrl);
}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/Src/PIED_LMS.Presentation/Extensions/EndpointExtensions.cs (1)

9-12: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Multiple handlers return successful responses with null data — verify clients handle 200 OK instead of 404.

Successful responses now unconditionally return 200 OK regardless of whether result.Data is null. This affects handlers that return ServiceResponse<string>(true, message) without providing data, since the Data parameter defaults to null. Found in:

  • UpdateCourseHandler, DeleteCourseHandler
  • UpdateQuestionQuizHandler, DeleteQuestionQuizHandler
  • AssignMentorsHandler

Previously, these null data responses likely returned 404 Not Found when clients expected them. Verify that clients consuming these endpoints do not depend on 404 responses. Update handlers to return Success = false with appropriate error code if a 404 response is semantically required, rather than relying on null data detection.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/Src/PIED_LMS.Presentation/Extensions/EndpointExtensions.cs` around
lines 9 - 12, Handlers such as UpdateCourseHandler, DeleteCourseHandler,
UpdateQuestionQuizHandler, DeleteQuestionQuizHandler, and AssignMentorsHandler
are returning Results.Ok(result) even when result.Data is null, causing 200 OK
where a 404 was expected; update those handlers to detect missing resources and
either set ServiceResponse.Success = false with an appropriate error
code/message or return Results.NotFound(...) (instead of Results.Ok) when
result.Data == null so clients receive a 404, and ensure the code paths that
construct ServiceResponse (e.g., ServiceResponse<string>(true, message)) are
adjusted to reflect failure when no resource exists.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@backend/Src/PIED_LMS.Application/UserCases/Commands/Identity/UpdateProfileHandler.cs`:
- Around line 67-79: The response currently resolves the profile URL later and
can return null even after a successful upload; modify UpdateProfileHandler to
call fileStorageService.GetFileUrlAsync immediately after
fileStorageService.SaveFileAsync (use SaveFileAsync and GetFileUrlAsync) when a
new picture is uploaded, capture the resolved URL and use that resolved value
when constructing the UserDto (while still persisting the storage key in
user.ProfilePictureUrl), and if GetFileUrlAsync fails after SaveFileAsync log
the error and include the storage key as a fallback in the response so clients
are not misled by a null profilePicUrl.
- Line 88: The code passes roles.ToList() to the update call but GetRolesAsync
already returns an IList<string>, so remove the redundant allocation and pass
the existing roles collection directly; locate the roles variable (result of
UserManager.GetRolesAsync) in UpdateProfileHandler (Handle method) and replace
the roles.ToList() usage with roles.

---

Outside diff comments:
In `@backend/Src/PIED_LMS.Presentation/Extensions/EndpointExtensions.cs`:
- Around line 9-12: Handlers such as UpdateCourseHandler, DeleteCourseHandler,
UpdateQuestionQuizHandler, DeleteQuestionQuizHandler, and AssignMentorsHandler
are returning Results.Ok(result) even when result.Data is null, causing 200 OK
where a 404 was expected; update those handlers to detect missing resources and
either set ServiceResponse.Success = false with an appropriate error
code/message or return Results.NotFound(...) (instead of Results.Ok) when
result.Data == null so clients receive a 404, and ensure the code paths that
construct ServiceResponse (e.g., ServiceResponse<string>(true, message)) are
adjusted to reflect failure when no resource exists.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 09d00aa2-bf10-484e-982a-0f124a6f414b

📥 Commits

Reviewing files that changed from the base of the PR and between a9a89f5 and f70144f.

📒 Files selected for processing (4)
  • backend/Src/PIED_LMS.Application/UserCases/Commands/Identity/UpdateProfileHandler.cs
  • backend/Src/PIED_LMS.Contract/Services/Identity/Command.cs
  • backend/Src/PIED_LMS.Presentation/APIs/AuthenticationEndpoints.cs
  • backend/Src/PIED_LMS.Presentation/Extensions/EndpointExtensions.cs

Comment on lines +67 to +79
string? profilePicUrl = null;
if (!string.IsNullOrWhiteSpace(user.ProfilePictureUrl))
{
try
{
profilePicUrl = await fileStorageService.GetFileUrlAsync(user.ProfilePictureUrl);
}
catch (Exception ex)
{
logger.LogWarning(ex, "Failed to resolve profile picture URL for user {UserId}. Key: {Key}", user.Id,
user.ProfilePictureUrl);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Profile picture URL resolution failure returns incomplete data after successful upload.

If a new profile picture is uploaded successfully (lines 45-52) and stored in the database (line 57), but GetFileUrlAsync fails when building the response (line 72), the returned UserDto will have a null profilePicUrl even though the upload succeeded. This misleads the client into believing the upload failed when it actually succeeded.

Consider one of these approaches:

  1. Call GetFileUrlAsync immediately after SaveFileAsync (line 50) to validate the URL is retrievable before saving to the database.
  2. Return the storage key instead of the resolved URL, letting clients resolve URLs on subsequent requests.
  3. Document that a null profilePicUrl in the response doesn't necessarily mean upload failed, but this is poor UX.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@backend/Src/PIED_LMS.Application/UserCases/Commands/Identity/UpdateProfileHandler.cs`
around lines 67 - 79, The response currently resolves the profile URL later and
can return null even after a successful upload; modify UpdateProfileHandler to
call fileStorageService.GetFileUrlAsync immediately after
fileStorageService.SaveFileAsync (use SaveFileAsync and GetFileUrlAsync) when a
new picture is uploaded, capture the resolved URL and use that resolved value
when constructing the UserDto (while still persisting the storage key in
user.ProfilePictureUrl), and if GetFileUrlAsync fails after SaveFileAsync log
the error and include the storage key as a fallback in the response so clients
are not misled by a null profilePicUrl.

user.LastName,
user.IsActive,
user.CreatedAt,
roles.ToList(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Unnecessary list conversion.

GetRolesAsync already returns IList<string>. The ToList() call creates a redundant copy.

♻️ Proposed refactor
-            roles.ToList(),
+            roles,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
roles.ToList(),
roles,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@backend/Src/PIED_LMS.Application/UserCases/Commands/Identity/UpdateProfileHandler.cs`
at line 88, The code passes roles.ToList() to the update call but GetRolesAsync
already returns an IList<string>, so remove the redundant allocation and pass
the existing roles collection directly; locate the roles variable (result of
UserManager.GetRolesAsync) in UpdateProfileHandler (Handle method) and replace
the roles.ToList() usage with roles.

@KietPham-VN KietPham-VN merged commit 8c04ed1 into main May 15, 2026
7 checks passed
@KietPham-VN KietPham-VN deleted the feat/update-update-profile-dto branch May 15, 2026 05:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants