Fix tenant-aware login resolution

This commit is contained in:
Eduardo Lopes 2026-01-26 09:15:08 -03:00
parent 9ff61cf937
commit bdb952c0e5
3 changed files with 39 additions and 7 deletions

View File

@ -72,16 +72,34 @@ public class AuthController : ControllerBase
[HttpPost("login")] [HttpPost("login")]
public async Task<IActionResult> Login(LoginRequest req) public async Task<IActionResult> Login(LoginRequest req)
{ {
// ✅ normaliza e evita null
var email = (req.Email ?? "").Trim().ToLowerInvariant(); var email = (req.Email ?? "").Trim().ToLowerInvariant();
var password = req.Password ?? ""; var password = req.Password ?? "";
var normalizedEmail = _userManager.NormalizeEmail(email); var normalizedEmail = _userManager.NormalizeEmail(email);
// ✅ SOLUÇÃO A: ignora filtros globais (multi-tenant / HasQueryFilter) var tenantId = ResolveTenantId(req);
// e pega 1 usuário (pra você logar logo). ApplicationUser? user;
var user = await _userManager.Users
if (tenantId == null)
{
var users = await _userManager.Users
.IgnoreQueryFilters() .IgnoreQueryFilters()
.FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail); .Where(u => u.NormalizedEmail == normalizedEmail)
.ToListAsync();
if (users.Count == 0)
return Unauthorized("Credenciais inválidas.");
if (users.Count > 1)
return BadRequest("Informe o tenant para realizar o login.");
user = users[0];
}
else
{
user = await _userManager.Users
.IgnoreQueryFilters()
.FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail && u.TenantId == tenantId);
}
if (user == null) if (user == null)
return Unauthorized("Credenciais inválidas."); return Unauthorized("Credenciais inválidas.");
@ -97,6 +115,15 @@ public class AuthController : ControllerBase
return Ok(new AuthResponse(token)); return Ok(new AuthResponse(token));
} }
private Guid? ResolveTenantId(LoginRequest req)
{
if (req.TenantId.HasValue)
return req.TenantId.Value;
var headerValue = Request.Headers["X-Tenant-Id"].FirstOrDefault();
return Guid.TryParse(headerValue, out var parsed) ? parsed : null;
}
private async Task<string> GenerateJwtAsync(ApplicationUser user) private async Task<string> GenerateJwtAsync(ApplicationUser user)
{ {
var key = _config["Jwt:Key"]!; var key = _config["Jwt:Key"]!;

View File

@ -1,3 +1,3 @@
namespace line_gestao_api.Dtos; namespace line_gestao_api.Dtos;
public record LoginRequest(string Email, string Password); public record LoginRequest(string Email, string Password, Guid? TenantId = null);

View File

@ -16,11 +16,16 @@ public class TenantMiddleware
Guid? tenantId = null; Guid? tenantId = null;
var claim = context.User.FindFirst("tenantId")?.Value var claim = context.User.FindFirst("tenantId")?.Value
?? context.User.FindFirst("tenant")?.Value; ?? context.User.FindFirst("tenant")?.Value;
var headerValue = context.Request.Headers["X-Tenant-Id"].FirstOrDefault();
if (Guid.TryParse(claim, out var parsed)) if (Guid.TryParse(claim, out var parsed))
{ {
tenantId = parsed; tenantId = parsed;
} }
else if (Guid.TryParse(headerValue, out var headerTenant))
{
tenantId = headerTenant;
}
tenantProvider.SetTenantId(tenantId); tenantProvider.SetTenantId(tenantId);