Exemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            var actionDescriptor = filterContext.ActionDescriptor;

            #region Check whether it's an anonymous action

            if (actionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) ||
                actionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true))
            {
                //Allow Anonymous
                return;
            }

            #endregion

            var values   = filterContext.RouteData.Values;
            var instCode = Convert.ToString(values["institution"]);

            var webHelper = new WebHelper(filterContext.HttpContext);
            // If user is not logged in (authenticated) yet,
            var IdentityUser = webHelper.GetCurrentlyLoggedInUser();
            //if (!filterContext.HttpContext.Request.IsAuthenticated)
            if (IdentityUser == null || filterContext.HttpContext.Session?.IsNewSession == true)
            {
                // It's not anonymous, so force user to login
                webHelper.LogOut();
                filterContext.Result = MvcUtility.GetLoginPageResult(instCode);
                return;
            }

            var    area          = values["area"];
            string privilegeName = string.Format("{0}-{1}-{2}",
                                                 actionDescriptor.ActionName,
                                                 actionDescriptor.ControllerDescriptor.ControllerName,
                                                 area);
            if (Utilities.INST_DEFAULT_CODE.Equals(instCode, StringComparison.OrdinalIgnoreCase))
            {
                #region Check whether to allow Core access the action

                if (!actionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAccessToParentAttribute), true) &&
                    !actionDescriptor.IsDefined(typeof(AllowAccessToParentAttribute), true))
                {
                    // bounce
                    filterContext.Result = MvcUtility.GetPageResult("TenantsOnlyAllowed", "Error", "", instCode, new Dictionary <string, object> {
                        { "actionAttempted", filterContext.HttpContext.Request.Url.AbsoluteUri }
                    });
                    return;
                }

                #endregion
            }

            // At this point, we have established that we have a logged-in user. So...
            #region Authorize at Privilege level

            var userPrivList = webHelper.LoggedInUsersPrivilegesDict;
            //This should never be true under normal circumstances, 'cos a properly logged-in user
            // should have at least one user privllege
            if (userPrivList == null)
            {
                webHelper.LogOut();
                filterContext.Result = MvcUtility.GetLoginPageResult(instCode);
                return;
            }

            // OK. So the user has some privileges. So...

            if (!userPrivList.ContainsKey(privilegeName))
            {
                //The generalized case of the above 'GetData' trick
                var point = actionDescriptor.GetCustomAttributes(typeof(ValidateUsingPrivilegeForActionAttribute), true)
                            .Cast <ValidateUsingPrivilegeForActionAttribute>().FirstOrDefault();
                if (point != null)
                {
                    foreach (var actionName in point.ActionNames)
                    {
                        if (userPrivList.ContainsKey(string.Format("{0}-{1}-{2}",
                                                                   actionName, actionDescriptor.ControllerDescriptor.ControllerName, area)))
                        {
                            return;
                        }
                    }
                }
                filterContext.Result = MvcUtility.GetPageResult("DenyAccess", "Error", "", instCode, new System.Collections.Generic.Dictionary <string, object> {
                    { "actionAttempted", privilegeName }
                });
                return;
            }

            #endregion

            // If we get to this point, then the user authorized to access this action
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="filterContext"></param>
        public void OnException(ExceptionContext filterContext)
        {
            if (!filterContext.ExceptionHandled)
            {
                filterContext.ExceptionHandled = true;
                bool isFatal = false;
                try
                {
                    bool   doLogout = false;
                    var    values   = filterContext.RouteData.Values;
                    string instCode = Convert.ToString(values["institution"]);
                    try
                    {
                        var _instCode = WebUtilities.InstitutionCode ?? Utilities.INST_DEFAULT_CODE;
                        if (!instCode.Equals(_instCode, StringComparison.OrdinalIgnoreCase))
                        {
                            instCode = Utilities.INST_DEFAULT_CODE;
                            doLogout = true;
                        }
                    }
                    catch (LogOutUserException)
                    {
                        doLogout = true;
                    }
                    catch (Exception) //(GeneralException ex) when (ex.ExceptionType == ExceptionType.UnidentifiedInstitutionCode)
                    {
                        instCode = Utilities.INST_DEFAULT_CODE;
                    }

                    // When view is not found, it usually throws
                    //Exception Details: System.InvalidOperationException:
                    // The view '~/Views/my-category/my-article-with-long-name.aspx' or its master could not be found. The following locations were searched: ~/Views/my-category/my-article-with-long-name.aspx
                    if (filterContext.Exception is InvalidOperationException && filterContext.Exception.Message.Contains("The view '~/Views"))
                    {
                        isFatal = true;
                        filterContext.Result = MvcUtility.GetPageResult("ViewNotFound", "Error", "", instCode);
                        return;
                    }

                    var urlAccessed = filterContext.RequestContext.HttpContext.Request.RawUrl; // string.Format("/{0}{1}/{2}/{3}", instCode, string.IsNullOrWhiteSpace(area) ? "" : ("/" + area), controller, action);

                    string area       = Convert.ToString(values["area"]);
                    string controller = Convert.ToString(values["controller"]);
                    string action     = Convert.ToString(values["action"]);
                    var    genEx      = filterContext.Exception as GeneralException;
                    if (genEx != null)
                    {
                        if (genEx.ExceptionType == ExceptionType.UnidentifiedInstitutionCode)
                        {
                            instCode = Utilities.INST_DEFAULT_CODE;
                            filterContext.Controller.TempData[ErrorMessageModel.ErrorMessageKey] = new ErrorMessageModel("Invalid Url. Please cross-check.", controller, action)
                            {
                                ErrorType            = ExceptionType.UnidentifiedInstitutionCode,
                                AreaName             = area,
                                FromUrl              = urlAccessed,
                                ResponseCode         = HttpStatusCode.NotFound,
                                RenderErrorPageFully = true,
                            };
                        }
                        else if (genEx.ExceptionType == ExceptionType.DatabaseRelated)
                        {
                            filterContext.Controller.TempData[ErrorMessageModel.ErrorMessageKey] = new ErrorMessageModel("A database error has occurred. Contact the administrator", controller, action)
                            {
                                ErrorType    = ExceptionType.DatabaseRelated,
                                AreaName     = area,
                                FromUrl      = urlAccessed,
                                ResponseCode = HttpStatusCode.InternalServerError,
                            };
                        }
                        else
                        {
                            filterContext.Controller.TempData[ErrorMessageModel.ErrorMessageKey] = new ErrorMessageModel(genEx, controller, action)
                            {
                                AreaName = area,
                                FromUrl  = urlAccessed
                            };
                        }
                        filterContext.Result = MvcUtility.GetPageResult("Index", "Error", "", instCode);
                        return;
                    }

                    if (doLogout || filterContext.Exception is LogOutUserException)
                    {
                        WebUtilities.LogOut();
                        filterContext.Result = MvcUtility.GetLoginPageResult(instCode);
                    }
                    else
                    {
                        var dbExType = typeof(System.Data.Common.DbException);
                        if (dbExType.IsAssignableFrom(filterContext.Exception.GetType()) ||
                            (filterContext.Exception.GetBaseException() != null && dbExType.IsAssignableFrom(filterContext.Exception.GetBaseException().GetType())))
                        {
                            filterContext.Controller.TempData[ErrorMessageModel.ErrorMessageKey] = new ErrorMessageModel("A database error has occurred. Contact the administrator", controller, action)
                            {
                                ErrorType    = ExceptionType.DatabaseRelated,
                                AreaName     = area,
                                FromUrl      = urlAccessed,
                                ResponseCode = HttpStatusCode.InternalServerError,
                            };
                        }
                        else if (filterContext.Exception is HttpAntiForgeryException)
                        {
                            filterContext.Controller.TempData[ErrorMessageModel.ErrorMessageKey] = new ErrorMessageModel("Looks like this is a cross-site request forgery. We can't find the token.", controller, action)
                            {
                                AreaName = area,
                                FromUrl  = urlAccessed
                            };
                        }
                        else
                        {
                            filterContext.Controller.TempData[ErrorMessageModel.ErrorMessageKey] = new ErrorMessageModel(filterContext.Exception, controller, action)
                            {
                                AreaName = area,
                                FromUrl  = urlAccessed
                            };
                        }
                        filterContext.Result = MvcUtility.GetPageResult("Index", "Error", "", instCode);
                    }
                }
                finally
                {
                    Utilities.Logger.Log(filterContext.Exception, isFatal);
                }
            }
        }