using MicCheck.Api.Common.Security.Authorization; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.RateLimiting; namespace MicCheck.Api.Users; [ApiController] [Route("api/v1/user")] [Authorize(Policy = AuthorizationPolicies.AdminApiAccess)] [EnableRateLimiting("AdminApi")] public class UsersController(UserService userService) : ControllerBase { [HttpGet("{id:int}")] public async Task> GetById(int id, CancellationToken ct) { var user = await userService.FindByIdAsync(id, ct); return user is null ? NotFound() : Ok(UserResponse.From(user)); } [HttpGet("me")] public async Task> GetMe(CancellationToken ct) { var userId = GetCurrentUserId(); if (userId is null) return Unauthorized(); var user = await userService.FindByIdAsync(userId.Value, ct); return user is null ? NotFound() : Ok(UserResponse.From(user)); } [HttpPut("me")] public async Task> UpdateMe(UpdateProfileRequest request, CancellationToken ct) { var userId = GetCurrentUserId(); if (userId is null) return Unauthorized(); if (string.IsNullOrWhiteSpace(request.FirstName) || string.IsNullOrWhiteSpace(request.LastName) || string.IsNullOrWhiteSpace(request.Email)) return BadRequest("First name, last name, and email are required."); var result = await userService.UpdateProfileAsync( userId.Value, request.FirstName.Trim(), request.LastName.Trim(), request.Email.Trim(), ct); if (result.EmailConflict) return Conflict("Email is already in use."); return result.User is null ? NotFound() : Ok(UserResponse.From(result.User)); } [HttpPost("me/change-password")] public async Task ChangePassword(ChangePasswordRequest request, CancellationToken ct) { var userId = GetCurrentUserId(); if (userId is null) return Unauthorized(); if (string.IsNullOrWhiteSpace(request.CurrentPassword) || string.IsNullOrWhiteSpace(request.NewPassword)) return BadRequest("Current and new passwords are required."); var success = await userService.ChangePasswordAsync(userId.Value, request.CurrentPassword, request.NewPassword, ct); return success ? NoContent() : BadRequest("Current password is incorrect."); } private int? GetCurrentUserId() { var claim = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value; return int.TryParse(claim, out var id) ? id : null; } }