using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using line_gestao_api.Dtos; using line_gestao_api.Models; using line_gestao_api.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; namespace line_gestao_api.Controllers; [ApiController] [Route("auth")] public class AuthController : ControllerBase { private readonly UserManager _userManager; private readonly ITenantProvider _tenantProvider; private readonly IConfiguration _config; public AuthController(UserManager userManager, ITenantProvider tenantProvider, IConfiguration config) { _userManager = userManager; _tenantProvider = tenantProvider; _config = config; } [HttpPost("register")] [Authorize(Roles = "admin")] public async Task Register(RegisterRequest req) { if (req.Password != req.ConfirmPassword) return BadRequest("As senhas não conferem."); var tenantId = _tenantProvider.TenantId; if (tenantId == null) { return Unauthorized("Tenant inválido."); } var email = req.Email.Trim().ToLowerInvariant(); var normalizedEmail = _userManager.NormalizeEmail(email); var exists = await _userManager.Users.AnyAsync(u => u.NormalizedEmail == normalizedEmail && u.TenantId == tenantId); if (exists) return BadRequest("E-mail já cadastrado."); var user = new ApplicationUser { Name = req.Name.Trim(), Email = email, UserName = email, TenantId = tenantId.Value, IsActive = true, EmailConfirmed = true }; var createResult = await _userManager.CreateAsync(user, req.Password); if (!createResult.Succeeded) { return BadRequest(createResult.Errors.Select(e => e.Description).ToList()); } await _userManager.AddToRoleAsync(user, "leitura"); var token = await GenerateJwtAsync(user); return Ok(new AuthResponse(token)); } [HttpPost("login")] public async Task Login(LoginRequest req) { var email = req.Email.Trim().ToLowerInvariant(); var normalizedEmail = _userManager.NormalizeEmail(email); var users = await _userManager.Users .IgnoreQueryFilters() .Where(u => u.NormalizedEmail == normalizedEmail) .ToListAsync(); if (users.Count != 1) return Unauthorized("Credenciais inválidas."); var user = users[0]; if (!user.IsActive) return Unauthorized("Usuário desativado."); var valid = await _userManager.CheckPasswordAsync(user, req.Password); if (!valid) return Unauthorized("Credenciais inválidas."); var token = await GenerateJwtAsync(user); return Ok(new AuthResponse(token)); } private async Task GenerateJwtAsync(ApplicationUser user) { var key = _config["Jwt:Key"]!; var issuer = _config["Jwt:Issuer"]!; var audience = _config["Jwt:Audience"]!; var expiresMinutes = int.Parse(_config["Jwt:ExpiresMinutes"]!); var roles = await _userManager.GetRolesAsync(user); var claims = new List { new(JwtRegisteredClaimNames.Sub, user.Id.ToString()), new(JwtRegisteredClaimNames.Email, user.Email ?? string.Empty), new("name", user.Name), new("tenantId", user.TenantId.ToString()) }; claims.AddRange(roles.Select(r => new Claim(ClaimTypes.Role, r))); var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)); var creds = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: issuer, audience: audience, claims: claims, expires: DateTime.UtcNow.AddMinutes(expiresMinutes), signingCredentials: creds ); return new JwtSecurityTokenHandler().WriteToken(token); } }