46 lines
1.9 KiB
C#
46 lines
1.9 KiB
C#
using Microsoft.AspNetCore.Components.Authorization;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using ZB.MOM.WW.Secrets.Abstractions;
|
|
|
|
namespace ZB.MOM.WW.Secrets.Ui;
|
|
|
|
/// <summary>
|
|
/// Resolves the principal to record as the audit <c>Actor</c> for a UI-driven secret mutation or
|
|
/// reveal. The resolution order is: an explicitly wired <see cref="ISecretActorAccessor"/> (if the
|
|
/// host registered one and it reports a non-blank actor); otherwise the authenticated user's
|
|
/// <see cref="System.Security.Principal.IIdentity.Name"/> from the cascading authentication state;
|
|
/// otherwise the literal <c>"unknown"</c> so an action is never attributed to a blank actor.
|
|
/// </summary>
|
|
internal static class SecretActorResolver
|
|
{
|
|
/// <summary>The fallback actor used when no accessor and no authenticated identity name is available.</summary>
|
|
public const string Unknown = "unknown";
|
|
|
|
/// <summary>
|
|
/// Resolves the audit actor. Never returns <c>null</c> or blank.
|
|
/// </summary>
|
|
/// <param name="services">The component's service provider, used to optionally resolve an <see cref="ISecretActorAccessor"/>.</param>
|
|
/// <param name="authState">The cascading authentication-state task, or <c>null</c> if unavailable.</param>
|
|
/// <returns>The resolved actor identity string.</returns>
|
|
public static async Task<string> ResolveAsync(IServiceProvider services, Task<AuthenticationState>? authState)
|
|
{
|
|
string? fromAccessor = services.GetService<ISecretActorAccessor>()?.CurrentActor;
|
|
if (!string.IsNullOrWhiteSpace(fromAccessor))
|
|
{
|
|
return fromAccessor;
|
|
}
|
|
|
|
if (authState is not null)
|
|
{
|
|
AuthenticationState state = await authState.ConfigureAwait(false);
|
|
string? name = state.User.Identity?.Name;
|
|
if (!string.IsNullOrWhiteSpace(name))
|
|
{
|
|
return name;
|
|
}
|
|
}
|
|
|
|
return Unknown;
|
|
}
|
|
}
|