/// <summary> /// Redirects to \Error /// </summary> /// <returns></returns> protected virtual RedirectToRouteResult HttpAccessDenied() { var values = RouteData.Values; string actionAttempted = Convert.ToString(values["action"]); var urlAccessed = string.Format("{0}/{1}/{2}/{3}", InstitutionCode, values["area"], values["controller"], actionAttempted); TempData[ErrorMessageModel.ErrorMessageKey] = new ErrorMessageModel((string.Format("You are not authorized to access this page.{0} Contact administrator.", !string.IsNullOrWhiteSpace(actionAttempted) ? $" [Endpoint: '{actionAttempted}']." : ""))) { AreaName = Convert.ToString(values["area"]), FromUrl = urlAccessed, RenderErrorPageFully = true, ResponseCode = System.Net.HttpStatusCode.Forbidden, }; WebUtilities.LogOut(); return(MvcUtility.GetPageResult("Index", "Error", "", InstitutionCode)); }
/// <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); } } }