передача токена
This commit is contained in:
@@ -9,8 +9,8 @@
|
|||||||
"Postgres": "Host=localhost;Port=5435;Database=tnsu_approval_route;Username=tnsu_approval_route;Password=tnsu_approval_route"
|
"Postgres": "Host=localhost;Port=5435;Database=tnsu_approval_route;Username=tnsu_approval_route;Password=tnsu_approval_route"
|
||||||
},
|
},
|
||||||
"Entra": {
|
"Entra": {
|
||||||
"TenantId": "",
|
"TenantId": "b4c2af35-bfd6-4cff-9af9-556efb53e65a",
|
||||||
"Audience": ""
|
"Audience": "9232d9e2-9807-4753-808f-07250e5474b0"
|
||||||
},
|
},
|
||||||
"Dev": {
|
"Dev": {
|
||||||
"DefaultUserEmail": "dev@tnsu.kz"
|
"DefaultUserEmail": "dev@tnsu.kz"
|
||||||
|
|||||||
@@ -13,5 +13,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" />
|
<PackageReference Include="Microsoft.Extensions.Http" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
|
||||||
|
<!-- Даёт доступ к IHttpContextAccessor из общего фреймворка ASP.NET Core (тот же тип, что в Api). -->
|
||||||
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,14 +1,23 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Tnsu.ApprovalRoute.Domain.Enums;
|
using Tnsu.ApprovalRoute.Domain.Enums;
|
||||||
|
|
||||||
namespace Tnsu.ApprovalRoute.Infrastructure.TnsuPortal;
|
namespace Tnsu.ApprovalRoute.Infrastructure.TnsuPortal;
|
||||||
|
|
||||||
// Клиент api.tnsu.kz (api-tnsu-portal). Сервисный токен прокидывается через TnsuPortalTokenProvider.
|
// Клиент api.tnsu.kz (api-tnsu-portal).
|
||||||
public sealed class HttpTnsuPortalClient(HttpClient httpClient, TnsuPortalTokenProvider tokenProvider) : ITnsuPortalClient
|
public sealed class HttpTnsuPortalClient(
|
||||||
|
HttpClient httpClient,
|
||||||
|
TnsuPortalTokenProvider tokenProvider,
|
||||||
|
IHttpContextAccessor httpContextAccessor) : ITnsuPortalClient
|
||||||
{
|
{
|
||||||
|
// Разные эндпоинты api-tnsu-portal отдают JSON в разном регистре (Dapper-результаты — PascalCase,
|
||||||
|
// строго типизированные модели — camelCase), поэтому сопоставляем поля без учёта регистра.
|
||||||
|
private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive = true };
|
||||||
|
|
||||||
public async Task<EmployeeDirectoryInfo?> GetEmployeeByEmailAsync(string email, CancellationToken cancellationToken)
|
public async Task<EmployeeDirectoryInfo?> GetEmployeeByEmailAsync(string email, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
using var request = new HttpRequestMessage(HttpMethod.Get, $"/Employee/ByEmail?email={Uri.EscapeDataString(email)}");
|
using var request = new HttpRequestMessage(HttpMethod.Get, $"/Employee/ByEmail?email={Uri.EscapeDataString(email)}");
|
||||||
@@ -19,7 +28,7 @@ public sealed class HttpTnsuPortalClient(HttpClient httpClient, TnsuPortalTokenP
|
|||||||
return null;
|
return null;
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
var employee = await response.Content.ReadFromJsonAsync<EmployeeResponse>(cancellationToken);
|
var employee = await response.Content.ReadFromJsonAsync<EmployeeResponse>(JsonOptions, cancellationToken);
|
||||||
if (employee is null)
|
if (employee is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -36,7 +45,7 @@ public sealed class HttpTnsuPortalClient(HttpClient httpClient, TnsuPortalTokenP
|
|||||||
return [];
|
return [];
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
var project = await response.Content.ReadFromJsonAsync<ProjectResponse>(cancellationToken);
|
var project = await response.Content.ReadFromJsonAsync<ProjectResponse>(JsonOptions, cancellationToken);
|
||||||
if (project is null)
|
if (project is null)
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
@@ -56,8 +65,18 @@ public sealed class HttpTnsuPortalClient(HttpClient httpClient, TnsuPortalTokenP
|
|||||||
executors.Add(new ProjectExecutorInfo(role, email));
|
executors.Add(new ProjectExecutorInfo(role, email));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ВРЕМЕННО: для TnsuPortal ещё нет своего client-credentials приложения в Entra, поэтому прокидываем
|
||||||
|
// токен текущего пользователя дальше — его aud совпадает с ClientId api-tnsu-portal, так что подходит.
|
||||||
|
// Когда появится своё приложение — вернуть на tokenProvider.GetAccessTokenAsync(...).
|
||||||
private async Task AuthorizeAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
private async Task AuthorizeAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
var incoming = httpContextAccessor.HttpContext?.Request.Headers.Authorization.ToString();
|
||||||
|
if (!string.IsNullOrWhiteSpace(incoming))
|
||||||
|
{
|
||||||
|
request.Headers.TryAddWithoutValidation("Authorization", incoming);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var token = await tokenProvider.GetAccessTokenAsync(cancellationToken);
|
var token = await tokenProvider.GetAccessTokenAsync(cancellationToken);
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user