forked from xiongyuxing/tiku-backend.net
115 lines
4.4 KiB
C#
115 lines
4.4 KiB
C#
using System.Net.Http.Json;
|
|
using System.Text.Json;
|
|
using Tiku.Api.Contracts;
|
|
using Tiku.Domain.Identity;
|
|
using Tiku.Domain.Tenancy;
|
|
|
|
namespace Tiku.IntegrationTests.Api;
|
|
|
|
internal sealed record TestAuthenticationTokens(string AccessToken, string RefreshToken);
|
|
|
|
internal static class AuthenticationTestClientExtensions
|
|
{
|
|
public static async Task<TestAuthenticationTokens> LoginAsTenantAsync(
|
|
this HttpClient client,
|
|
Guid tenantId,
|
|
string identifier,
|
|
string password = PasswordTestUserExtensions.TestPassword)
|
|
{
|
|
SetTenantHeader(client, tenantId);
|
|
var response = await client.PostAsJsonAsync(
|
|
"/api/auth/login/password",
|
|
new PasswordLoginDto
|
|
{
|
|
Realm = AuthRealm.Tenant,
|
|
TenantCode = tenantId.ToString("N"),
|
|
Identifier = identifier,
|
|
Password = password
|
|
});
|
|
|
|
return await client.CompleteTenantAuthenticationAsync(response, tenantId, identifier);
|
|
}
|
|
|
|
public static async Task<TestAuthenticationTokens> LoginAsPlatformAsync(
|
|
this HttpClient client,
|
|
string identifier,
|
|
string password = PasswordTestUserExtensions.TestPassword)
|
|
{
|
|
client.DefaultRequestHeaders.Remove("x-tenant-code");
|
|
var response = await client.PostAsJsonAsync(
|
|
"/api/auth/login/password",
|
|
new PasswordLoginDto
|
|
{
|
|
Realm = AuthRealm.Platform,
|
|
Identifier = identifier,
|
|
Password = password
|
|
});
|
|
|
|
return await client.CompletePlatformAuthenticationAsync(response, identifier);
|
|
}
|
|
|
|
public static async Task<TestAuthenticationTokens> CompleteTenantAuthenticationAsync(
|
|
this HttpClient client,
|
|
HttpResponseMessage response,
|
|
Guid tenantId,
|
|
string _)
|
|
{
|
|
SetTenantHeader(client, tenantId);
|
|
using var authentication = await ReadSuccessfulJsonAsync(response);
|
|
var root = authentication.RootElement;
|
|
var status = root.GetProperty("status").GetString();
|
|
|
|
return string.Equals(status, "authenticated", StringComparison.OrdinalIgnoreCase)
|
|
? ReadTokens(root.GetProperty("user").GetProperty("tokens"))
|
|
: throw new InvalidOperationException($"Unsupported test authentication status '{status}'.");
|
|
}
|
|
|
|
private static async Task<TestAuthenticationTokens> CompletePlatformAuthenticationAsync(
|
|
this HttpClient client,
|
|
HttpResponseMessage response,
|
|
string _)
|
|
{
|
|
client.DefaultRequestHeaders.Remove("x-tenant-code");
|
|
using var authentication = await ReadSuccessfulJsonAsync(response);
|
|
var root = authentication.RootElement;
|
|
var status = root.GetProperty("status").GetString();
|
|
|
|
return string.Equals(status, "authenticated", StringComparison.OrdinalIgnoreCase)
|
|
? ReadTokens(root.GetProperty("user").GetProperty("tokens"))
|
|
: throw new InvalidOperationException($"Unsupported test authentication status '{status}'.");
|
|
}
|
|
|
|
public static void UseAccessToken(this HttpClient client, TestAuthenticationTokens tokens)
|
|
{
|
|
client.DefaultRequestHeaders.Authorization = new("Bearer", tokens.AccessToken);
|
|
}
|
|
|
|
private static void SetTenantHeader(HttpClient client, Guid tenantId)
|
|
{
|
|
client.DefaultRequestHeaders.Remove("x-tenant-code");
|
|
client.DefaultRequestHeaders.Add("x-tenant-code", tenantId.ToString("N"));
|
|
}
|
|
|
|
private static async Task<JsonDocument> ReadSuccessfulJsonAsync(HttpResponseMessage response)
|
|
{
|
|
var body = await response.Content.ReadAsStringAsync();
|
|
if (!response.IsSuccessStatusCode)
|
|
{
|
|
throw new HttpRequestException(
|
|
$"Authentication request failed with {(int)response.StatusCode} ({response.StatusCode}): {body}");
|
|
}
|
|
|
|
return JsonDocument.Parse(body);
|
|
}
|
|
|
|
private static TestAuthenticationTokens ReadTokens(JsonElement tokens)
|
|
{
|
|
var accessToken = tokens.GetProperty("accessToken").GetString()
|
|
?? throw new InvalidOperationException("Authentication response did not contain an access token.");
|
|
var refreshToken = tokens.GetProperty("refreshToken").GetString()
|
|
?? throw new InvalidOperationException("Authentication response did not contain a refresh token.");
|
|
return new TestAuthenticationTokens(accessToken, refreshToken);
|
|
}
|
|
|
|
}
|