Add Master Data

This commit is contained in:
Thanakarn Klangkasame
2025-10-10 16:22:06 +07:00
parent ad0d9e41ba
commit d4ab1cb592
55 changed files with 16058 additions and 197 deletions

View File

@@ -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));