Add Master Data
This commit is contained in:
@@ -32,52 +32,71 @@ public sealed class IssueTokenPairUseCase : IIssueTokenPairUseCase
|
||||
}
|
||||
|
||||
public async Task<IssueTokenPairResponse> ExecuteAsync(IssueTokenPairRequest request, CancellationToken ct = default)
|
||||
{
|
||||
var http = _http.HttpContext ?? throw new InvalidOperationException("No HttpContext");
|
||||
|
||||
var tenantId = request.TenantId;
|
||||
|
||||
// ---- สร้าง/บันทึก refresh session ----
|
||||
var refreshRaw = Convert.ToBase64String(RandomNumberGenerator.GetBytes(64));
|
||||
var refreshHash = Sha256(refreshRaw);
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
|
||||
var session = await _users.CreateSessionAsync(new UserSession
|
||||
{
|
||||
var http = _http.HttpContext ?? throw new InvalidOperationException("No HttpContext");
|
||||
Id = Guid.NewGuid(),
|
||||
TenantId = tenantId,
|
||||
UserId = request.UserId,
|
||||
RefreshTokenHash = refreshHash,
|
||||
IssuedAt = now,
|
||||
ExpiresAt = now.AddDays(RefreshDays),
|
||||
DeviceId = http.Request.Headers["X-Device-Id"].FirstOrDefault(),
|
||||
UserAgent = http.Request.Headers["User-Agent"].FirstOrDefault(),
|
||||
IpAddress = http.Connection.RemoteIpAddress?.ToString()
|
||||
}, ct);
|
||||
|
||||
var tenantId = request.TenantId;
|
||||
// ---- เวอร์ชัน/สแตมป์ความปลอดภัย ----
|
||||
var tv = await _users.GetTenantTokenVersionAsync(tenantId, ct);
|
||||
var sstamp = await _users.GetUserSecurityStampAsync(request.UserId, ct) ?? string.Empty;
|
||||
|
||||
var refreshRaw = Convert.ToBase64String(RandomNumberGenerator.GetBytes(64));
|
||||
var refreshHash = Sha256(refreshRaw);
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
// ---- เตรียม claims พื้นฐาน ----
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new("sub", request.UserId.ToString()),
|
||||
new("email", request.Email),
|
||||
new("tenant", request.Tenant), // tenantKey ที่ FE ใช้
|
||||
new("tenant_id", tenantId.ToString()),
|
||||
new("sid", session.Id.ToString()),
|
||||
new("jti", Guid.NewGuid().ToString("N")),
|
||||
new("tv", tv),
|
||||
new("sstamp", sstamp),
|
||||
new("iat", now.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)
|
||||
};
|
||||
|
||||
var session = await _users.CreateSessionAsync(new UserSession
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
TenantId = tenantId,
|
||||
UserId = request.UserId,
|
||||
RefreshTokenHash = refreshHash,
|
||||
IssuedAt = now,
|
||||
ExpiresAt = now.AddDays(RefreshDays),
|
||||
DeviceId = http.Request.Headers["X-Device-Id"].FirstOrDefault(),
|
||||
UserAgent = http.Request.Headers["User-Agent"].FirstOrDefault(),
|
||||
IpAddress = http.Connection.RemoteIpAddress?.ToString()
|
||||
}, ct);
|
||||
|
||||
var tv = await _users.GetTenantTokenVersionAsync(tenantId, ct);
|
||||
var sstamp = await _users.GetUserSecurityStampAsync(request.UserId, ct) ?? string.Empty;
|
||||
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new("sub", request.UserId.ToString()),
|
||||
new("tenant_id", tenantId.ToString()),
|
||||
new("sid", session.Id.ToString()),
|
||||
new("jti", Guid.NewGuid().ToString("N")),
|
||||
new("tv", tv),
|
||||
new("sstamp", sstamp)
|
||||
};
|
||||
|
||||
var (access, accessExp) = _jwt.CreateAccessToken(claims);
|
||||
|
||||
return new IssueTokenPairResponse
|
||||
{
|
||||
AccessToken = access,
|
||||
AccessExpiresAt = accessExp,
|
||||
RefreshToken = refreshRaw, // ส่ง raw กลับให้ client
|
||||
RefreshExpiresAt = session.ExpiresAt
|
||||
};
|
||||
string[] roles = request.Roles ?? Array.Empty<string>();
|
||||
if (roles.Length == 0)
|
||||
{
|
||||
roles = await _users.GetRoleCodesByUserIdAsync(request.UserId, tenantId, ct);
|
||||
}
|
||||
|
||||
foreach (var r in roles.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct(StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
claims.Add(new Claim("role", r));
|
||||
claims.Add(new Claim(ClaimTypes.Role, r));
|
||||
}
|
||||
|
||||
// ---- ออก access token ----
|
||||
var (access, accessExp) = _jwt.CreateAccessToken(claims);
|
||||
|
||||
return new IssueTokenPairResponse
|
||||
{
|
||||
AccessToken = access,
|
||||
AccessExpiresAt = accessExp,
|
||||
RefreshToken = refreshRaw,
|
||||
RefreshExpiresAt = session.ExpiresAt
|
||||
};
|
||||
}
|
||||
|
||||
private static string Sha256(string raw)
|
||||
{
|
||||
var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(raw));
|
||||
|
||||
@@ -5,6 +5,7 @@ using AMREZ.EOP.Abstractions.Infrastructures.Common;
|
||||
using AMREZ.EOP.Abstractions.Infrastructures.Repositories;
|
||||
using AMREZ.EOP.Abstractions.Security;
|
||||
using AMREZ.EOP.Contracts.DTOs.Authentications.Login;
|
||||
using AMREZ.EOP.Domain.Entities.Authentications;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace AMREZ.EOP.Application.UseCases.Authentications
|
||||
@@ -60,9 +61,15 @@ namespace AMREZ.EOP.Application.UseCases.Authentications
|
||||
return null;
|
||||
}
|
||||
|
||||
var roles = (user.UserRoles ?? Enumerable.Empty<UserRole>())
|
||||
.Where(ur => ur.Role != null /*&& ur.Role.TenantId == user.TenantId*/) // ถ้า Role เป็น per-tenant ค่อยกรอง
|
||||
.Select(ur => ur.Role!.Code)
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToArray();
|
||||
|
||||
await _uow.CommitAsync(ct);
|
||||
|
||||
return new LoginResponse(user.Id, user.TenantId, email, tenantKey);
|
||||
return new LoginResponse(user.Id, user.TenantId, email, tenantKey, roles);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user