thalos-dal/src/Thalos.DAL/Providers/ProviderUserDataProviders.cs
2026-02-25 13:13:56 -06:00

144 lines
4.4 KiB
C#

using BuildingBlock.Identity.Contracts.Conventions;
using Thalos.DAL.Contracts;
namespace Thalos.DAL.Providers;
/// <summary>
/// Internal JWT provider implementation for identity user reads.
/// </summary>
public sealed class InternalJwtUserDataProvider : IUserDataProvider
{
/// <inheritdoc />
public Task<IdentityUserRecord?> ReadUserAsync(
IdentityUserLookupRequest request,
CancellationToken cancellationToken = default)
{
if (request.SubjectId.StartsWith("missing-", StringComparison.OrdinalIgnoreCase))
{
return Task.FromResult<IdentityUserRecord?>(null);
}
var record = new IdentityUserRecord(
request.Envelope,
request.SubjectId,
request.TenantId,
"active",
$"{request.SubjectId}:{request.TenantId}:token",
1800,
true);
return Task.FromResult<IdentityUserRecord?>(record);
}
}
/// <summary>
/// Azure AD provider implementation for identity user reads.
/// </summary>
public sealed class AzureAdUserDataProvider : IUserDataProvider
{
/// <inheritdoc />
public Task<IdentityUserRecord?> ReadUserAsync(
IdentityUserLookupRequest request,
CancellationToken cancellationToken = default)
{
var subjectId = ResolveSubjectId(request, "azure-sub");
if (string.IsNullOrWhiteSpace(subjectId))
{
return Task.FromResult<IdentityUserRecord?>(null);
}
var record = new IdentityUserRecord(
request.Envelope,
subjectId,
request.TenantId,
"active",
$"azure:{subjectId}:{request.TenantId}:token",
3600,
true);
return Task.FromResult<IdentityUserRecord?>(record);
}
private static string ResolveSubjectId(IdentityUserLookupRequest request, string prefix)
{
if (!string.IsNullOrWhiteSpace(request.SubjectId))
{
return request.SubjectId;
}
if (string.IsNullOrWhiteSpace(request.ExternalToken))
{
return string.Empty;
}
return $"{prefix}-{Math.Abs(request.ExternalToken.GetHashCode(StringComparison.Ordinal))}";
}
}
/// <summary>
/// Google provider implementation for identity user reads.
/// </summary>
public sealed class GoogleUserDataProvider : IUserDataProvider
{
/// <inheritdoc />
public Task<IdentityUserRecord?> ReadUserAsync(
IdentityUserLookupRequest request,
CancellationToken cancellationToken = default)
{
var subjectId = ResolveSubjectId(request, "google-sub");
if (string.IsNullOrWhiteSpace(subjectId))
{
return Task.FromResult<IdentityUserRecord?>(null);
}
var record = new IdentityUserRecord(
request.Envelope,
subjectId,
request.TenantId,
"active",
$"google:{subjectId}:{request.TenantId}:token",
3000,
true);
return Task.FromResult<IdentityUserRecord?>(record);
}
private static string ResolveSubjectId(IdentityUserLookupRequest request, string prefix)
{
if (!string.IsNullOrWhiteSpace(request.SubjectId))
{
return request.SubjectId;
}
if (string.IsNullOrWhiteSpace(request.ExternalToken))
{
return string.Empty;
}
return $"{prefix}-{Math.Abs(request.ExternalToken.GetHashCode(StringComparison.Ordinal))}";
}
}
/// <summary>
/// Routes user lookups to the matching provider implementation.
/// </summary>
public sealed class RoutedUserDataProvider(
InternalJwtUserDataProvider internalJwtProvider,
AzureAdUserDataProvider azureProvider,
GoogleUserDataProvider googleProvider) : IUserDataProvider
{
/// <inheritdoc />
public Task<IdentityUserRecord?> ReadUserAsync(
IdentityUserLookupRequest request,
CancellationToken cancellationToken = default)
{
return request.Provider switch
{
IdentityAuthProvider.InternalJwt => internalJwtProvider.ReadUserAsync(request, cancellationToken),
IdentityAuthProvider.AzureAd => azureProvider.ReadUserAsync(request, cancellationToken),
IdentityAuthProvider.Google => googleProvider.ReadUserAsync(request, cancellationToken),
_ => Task.FromResult<IdentityUserRecord?>(null)
};
}
}