using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.IdentityModel.JsonWebTokens;
namespace OpenWarehouse.auth.api.Common.PrivilageManager;
///
/// Attribute to enforce privilege-based authorization.
///
public class HasPrivilegeAttribute : Attribute, IAsyncAuthorizationFilter
{
private GlobalPrivilage.Privilege[] Privileges { get; }
///
/// Initializes a new instance of the class with one or more required privileges.
///
/// The privileges required to access the resource.
public HasPrivilegeAttribute(params GlobalPrivilage.Privilege[] privileges)
{
Privileges = privileges;
}
///
/// Performs the privilege check during authorization.
///
/// The authorization filter context.
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
var userActionId = context.HttpContext.User.FindFirstValue(JwtRegisteredClaimNames.Sub);
var userManager = context.HttpContext.RequestServices.GetRequiredService>();
var privilegeManager = context.HttpContext.RequestServices.GetRequiredService();
if (userActionId != null)
{
var userAction = await userManager.FindByIdAsync(userActionId);
if (userAction == null ||
!await UserHasAnyRequiredPrivilege(privilegeManager, userAction))
{
context.Result = new ContentResult
{
StatusCode = StatusCodes.Status403Forbidden,
Content = "Access Denied: You do not have the required privileges to perform this action.",
ContentType = "text/plain"
};
}
}
}
///
/// Checks if the user has at least one of the required privileges.
///
/// The privilege manager service.
/// The user to check privileges for.
/// True if the user has any required privilege; otherwise, false.
private async Task UserHasAnyRequiredPrivilege(PrivilegeManager privilegeManager, ApplicationUser user)
{
foreach (var privilege in Privileges)
{
if (await privilegeManager.UserHasGlobalPrivilage(user, privilege))
{
return true;
}
}
return false;
}
}