using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using StickyBoard.Api.Common; using StickyBoard.Core.Common.Exceptions; using StickyBoard.Core.DTOs.Common; using StickyBoard.Core.DTOs.UsersAndAuth; using StickyBoard.Core.Services.UsersAndAuth.Contracts; namespace StickyBoard.Api.Controllers; [ApiController] [Route("api/[controller]")] public sealed class AuthController : ControllerBase { private readonly IAuthService _auth; public AuthController(IAuthService auth) { _auth = auth; } // ============================================================ // REGISTER // ============================================================ [HttpPost("register")] [AllowAnonymous] public async Task>> Register( [FromBody] RegisterDto dto, CancellationToken ct) { try { var result = await _auth.RegisterAsync(dto, ct); return Ok(ApiResponseDto.Ok(result)); } catch (ValidationException ex) { return BadRequest(ApiResponseDto.Fail(ex.Message)); } } // ============================================================ // LOGIN // ============================================================ [HttpPost("login")] [AllowAnonymous] public async Task>> Login( [FromBody] LoginDto dto, CancellationToken ct) { try { var result = await _auth.LoginAsync(dto, ct); return Ok(ApiResponseDto.Ok(result)); } catch (AuthInvalidException ex) { return Unauthorized(ApiResponseDto.Fail(ex.Message)); } catch (ValidationException ex) { return BadRequest(ApiResponseDto.Fail(ex.Message)); } } // ============================================================ // REFRESH TOKEN // ============================================================ [HttpPost("refresh")] [AllowAnonymous] public async Task>> Refresh( [FromBody] RefreshTokenRequestDto dto, CancellationToken ct) { try { var result = await _auth.RefreshAsync(dto, ct); return Ok(ApiResponseDto.Ok(result)); } catch (AuthExpiredException ex) { return Unauthorized(ApiResponseDto.Fail(ex.Message)); } catch (ValidationException ex) { return BadRequest(ApiResponseDto.Fail(ex.Message)); } } // ============================================================ // LOGOUT (Revoke all tokens for this user) // ============================================================ [HttpPost("logout")] [Authorize] public async Task>> Logout(CancellationToken ct) { var userId = User.GetUserId(); if (userId == Guid.Empty) return Unauthorized(ApiResponseDto.Fail("Invalid or missing token.")); await _auth.LogoutAsync(userId, ct); return Ok(ApiResponseDto.Ok(new { success = true })); } // ============================================================ // ME (Current authenticated user) // ============================================================ [HttpGet("me")] [Authorize] public async Task>> Me(CancellationToken ct) { var userId = User.GetUserId(); if (userId == Guid.Empty) return Unauthorized(ApiResponseDto.Fail("Invalid or missing token.")); var me = await _auth.GetSelfAsync(userId, ct); if (me is null) return NotFound(ApiResponseDto.Fail("User not found.")); return Ok(ApiResponseDto.Ok(me)); } // ============================================================ // CLEANUP REVOKED TOKENS (Admin only) // ============================================================ [HttpPost("cleanup")] [Authorize(Roles = "admin")] public async Task>> CleanupRevokedTokens(CancellationToken ct) { var deleted = await _auth.CleanupRevokedTokensAsync(ct); return Ok(ApiResponseDto.Ok(new { deleted })); } }