NonInventPurchasingSystem/CPRNIMS.WebApi/Security/AuthorizeRolesAttribute.cs
2026-01-26 14:21:31 +08:00

103 lines
3.5 KiB
C#

using CPRNIMS.Domain.Services.Account;
using CPRNIMS.Infrastructure.Database;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;
namespace CPRNIMS.WebApi.Security
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeRolesAttribute : AuthorizeAttribute, IAsyncAuthorizationFilter
{
private readonly string _controllerName;
public AuthorizeRolesAttribute(string controllerName)
{
_controllerName = controllerName;
}
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
try
{
var user = context.HttpContext.User;
if (!user.Identity?.IsAuthenticated ?? true)
{
context.Result = new JsonResult(new
{
Success = false,
MessCode = 0,
Message = "You must be logged in to access this resource."
})
{
StatusCode = StatusCodes.Status401Unauthorized
};
return;
}
var userId = user.FindFirstValue(ClaimTypes.NameIdentifier);
if (string.IsNullOrEmpty(userId))
{
context.Result = new UnauthorizedResult();
return;
}
var serviceProvider = context.HttpContext.RequestServices;
var authCache = serviceProvider.GetService<IRoleAuthorizationCache>();
bool hasAccess;
if (authCache != null)
{
// Use cached authorization check
hasAccess = await authCache.UserHasAccessAsync(userId, _controllerName);
}
else
{
// Fallback to direct database query
var dbContext = serviceProvider.GetRequiredService<NonInventoryDbContext>();
hasAccess = await (
from ar in dbContext.AuthorizeRoles
join ur in dbContext.UserRoles on ar.RoleId equals ur.RoleId
where ar.IsActive
&& ar.Controller == _controllerName
&& ur.UserId == userId
select ar.AuthorizeRoleId
).AnyAsync();
}
if (!hasAccess)
{
context.Result = new JsonResult(new
{
Success = false,
MessCode = 0,
Message = "You don't have permission to access this page. Please contact your administrator."
})
{
StatusCode = StatusCodes.Status403Forbidden
};
return;
}
}
catch (Exception ex)
{
context.Result = new JsonResult(new
{
Success = false,
MessCode = 0,
Message = "An error occurred while checking permissions."
})
{
StatusCode = StatusCodes.Status500InternalServerError
};
}
}
}
}