using DodoSSH.Domain;
using Microsoft.AspNetCore.Authorization;
namespace DodoSSH.Api.Authorization;
/// Requires the caller's account to be .
///
///
/// is documented as "sign-in blocked", and nothing blocked it: the identity
/// provider still issues tokens for the person, every endpoint resolved them through the current-user context,
/// and that context looked an account up by issuer, subject and deletion alone. A suspended account could pull
/// and push vaults, take relay tickets and hold the events socket open. This is the check, on both policies, so
/// that no endpoint can be reached without it.
///
///
/// A connection already open when the account is suspended — a relay tunnel, the events socket — is not
/// reached by this; it ends on its own idle and lifetime limits.
///
///
internal sealed class ActiveAccountRequirement : IAuthorizationRequirement;
/// Satisfies from the account row.
internal sealed class ActiveAccountHandler(ICurrentUserContext currentUser, IHttpContextAccessor accessor)
: AuthorizationHandler
{
///
protected override async Task HandleRequirementAsync(
AuthorizationHandlerContext context,
ActiveAccountRequirement requirement)
{
ArgumentNullException.ThrowIfNull(context);
// The policy's authentication requirement already refuses an anonymous caller with a 401; failing this
// as well would turn that into a 403.
if (context.User.Identity?.IsAuthenticated != true)
{
return;
}
var cancellationToken = accessor.HttpContext?.RequestAborted ?? CancellationToken.None;
var user = await currentUser.GetOrProvisionAsync(cancellationToken).ConfigureAwait(false);
if (user.Status == UserStatus.Active)
{
context.Succeed(requirement);
}
}
}