using System.Security.Claims; using AMREZ.EOP.Abstractions.Applications.UseCases.Authentications; using AMREZ.EOP.Contracts.DTOs.Authentications.AddEmailIdentity; using AMREZ.EOP.Contracts.DTOs.Authentications.ChangePassword; using AMREZ.EOP.Contracts.DTOs.Authentications.DisableMfa; using AMREZ.EOP.Contracts.DTOs.Authentications.EnableTotp; using AMREZ.EOP.Contracts.DTOs.Authentications.Login; using AMREZ.EOP.Contracts.DTOs.Authentications.Logout; using AMREZ.EOP.Contracts.DTOs.Authentications.LogoutAll; using AMREZ.EOP.Contracts.DTOs.Authentications.Register; using AMREZ.EOP.Contracts.DTOs.Authentications.VerifyEmail; using AMREZ.EOP.Domain.Shared.Contracts; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Mvc; namespace AMREZ.EOP.API.Controllers; [ApiController] [Route("api/[controller]")] public class AuthenticationController : ControllerBase { private readonly ILoginUseCase _login; private readonly IRegisterUseCase _register; private readonly IChangePasswordUseCase _changePassword; private readonly IAddEmailIdentityUseCase _addEmail; private readonly IVerifyEmailUseCase _verifyEmail; private readonly IEnableTotpUseCase _enableTotp; private readonly IDisableMfaUseCase _disableMfa; private readonly ILogoutUseCase _logout; private readonly ILogoutAllUseCase _logoutAll; public AuthenticationController( ILoginUseCase login, IRegisterUseCase register, IChangePasswordUseCase changePassword) { _login = login; _register = register; _changePassword = changePassword; } [HttpPost("login")] public async Task PostLogin([FromBody] LoginRequest body, CancellationToken ct) { var res = await _login.ExecuteAsync(body, ct); if (res is null) return Unauthorized(new { message = "Invalid credentials" }); var claims = new List { new(ClaimTypes.NameIdentifier, res.UserId.ToString()), new(ClaimTypes.Name, string.IsNullOrWhiteSpace(res.DisplayName) ? res.Email : res.DisplayName), new(ClaimTypes.Email, res.Email), new("tenant", res.TenantId) }; var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, AuthPolicies.Scheme)); await HttpContext.SignInAsync(AuthPolicies.Scheme, principal); return Ok(res); } [HttpPost("register")] public async Task Register([FromBody] RegisterRequest body, CancellationToken ct) { var res = await _register.ExecuteAsync(body, ct); if (res is null) return Conflict(new { message = "Email already exists or tenant not found" }); return Created($"/api/authentication/users/{res.UserId}", res); } [HttpPost("change-password")] public async Task ChangePassword([FromBody] ChangePasswordRequest body, CancellationToken ct) { var ok = await _changePassword.ExecuteAsync(body, ct); if (!ok) return BadRequest(new { message = "Change password failed" }); return NoContent(); } [HttpPost("logout")] public async Task Logout() { await HttpContext.SignOutAsync(AuthPolicies.Scheme); return NoContent(); } [HttpPost("email")] public async Task AddEmail([FromBody] AddEmailIdentityRequest body, CancellationToken ct) { var ok = await _addEmail.ExecuteAsync(body, ct); if (!ok) return BadRequest(new { message = "Cannot add email identity" }); return NoContent(); } [HttpPost("email/verify")] public async Task VerifyEmail([FromBody] VerifyEmailRequest body, CancellationToken ct) { var ok = await _verifyEmail.ExecuteAsync(body, ct); if (!ok) return BadRequest(new { message = "Verify email failed" }); return NoContent(); } [HttpPost("totp/enable")] public async Task EnableTotp([FromBody] EnableTotpRequest body, CancellationToken ct) { var res = await _enableTotp.ExecuteAsync(body, ct); if (res is null) return BadRequest(new { message = "Enable TOTP failed" }); return Ok(res); } [HttpPost("disable")] public async Task DisableMfa([FromBody] DisableMfaRequest body, CancellationToken ct) { var ok = await _disableMfa.ExecuteAsync(body, ct); if (!ok) return BadRequest(new { message = "Disable MFA failed" }); return NoContent(); } [HttpPost("revoke")] public async Task Revoke([FromBody] LogoutRequest body, CancellationToken ct) { var ok = await _logout.ExecuteAsync(body, ct); if (!ok) return NotFound(new { message = "Session not found" }); return NoContent(); } [HttpPost("revoke-all")] public async Task RevokeAll([FromBody] LogoutAllRequest body, CancellationToken ct) { var n = await _logoutAll.ExecuteAsync(body, ct); return Ok(new { revoked = n }); } }