#nullable enable
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Services;
using Microsoft.AspNetCore.Authorization;
namespace Bit.Api.AdminConsole.Authorization;
///
/// Handles any requirement that implements .
/// Retrieves the Organization ID from the route and then passes it to the requirement's AuthorizeAsync callback to
/// determine whether the action is authorized.
///
public class OrganizationRequirementHandler(
IHttpContextAccessor httpContextAccessor,
IProviderUserRepository providerUserRepository,
IUserService userService)
: AuthorizationHandler
{
public const string NoHttpContextError = "This method should only be called in the context of an HTTP Request.";
public const string NoUserIdError = "This method should only be called on the private api with a logged in user.";
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, IOrganizationRequirement requirement)
{
var httpContext = httpContextAccessor.HttpContext;
if (httpContext == null)
{
throw new InvalidOperationException(NoHttpContextError);
}
var organizationId = httpContext.GetOrganizationId();
var organizationClaims = httpContext.User.GetCurrentContextOrganization(organizationId);
var userId = userService.GetProperUserId(httpContext.User);
if (userId == null)
{
throw new InvalidOperationException(NoUserIdError);
}
Task IsProviderUserForOrg() => httpContext.IsProviderUserForOrgAsync(providerUserRepository, userId.Value, organizationId);
var authorized = await requirement.AuthorizeAsync(organizationClaims, IsProviderUserForOrg);
if (authorized)
{
context.Succeed(requirement);
}
}
}