/// <summary>
        /// When implemented in a derived class, checks authorization for the subject in the specified context to perform the specified action on the specified resource.
        /// </summary>
        /// <param name="context">The authorization context that contains the subject, resource, and action for which authorization is to be checked.</param>
        /// <returns>
        /// true if the subject is authorized to perform the specified action on the specified resource; otherwise, false.
        /// </returns>
        public override bool CheckAccess(AuthorizationContext context)
        {
            bool result = false;

            // 如果沒有Resource和Operation的情況下,表示可以看
            if (context.Resource.Count == 0 && context.Action.Count == 0)
            {
                return true;
            }

            if (context.Principal.Identity.IsAuthenticated)
            {
                string resourceStr = context.Resource.First().Value;
                string operationStr = context.Action.First().Value;

                ResourceOperationEnum operation = (ResourceOperationEnum)
                                                    Enum.Parse(typeof(ResourceOperationEnum), operationStr);

                ResourceOperation resourceOperation = new ResourceOperation()
                {
                    ResourceName = resourceStr,
                    Operation = operation
                };

                var rolesName = context.Principal.FindAll(x => x.Type == ClaimTypes.Role)
                                .Select(x => x.Value).ToArray();

                result = CheckAccess(context, resourceOperation, rolesName);
            }

            return result;
        }
        /// <summary>
        /// 驗證是否有權限使用某個資源
        /// </summary>
        /// <param name="resource">資源</param>
        /// <param name="roleId">要驗證的群組Id</param>
        /// <returns>是否有權限</returns>
        public bool Authorize(ResourceOperation resource, string roleId)
        {
            bool authorized = false;

            authorized = uow.Repository<RolesOperationPermission>().Reads().Where(x => x.RoleId == roleId &&
                            x.ResourceName == resource.ResourceName && (x.Operation & resource.Operation) == resource.Operation).Count() > 0;

            return authorized;
        }
        /// <summary>
        /// 驗證是否有權限使用某個資源
        /// </summary>
        /// <param name="resource">資源</param>
        /// <param name="roleNames">要驗證的群組名稱</param>
        /// <returns>是否有權限</returns>
        public bool Authorize(ResourceOperation resource, string[] roleNames)
        {
            bool authorized = false;

            var roleIds = GetRoleIdFromRoleNames(roleNames);

            foreach (var item in roleIds)
            {
                authorized = Authorize(resource, item);

                if (authorized == true)
                {
                    break;
                }
            }

            return authorized;
        }
        /// <summary>
        /// 依照內容建立出AuthorizationContext
        /// </summary>
        /// <param name="principal">目前的Principal</param>
        /// <param name="resourceOperation">目前要驗證的ResourceOperation</param>
        /// <returns>AuthorizationContext</returns>
        public AuthorizationContext CreateAuthorizationContext(ClaimsPrincipal principal, ResourceOperation resourceOperation)
        {
            var actionClaims = new Collection<Claim>();

            var resourceClaims = new Collection<Claim>();

            if (resourceOperation != null)
            {
                actionClaims.Add(new Claim(ActionType, resourceOperation.Operation.ToString()));

                resourceClaims.Add(new Claim(ResourceType, resourceOperation.ResourceName));
            }

            return new AuthorizationContext(
                principal,
                resourceClaims,
                actionClaims);
        }
        /// <summary>
        /// 組合出AuthorizationContext交給ClaimsAuthorizationManager去做是否有權限的判斷
        /// </summary>
        /// <param name="principal">目前的Principal</param>
        /// <param name="resourceOperation">要檢查的ResourceOperation</param>
        /// <returns>true,表示有權限,要不然就是fals</returns>
        public bool CheckAccess(ClaimsPrincipal principal, ResourceOperation resourceOperation)
        {
            var authorisationContext = CreateAuthorizationContext(principal, resourceOperation);

            return AuthorizationManager.CheckAccess(authorisationContext);
        }
 /// <summary>
 /// 新增某一筆的權限到Role Id
 /// </summary>
 /// <param name="roleId">要被新增的Role Id</param>
 /// <param name="resourcOperation">權限內容</param>
 private void AddPemissionToRole(string roleId, ResourceOperation resourcOperation)
 {
     uow.Repository<RolesOperationPermission>().Create(new RolesOperationPermission()
     {
         Operation = resourcOperation.Operation,
         ResourceName = resourcOperation.ResourceName,
         RoleId = roleId
     });
 }
        /// <summary>
        /// 取得某一筆RoleId的權限
        /// </summary>
        /// <param name="roleId">要搜索的role Id</param>
        /// <returns>擁有的權限</returns>
        public List<ResourceOperation> GetResourceOperationForRole(string roleId)
        {
            var result = new List<ResourceOperation>();

            foreach (var item in GetRolesPermissionForRole(roleId))
            {
                var temp = new ResourceOperation();
                temp.Operation = item.Operation;
                temp.ResourceName = item.ResourceName;

                result.Add(temp);
            }

            return result;
        }
 /// <summary>
 /// 檢查是否有權限使用某個ResourceOperation
 /// </summary>
 /// <param name="context">目前的AuthorizationContext</param>
 /// <param name="resourceOperation">要驗證的ResourceOperation</param>
 /// <param name="rolesName">目前使用者的Role</param>
 /// <returns>true,表示有權限,不然則是false</returns>
 public abstract bool CheckAccess(AuthorizationContext context,
     ResourceOperation resourceOperation, string[] rolesName);
        /// Duran 當初alan設計的架構是多一層,避免core被綁死,但起專案沒有比較快,需要起專案會有兩個方法:
        /// 1. 用原架構起,但與資料庫資料庫綁死,那不如寫死在這邊。
        /// 2. 不同的資料庫結構,這段一樣要重寫,加入不同資料庫後,在重新匯入改model,步驟繁瑣
        /// 目前直接綁資料庫與model,之後起下一個專案方便。
        /// TODO: 需要重購:將data access層抽出重寫?會自動產生資料庫架構?(需要在規劃與思考)。
        /// <summary>
        /// 傳入parse出來的ResourceOperation,方便在做處理
        /// 應該是用來記錄操作紀錄用的
        /// </summary>
        /// <param name="resourceOpertation">傳入的ResourceOperation</param>
        /// <param name="httpContext">The HTTP context.</param>
        protected virtual void ProcessResourceOperation(ResourceOperation resourceOpertation, HttpContextBase httpContext)
        {
            var currentIdentity = httpContext.User.Identity as ClaimsIdentity;

            if (currentIdentity.FindFirst(ClaimTypes.NameIdentifier) != null)
            {

                var routeData = httpContext.Request.RequestContext.RouteData;

                var area = routeData.Values.ContainsKey("area") == true ? routeData.GetRequiredString("area") : string.Empty;
                var controller = routeData.GetRequiredString("controller");
                var action = routeData.GetRequiredString("action");

                var operationLog = new UserOperationLog()
                {
                    Area = area,
                    Action = action,
                    Controller = controller,
                    VisitDateTime = DateTime.Now,
                    RawUrl = httpContext.Request.RawUrl,
                    UserId = currentIdentity.FindFirst(ClaimTypes.NameIdentifier).Value,
                    IP = httpContext.Request.ServerVariables["REMOTE_ADDR"]
                };

                if (resourceOpertation != null)
                {
                    operationLog.Operation = resourceOpertation.Operation;
                    operationLog.Resource = resourceOpertation.ResourceName;
                    operationLog.ResourceName = resourceOpertation.DisplayNameWithParent;

                }
                else
                {
                    var siteMap = SiteMaps.Current.RootNode.Descendants.Where(x =>
                        x.Controller == controller && x.Area == area && x.Action == action).FirstOrDefault();

                    var resourceName = string.Empty;

                    if (siteMap != null)
                    {
                        resourceName = siteMap.Title;

                        if (siteMap.ParentNode != null)
                        {
                            resourceName = siteMap.ParentNode.Title + "/" + resourceName;
                        }
                    }

                    operationLog.ResourceName = resourceName;
                }

                DB.Repository<UserOperationLog>().Create(operationLog);
                DB.Save();
            }
        }