MVC CustomAuthorizeAttribute using Reflection to get Controllers and Actions

Code beautifier used: http://hilite.me/ 

Usage:

    [CustomAuthorize]
    public class AdministrationController : BaseController
    {
        #region Users List

        [NavigationMenuEnumAuthorize(NavigationMenuEnum.UserAdministration)]
        public ActionResult Index()
        {
            return View();
        }
    }

 

CustomAuthorizeAttrbute Code:

namespace System.ComponentModel.DataAnnotations
{

    public class NavigationMenuEnumAuthorizeAttribute : System.Attribute
    {
        public List NavigationMenuEnumList { get; set; }
        public NavigationMenuEnumAuthorizeAttribute(params NavigationMenuEnum[] navigationPages)
        {
            NavigationMenuEnumList = new List();
            if (navigationPages != null && navigationPages.Count() > 0)
            {
                NavigationMenuEnumList = navigationPages.ToList();
            }
        }
    }

    public class CustomAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
    {
        string currentAction;
        string currentController;
        string currentArea;
        public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
        }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var routeData = httpContext.Request.RequestContext.RouteData;

            currentAction = routeData.GetRequiredString("action");
            currentController = routeData.GetRequiredString("controller");
            currentArea = routeData.Values["area"] as string;

            if (Utils.CurrentUser == null)
                return false;

            Dictionary<NavigationMenuEnum, bool> menuSecurity = new Dictionary<NavigationMenuEnum, bool>();

            using (var dbContext = new Web.Models.ConnectionStringEDMX())
            {
                int userid = Utils.CurrentUser.UserId;

                menuSecurity[NavigationMenuEnum.CreateNewForm] = false;
                menuSecurity[NavigationMenuEnum.CreateNewChildForm] = false;
                menuSecurity[NavigationMenuEnum.EditNewForm] = false;
                menuSecurity[NavigationMenuEnum.FormSummary] = false;
                menuSecurity[NavigationMenuEnum.AllRequests] = false;
                menuSecurity[NavigationMenuEnum.MyRequests] = false;
                menuSecurity[NavigationMenuEnum.WaitingForApproval] = false;
                menuSecurity[NavigationMenuEnum.UserAdministration] = false;
                menuSecurity[NavigationMenuEnum.Delegate] = false;
                menuSecurity[NavigationMenuEnum.Reporting] = false;

                if (userid == 0)
                {
                    httpContext.Session[Web.Helpers.StaticStrings.MenuSecuritySessionName] = (Dictionary<NavigationMenuEnum, bool>)menuSecurity;
                    return false;
                }

                var userRoles = dbContext.admUserRoles.Where(x => x.UserId == userid || Utils.CurrentUser.CurrentUserDelegatedForUserIdList.Contains(x.UserId));

                foreach (admUserRole userRole in userRoles)
                {
                    switch ((EnRoles)userRole.RoleId)
                    {
                        case EnRoles.Admin:
                            {
                                menuSecurity[NavigationMenuEnum.CreateNewForm] = true;
                                menuSecurity[NavigationMenuEnum.CreateNewChildForm] = true;
                                menuSecurity[NavigationMenuEnum.EditNewForm] = true;
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.MyRequests] = true;
                                menuSecurity[NavigationMenuEnum.WaitingForApproval] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.UserAdministration] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                menuSecurity[NavigationMenuEnum.Reporting] = true;
                                break;
                            }
                        case EnRoles.Originator:
                            {
                                menuSecurity[NavigationMenuEnum.CreateNewForm] = true;
                                menuSecurity[NavigationMenuEnum.CreateNewChildForm] = true;
                                menuSecurity[NavigationMenuEnum.EditNewForm] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.MyRequests] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        case EnRoles.Reviewer:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.WaitingForApproval] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        case EnRoles.Approver:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.WaitingForApproval] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        case EnRoles.Reporting:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.Reporting] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        case EnRoles.Viewer:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                break;
                            }
                        case EnRoles.Supervisor:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.WaitingForApproval] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        default:
                            {
                                break;
                            }
                    }
                }
            }

            httpContext.Session[Web.Helpers.StaticStrings.MenuSecuritySessionName] = (Dictionary<NavigationMenuEnum, bool>)menuSecurity;
            
            List pageMapping = GetGeneralPageDetailsList(); // all page mappings are generating from controllers that have the CustomAuthorizeAttribute and Actions that have the NavigationMenuEnumAuthorizeAttribute


            if (!pageMapping.Any(x => x.Action == currentAction && x.Controller == currentController))
                return true;

            NavigationMenuEnum currentPage = pageMapping.Where(x => x.Action == currentAction && x.Controller == currentController).Select(x => x.Page).FirstOrDefault();

            return menuSecurity[currentPage];
        }

        public class PageDetails
        {
            public string Action { get; set; }
            public string Controller { get; set; }
            public NavigationMenuEnum Page { get; set; }
            public PageDetails(string action, string controller, NavigationMenuEnum page)
            {
                this.Action = action;
                this.Controller = controller;
                this.Page = page;
            }
                }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {            
            if (Utils.CurrentUser == null || Utils.CurrentUser.UserId == 0)
            {
                filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary 
                        {
                            { "area", "" },
                            { "controller", "Home" },
                            { "action", "SignIn" }
                        });
            }
            else
            {
                filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary 
                        {
                            { "area", "" },
                            { "controller", "Account" },
                            { "action", "NoAccess" }
                        });
            }
            return;
            base.HandleUnauthorizedRequest(filterContext);
        }

        /// https://stackoverflow.com/a/11305443/249895
        public List GetGeneralPageDetailsList()
        {
            try
            {
                ///https://stackoverflow.com/a/30969888/249895
                Assembly asm = Assembly.GetAssembly(typeof(MvcApplication));

                var controllerTypesList = asm.GetTypes().Where(type => typeof(System.Web.Mvc.Controller).IsAssignableFrom(type));

                var returnPagesList = new List();

                foreach (var controllerType in controllerTypesList)
                {
                    var reflectedControllerDescriptor = new ReflectedControllerDescriptor(controllerType);
                    string controllerName = reflectedControllerDescriptor.ControllerName;
                    var customAuthorizeAttributeList = reflectedControllerDescriptor.GetCustomAttributes(typeof(CustomAuthorizeAttribute), true);

                    if (customAuthorizeAttributeList != null && customAuthorizeAttributeList.Count() > 0)
                    {
                        var actionsList = reflectedControllerDescriptor.GetCanonicalActions();
                        foreach (var action in actionsList)
                        {
                            var attributesList = action.GetCustomAttributes(typeof(NavigationMenuEnumAuthorizeAttribute), true).Select(x => (NavigationMenuEnumAuthorizeAttribute)x).ToList();
                            if (attributesList != null && attributesList.Count() > 0)
                            {
                                foreach (var attribute in attributesList)
                                {
                                    foreach (var navigMenuEnum in attribute.NavigationMenuEnumList)
                                    {
                                        var page = new CustomAuthorizeAttribute.PageDetails(action.ActionName, controllerName, navigMenuEnum);
                                        returnPagesList.Add(page);
                                    }
                                }
                            }
                            else
                            {
                                var page = new CustomAuthorizeAttribute.PageDetails(action.ActionName, controllerName, NavigationMenuEnum.None);
                                returnPagesList.Add(page);
                            }
                        }
                    }
                }

                return returnPagesList;
            }
            catch (ReflectionTypeLoadException ex)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                foreach (Exception exSub in ex.LoaderExceptions)
                {
                    sb.AppendLine(exSub.Message);
                    System.IO.FileNotFoundException exFileNotFound = exSub as System.IO.FileNotFoundException;
                    if (exFileNotFound != null)
                    {
                        if (!string.IsNullOrEmpty(exFileNotFound.FusionLog))
                        {
                            sb.AppendLine("Fusion Log:");
                            sb.AppendLine(exFileNotFound.FusionLog);
                        }
                    }
                    sb.AppendLine();
                }
                string errorMessage = sb.ToString();
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
                Exception newEx = new Exception(errorMessage);
                Elmah.ErrorSignal.FromCurrentContext().Raise(newEx);
                throw newEx;
                //Display or log the error based on your application.
            }
            catch (Exception ex)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
                throw;
            }
        }
    }


}

Leave a Reply

Your email address will not be published. Required fields are marked *