using System.IdentityModel.Tokens.Jwt; using Distribution.Features.User; using Distribution.Infra.Authorization; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace Distribution.Features.Auth; [ApiController] [Route("api/auth")] public class AuthController(AuthService service, ICurrentUserService currentUser, IUserRepository userRepo) : ControllerBase { private static IActionResult ToActionResult(AuthHexResponse result) => result.Success ? new OkObjectResult(result) : new ObjectResult(result) { StatusCode = result.StatusCode is >= 400 and < 600 ? result.StatusCode : 401 }; [HttpPost("login")] [AllowAnonymous] public async Task Login(LoginRequest request, CancellationToken ct) { var result = await service.LoginAsync(request, ct); if (!result.Success || result.Data is not { } data) return ToActionResult(result); string? token = null; TimeSpan maxAge = TimeSpan.FromHours(1); if (data.TryGetProperty("accessToken", out var tokenEl)) token = tokenEl.GetString(); if (data.TryGetProperty("expiresIn", out var expEl)) maxAge = TimeSpan.FromSeconds(expEl.GetInt32()); if (!string.IsNullOrEmpty(token)) { Response.Cookies.Append("access-token", token, new CookieOptions { HttpOnly = true, SameSite = SameSiteMode.Lax, Path = "/", MaxAge = maxAge, Secure = Request.IsHttps, }); } MeResponse? profile = null; if (!string.IsNullOrEmpty(token)) { var jwt = new JwtSecurityTokenHandler().ReadJwtToken(token); var userIdStr = jwt.Claims.FirstOrDefault(c => c.Type == "UserId")?.Value; if (Guid.TryParse(userIdStr, out var userId)) { var user = await userRepo.GetByIdAsync(userId); if (user is not null) profile = new MeResponse( user.Id, user.Username, user.FK_RoleId, user.Role?.Name ?? string.Empty, user.Role?.Level ?? 0); } } return Ok(new { result.StatusCode, result.Success, result.Message, result.Data, profile }); } [HttpPost("register")] [AllowAnonymous] public async Task Register(RegisterRequest request, CancellationToken ct) => ToActionResult(await service.RegisterAsync(request, ct)); [HttpGet("me")] [Authorize] public async Task Me() { if (currentUser.UserId is null) return Unauthorized(); var user = await userRepo.GetByIdAsync(currentUser.UserId.Value); if (user is null) return Unauthorized(); return Ok(new MeResponse( user.Id, user.Username, user.FK_RoleId, user.Role?.Name ?? string.Empty, user.Role?.Level ?? 0)); } [HttpPost("logout")] [AllowAnonymous] public IActionResult Logout() { Response.Cookies.Delete("access-token", new CookieOptions { HttpOnly = true, SameSite = SameSiteMode.Lax, Path = "/", Secure = Request.IsHttps, }); return Ok(new { success = true }); } }