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(); 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(); 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 }; } } } }