diff --git a/BMA.EHR.Application/Repositories/PermissionRepository.cs b/BMA.EHR.Application/Repositories/PermissionRepository.cs index d5ac981a..84191f91 100644 --- a/BMA.EHR.Application/Repositories/PermissionRepository.cs +++ b/BMA.EHR.Application/Repositories/PermissionRepository.cs @@ -62,6 +62,10 @@ namespace BMA.EHR.Application.Repositories new AuthenticationHeaderValue("Bearer", AccessToken.Replace("Bearer ", "")); client.DefaultRequestHeaders.Add("api-key", _configuration["API_KEY"]); var req = await client.GetAsync(apiPath); + if (!req.IsSuccessStatusCode) + { + throw new Exception("Error calling permission API"); + } var res = await req.Content.ReadAsStringAsync(); return res; } diff --git a/BMA.EHR.Application/Repositories/UserProfileRepository.cs b/BMA.EHR.Application/Repositories/UserProfileRepository.cs index 1c9d5596..9ef3f76e 100644 --- a/BMA.EHR.Application/Repositories/UserProfileRepository.cs +++ b/BMA.EHR.Application/Repositories/UserProfileRepository.cs @@ -186,6 +186,30 @@ namespace BMA.EHR.Application.Repositories } } + public async Task GetProfileByKeycloakIdNewAsync(Guid keycloakId, string? accessToken) + { + try + { + var apiPath = $"{_configuration["API"]}/org/dotnet/by-keycloak/{keycloakId}"; + var apiKey = _configuration["API_KEY"]; + + var apiResult = await GetExternalAPIAsync(apiPath, accessToken ?? "", apiKey); + if (apiResult != null) + { + var raw = JsonConvert.DeserializeObject(apiResult); + if (raw != null) + return raw.Result; + } + + return null; + } + catch + { + throw; + } + } + + public async Task GetProfileLeaveByKeycloakIdAsync(Guid keycloakId, string? accessToken) { try diff --git a/BMA.EHR.Domain/Middlewares/CombinedErrorHandlerAndLoggingMiddleware.cs b/BMA.EHR.Domain/Middlewares/CombinedErrorHandlerAndLoggingMiddleware.cs index 5f5aa2af..3391e6a3 100644 --- a/BMA.EHR.Domain/Middlewares/CombinedErrorHandlerAndLoggingMiddleware.cs +++ b/BMA.EHR.Domain/Middlewares/CombinedErrorHandlerAndLoggingMiddleware.cs @@ -144,12 +144,22 @@ namespace BMA.EHR.Domain.Middlewares { stopwatch.Stop(); + // อ่านข้อมูล response ก่อนที่ stream จะถูก dispose + string? responseBodyForLogging = null; + if (memoryStream.Length > 0) + { + memoryStream.Seek(0, SeekOrigin.Begin); + using var reader = new StreamReader(memoryStream, leaveOpen: true); + responseBodyForLogging = await reader.ReadToEndAsync(); + memoryStream.Seek(0, SeekOrigin.Begin); + } + // ทำ logging แบบ fire-and-forget เพื่อไม่ block response _ = Task.Run(async () => { try { - await LogRequestAsync(context, _elasticClient!, startTime, stopwatch, pf, keycloakId, requestBodyJson, memoryStream, caughtException); + await LogRequestAsync(context, _elasticClient!, startTime, stopwatch, pf, keycloakId, requestBodyJson, responseBodyForLogging, caughtException); } catch (Exception ex) { @@ -393,7 +403,7 @@ namespace BMA.EHR.Domain.Middlewares } private async Task LogRequestAsync(HttpContext context, ElasticClient client, DateTime startTime, Stopwatch stopwatch, - GetProfileByKeycloakIdLocal? pf, string keycloakId, string? requestBodyJson, MemoryStream memoryStream, Exception? caughtException) + GetProfileByKeycloakIdLocal? pf, string keycloakId, string? requestBodyJson, string? responseBodyForLogging, Exception? caughtException) { try { @@ -412,48 +422,42 @@ namespace BMA.EHR.Domain.Middlewares string? message = null; string? responseBodyJson = null; - // อ่านข้อมูลจาก Response (ลด serialization ที่ซ้ำ) - if (memoryStream.Length > 0) + // ใช้ response body ที่ส่งมาจากการอ่านก่อนหน้า + if (!string.IsNullOrEmpty(responseBodyForLogging)) { - memoryStream.Seek(0, SeekOrigin.Begin); - var responseBody = new StreamReader(memoryStream).ReadToEnd(); + var contentType = context.Response.ContentType ?? ""; + var isFileResponse = !contentType.StartsWith("application/json") && !contentType.StartsWith("text/html") && ( + contentType.StartsWith("application/") || + contentType.StartsWith("image/") || + contentType.StartsWith("audio/") || + context.Response.Headers.ContainsKey("Content-Disposition") + ); - if (!string.IsNullOrEmpty(responseBody)) + if (isFileResponse) { - var contentType = context.Response.ContentType ?? ""; - var isFileResponse = !contentType.StartsWith("application/json") && !contentType.StartsWith("text/html") && ( - contentType.StartsWith("application/") || - contentType.StartsWith("image/") || - contentType.StartsWith("audio/") || - context.Response.Headers.ContainsKey("Content-Disposition") - ); - - if (isFileResponse) + responseBodyJson = ""; + message = "success"; + } + else + { + // ใช้ response body ที่มีอยู่แล้วโดยไม่ serialize ซ้ำ + responseBodyJson = responseBodyForLogging; + + try { - responseBodyJson = ""; - message = "success"; + var json = JsonSerializer.Deserialize(responseBodyForLogging); + if (json.ValueKind == JsonValueKind.Array) + { + message = "success"; + } + else if (json.TryGetProperty("message", out var messageElement)) + { + message = messageElement.GetString(); + } } - else + catch { - // ใช้ response body ที่มีอยู่แล้วโดยไม่ serialize ซ้ำ - responseBodyJson = responseBody; - - try - { - var json = JsonSerializer.Deserialize(responseBody); - if (json.ValueKind == JsonValueKind.Array) - { - message = "success"; - } - else if (json.TryGetProperty("message", out var messageElement)) - { - message = messageElement.GetString(); - } - } - catch - { - message = caughtException?.Message ?? "Unknown error"; - } + message = caughtException?.Message ?? "Unknown error"; } } } @@ -467,7 +471,7 @@ namespace BMA.EHR.Domain.Middlewares { logType = logType, ip = context.Connection.RemoteIpAddress?.ToString(), - rootId = pf?.RootId, + rootId = pf?.RootDnaId, systemName = SystemName, startTimeStamp = startTime.ToString("o"), endTimeStamp = endTime.ToString("o"), @@ -660,7 +664,7 @@ namespace BMA.EHR.Domain.Middlewares { try { - var apiPath = $"{_configuration["API"]}/org/dotnet/keycloak/{keycloakId}"; + var apiPath = $"{_configuration["API"]}/org/dotnet/by-keycloak/{keycloakId}"; var apiKey = _configuration["API_KEY"]; var apiResult = await GetExternalAPIAsync(apiPath, accessToken ?? "", apiKey);