From 8f18166dbf41273f3ff3070e06a1cf902d3d60a9 Mon Sep 17 00:00:00 2001 From: Chris Chen Date: Tue, 23 Jun 2026 19:54:20 -0700 Subject: [PATCH] feat(auth): add POST /api/auth/change-password endpoint --- API/ROLAC.API/Controllers/AuthController.cs | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/API/ROLAC.API/Controllers/AuthController.cs b/API/ROLAC.API/Controllers/AuthController.cs index e718c20..d0ef6d5 100644 --- a/API/ROLAC.API/Controllers/AuthController.cs +++ b/API/ROLAC.API/Controllers/AuthController.cs @@ -154,6 +154,38 @@ public class AuthController : ControllerBase return NoContent(); } + // ------------------------------------------------------------------------- + // POST /api/auth/change-password + // ------------------------------------------------------------------------- + + /// + /// Changes the current user's password. Requires the correct current password and a + /// new password meeting the configured policy. On success the user's *other* sessions + /// are revoked while the current session stays active. + /// + [HttpPost("change-password")] + [Authorize] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task ChangePassword([FromBody] ChangePasswordRequest request) + { + var userId = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub"); + if (string.IsNullOrEmpty(userId)) + return Unauthorized(); + + var currentRefresh = Request.Cookies[CookieName]; + var result = await _authService.ChangePasswordAsync( + userId, request.CurrentPassword, request.NewPassword, currentRefresh); + + if (!result.Succeeded) + return BadRequest(new + { + message = string.Join(" ", result.Errors.Select(error => error.Description)), + }); + + return NoContent(); + } + // ------------------------------------------------------------------------- // Private helpers // -------------------------------------------------------------------------