129 lines
4.2 KiB
C#
129 lines
4.2 KiB
C#
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<ApplicationUser> _userManager;
|
|
private readonly ITenantProvider _tenantProvider;
|
|
private readonly IConfiguration _config;
|
|
|
|
public AuthController(UserManager<ApplicationUser> userManager, ITenantProvider tenantProvider, IConfiguration config)
|
|
{
|
|
_userManager = userManager;
|
|
_tenantProvider = tenantProvider;
|
|
_config = config;
|
|
}
|
|
|
|
[HttpPost("register")]
|
|
[Authorize(Roles = "admin")]
|
|
public async Task<IActionResult> 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<IActionResult> 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<string> 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<Claim>
|
|
{
|
|
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);
|
|
}
|
|
}
|