예제 #1
0
        public async Task <IResultModel> GetTree()
        {
            if (_cacheHandler.TryGetValue(CacheKeys.EMPLOYEE_TREE, out TreeResultModel <int, EmployeeTreeResultModel> root))
            {
                return(ResultModel.Success(root));
            }

            var allDepart = await _departmentRepository.GetAllAsync();

            var config = _configProvider.Get <PersonnelFilesConfig>();

            root = new TreeResultModel <int, EmployeeTreeResultModel>
            {
                Label = config.CompanyName,
                Item  = new EmployeeTreeResultModel
                {
                    SourceId = "",
                    Name     = config.CompanyName
                }
            };

            root.Children = ResolveTree(allDepart, Guid.Empty, root);

            root.Id = 0;

            if (root.Children.Any())
            {
                await _cacheHandler.SetAsync(CacheKeys.EMPLOYEE_TREE, root);
            }

            return(ResultModel.Success(root));
        }
예제 #2
0
        /// <summary>
        /// 检查邮箱是否存在
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        public async Task <IResultModel> CheckEmail(string email)
        {
            if (_cacheHandler.TryGetValue(CacheKeys.USER_EMAIL, out List <string> root))
            {
                return(ResultModel.Success(root != null && root.Contains(email)));
            }
            var list = _repository.GetAll().Where(w => !string.IsNullOrEmpty(w.Email)).Select(s => s.Email).ToList();
            await _cacheHandler.SetAsync(CacheKeys.USER_EMAIL, list);

            return(ResultModel.Success(root));
        }
예제 #3
0
        /// <summary>
        /// 刷新令牌
        /// </summary>
        /// <param name="refreshToken"></param>
        /// <returns></returns>
        public async Task <LoginResultModel> RefreshToken(string refreshToken)
        {
            var result   = new LoginResultModel();
            var cacheKey = CacheKeys.AUTH_REFRESH_TOKEN + refreshToken;

            if (!_cacheHandler.TryGetValue(cacheKey, out AccountAuthInfoEntity authInfo))
            {
                authInfo = await _authInfoRepository.GetByRefreshToken(refreshToken);

                if (authInfo == null)
                {
                    result.Error = "身份认证信息无效,请重新登录~";
                    return(result);
                }

                //加入缓存
                var expires = (int)(authInfo.RefreshTokenExpiredTime - DateTime.Now).TotalMinutes;
                await _cacheHandler.SetAsync(cacheKey, authInfo, expires);
            }

            if (authInfo.RefreshTokenExpiredTime <= DateTime.Now)
            {
                result.Error = "身份认证信息过期,请重新登录~";
                return(result);
            }

            var account = await _accountRepository.GetAsync(authInfo.AccountId);

            if (account == null)
            {
                result.Error = "账户信息不存在~";
                return(result);
            }
            var checkAccountResult = account.Check();

            if (!checkAccountResult.Successful)
            {
                result.Error = checkAccountResult.Msg;
                return(result);
            }

            result.Success      = true;
            result.AccountId    = account.Id;
            result.AccountType  = account.Type;
            result.TenantId     = account.TenantId;
            result.UserName     = account.UserName;
            result.Name         = account.Name;
            result.Phone        = account.Phone;
            result.Platform     = authInfo.Platform;
            result.RefreshToken = authInfo.RefreshToken;
            result.LoginTime    = _dateTimeHelper.TimeStamp2DateTime(authInfo.LoginTime);
            return(result);
        }
예제 #4
0
        public async Task <T> Resolve <T>() where T : IConfig, new()
        {
            var type     = typeof(T);
            var cacheKey = CacheKeyPrefix + type.FullName;

            if (!_cacheHandler.TryGetValue(cacheKey, out T config))
            {
                config = new T();

                var list = await _storage.GetAll();

                if (list != null && list.Any())
                {
                    var properties = type.GetProperties();
                    foreach (var property in properties)
                    {
                        var key = type.FullName + "." + property.Name;
                        var configDescriptor = list.FirstOrDefault(m => m.Key.EqualsIgnoreCase(key));
                        if (configDescriptor != null)
                        {
                            property.SetValue(config, Convert.ChangeType(configDescriptor.Value, property.PropertyType));
                        }
                        CacheDic.TryAdd(key, cacheKey);
                    }
                }

                await _cacheHandler.SetAsync(cacheKey, config);
            }

            return(config);
        }
예제 #5
0
        public async Task <IResultModel <IList <AreaEntity> > > QueryChildren(string parentCode)
        {
            var result   = new ResultModel <IList <AreaEntity> >();
            var cacheKey = CacheKeys.Area + parentCode;

            if (!_cache.TryGetValue(cacheKey, out IList <AreaEntity> list))
            {
                var parentId = 0;
                if (parentCode.NotNull() && parentCode != "0")
                {
                    var entity = await _repository.GetByCode(parentCode);

                    if (entity != null)
                    {
                        parentId = entity.Id;
                    }
                }

                list = await _repository.QueryChildren(parentId);

                await _cache.SetAsync(cacheKey, list);
            }

            return(result.Success(list));
        }
예제 #6
0
        public async Task <ApplicationUser> GetUserByUserNameAndFilterRoleAssignmentsByClientIdAsync(string username, Guid clientId)
        {
            var normalizedUserName = username.ToUpper().Trim();

            if (!cacheHandler.TryGetValue <ApplicationUser>(normalizedUserName, out var user))
            {
                user = await userManager.Users
                       .Include(u => u.IdentityUserRoles)
                       .ThenInclude(ur => ur.IdentityRole)
                       .Include(u => u.IdentityClaims)
                       .AsNoTracking()
                       .SingleOrDefaultAsync(u => u.NormalizedUserName == normalizedUserName);

                if (user != null && user.EmailConfirmed && user.RoleAssignments.Any())
                {
                    await cacheHandler.SetAsync(normalizedUserName, user, new string[] { nameof(ApplicationUser.Claims), nameof(ApplicationUser.RoleAssignments), nameof(ApplicationUser.IsSystemUser) });
                }
            }

            if (user != null)
            {
                user.IdentityUserRoles = user.IdentityUserRoles.Where(ur => ur.ClientId == clientId).ToList();
                user.IdentityClaims.Add(new ApplicationUserClaim()
                {
                    ClaimType  = FurizaClaimNames.ClientId,
                    ClaimValue = clientId.ToString()
                });
            }

            return(user);
        }
예제 #7
0
        public async Task <IActionResult> PostAsync([FromBody] AuthPost model)
        {
            var result = Unauthorized() as IActionResult;

            var user            = null as ApplicationUser;
            var isAuthenticated = false;

            switch (model.GrantType)
            {
            case GrantType.Password:
                ValidateModelForGrantTypePassword(model);

                user = await cachedUserManager.GetUserByUserNameAndFilterRoleAssignmentsByClientIdAsync(model.User, model.ClientId.Value);

                if (user != null)
                {
                    await ValidateUserStateAsync(user);

                    var checkPassword = await signInManager.CheckPasswordSignInAsync(user, model.Password);

                    if (checkPassword)
                    {
                        isAuthenticated = true;
                    }
                }

                break;

            case GrantType.RefreshToken:
                ValidateModelForGrantTypeRefreshToken(model);

                if (cacheHandler.TryGetValue <RefreshTokenData>(model.RefreshToken, out var refreshTokenData))
                {
                    await cacheHandler.RemoveAsync <RefreshTokenData>(model.RefreshToken);

                    user = await cachedUserManager.GetUserByUserNameAndFilterRoleAssignmentsByClientIdAsync(refreshTokenData.UserName, model.ClientId.Value);

                    isAuthenticated = true;
                }

                break;
            }

            if (isAuthenticated)
            {
                var authPostResult = new AuthPostResult(userPrincipalTokenizer.GenerateToken(user));
                await cacheHandler.SetAsync(authPostResult.RefreshToken, new RefreshTokenData()
                {
                    Token    = authPostResult.RefreshToken,
                    UserName = user.UserName
                });

                result = Ok(authPostResult);
            }

            return(result);
        }
예제 #8
0
        public async Task <IList <string> > Resolve(Guid accountId, Platform platform)
        {
            if (accountId.IsEmpty())
            {
                return(new List <string>());
            }

            var key = $"{CacheKeys.ACCOUNT_PERMISSIONS}{accountId}:{platform.ToInt()}";

            if (!_cache.TryGetValue(key, out IList <string> list))
            {
                list = await _rolePermissionRepository.QueryByAccount(accountId, platform);

                await _cache.SetAsync(key, list);
            }

            return(list);
        }
예제 #9
0
        /// <summary>
        /// 刷新令牌
        /// </summary>
        /// <param name="refreshToken"></param>
        /// <returns></returns>
        public async Task <ResultModel <LoginResultModel> > RefreshToken(string refreshToken)
        {
            var result   = new ResultModel <LoginResultModel>();
            var cacheKey = CacheKeys.AUTH_REFRESH_TOKEN + refreshToken;

            if (!_cacheHandler.TryGetValue(cacheKey, out AccountAuthInfoEntity authInfo))
            {
                authInfo = await _authInfoRepository.GetByRefreshToken(refreshToken);

                if (authInfo == null)
                {
                    return(result.Failed("身份认证信息无效,请重新登录~"));
                }

                //加入缓存
                var expires = (int)(authInfo.RefreshTokenExpiredTime - DateTime.Now).TotalMinutes;
                await _cacheHandler.SetAsync(cacheKey, authInfo, expires);
            }

            if (authInfo.RefreshTokenExpiredTime <= DateTime.Now)
            {
                return(result.Failed("身份认证信息过期,请重新登录~"));
            }

            var account = await _accountRepository.GetAsync(authInfo.AccountId);

            if (account == null)
            {
                return(result.Failed("账户信息不存在"));
            }

            var checkAccountResult = account.Check();

            if (!checkAccountResult.Successful)
            {
                return(result.Failed(checkAccountResult.Msg));
            }

            return(result.Success(new LoginResultModel
            {
                Account = account,
                AuthInfo = authInfo
            }));
        }
예제 #10
0
        public async Task <IList <string> > QueryPermissionList(Guid id, Platform platform)
        {
            var account = await Get(id);

            if (account == null || account.Deleted)
            {
                return(new List <string>());
            }

            var key = $"{CacheKeys.ACCOUNT_PERMISSIONS}:{id}:{platform.ToInt()}";

            if (!_cache.TryGetValue(key, out IList <string> list))
            {
                list = await _permissionRepository.QueryCodeByAccount(id, platform);

                await _cache.SetAsync(key, list);
            }

            return(list);
        }
예제 #11
0
        public async Task <T> Resolve <T>() where T : IConfig, new()
        {
            var type     = typeof(T);
            var cacheKey = CacheKeyPrefix + type.FullName;

            if (!_cacheHandler.TryGetValue(cacheKey, out T config))
            {
                config = new T();

                var list = await _storage.GetAll();

                if (list != null && list.Any())
                {
                    var properties = type.GetProperties();
                    foreach (var property in properties)
                    {
                        var key = type.FullName + "." + property.Name;
                        var configDescriptor = list.FirstOrDefault(m => m.Key.EqualsIgnoreCase(key));
                        if (configDescriptor != null)
                        {
                            property.SetValue(config, configDescriptor.Value);
                        }
                        else
                        {
                            configDescriptor = new ConfigDescriptor
                            {
                                Key     = key,
                                Value   = string.Empty,
                                Remarks = property.Name
                            };
                            var value = property.GetValue(config);
                            if (value != null)
                            {
                                configDescriptor.Value = value.ToString();
                            }

                            var desc = property.GetCustomAttributes(false)
                                       .FirstOrDefault(m => m.GetType() == typeof(DescriptionAttribute));
                            if (desc != null)
                            {
                                configDescriptor.Remarks = ((DescriptionAttribute)desc).Description;
                            }

                            await _storage.Add(configDescriptor);
                        }
                        CacheDic.TryAdd(key, cacheKey);
                    }
                }

                await _cacheHandler.SetAsync(cacheKey, config);
            }

            return(config);
        }
예제 #12
0
 private async Task SetUserEmailCache(string email)
 {
     if (_cacheHandler.TryGetValue(CacheKeys.USER_EMAIL, out List <string> root))
     {
         root = root == null ? new List <string>() : root;
         if (!root.Contains(email))
         {
             root.Add(email);
         }
         await _cacheHandler.SetAsync(CacheKeys.USER_EMAIL, root);
     }
 }
예제 #13
0
        public async Task <IResultModel> QueryChildren(int parentId)
        {
            var cacheKey = AreaCacheKey + parentId;

            if (!_cache.TryGetValue(cacheKey, out IList <AreaEntity> list))
            {
                list = await _repository.QueryChildren(parentId);

                await _cache.SetAsync(cacheKey, list);
            }

            return(ResultModel.Success(list));
        }
예제 #14
0
        public async Task <ResultModel <LoginResultModel> > RefreshToken(string refreshToken)
        {
            var result   = new ResultModel <LoginResultModel>();
            var cacheKey = string.Format(CacheKeys.RefreshToken, refreshToken);

            if (!_cacheHandler.TryGetValue(cacheKey, out AccountAuthInfoEntity authInfo))
            {
                authInfo = await _authInfoRepository.GetByRefreshToken(refreshToken);

                if (authInfo == null)
                {
                    return(result.Failed("刷新令牌无效"));
                }

                //加入缓存
                var expires = (int)(authInfo.RefreshTokenExpiredTime - DateTime.Now).TotalMinutes;
                await _cacheHandler.SetAsync(cacheKey, authInfo, expires);
            }

            if (authInfo.RefreshTokenExpiredTime <= DateTime.Now)
            {
                return(result.Failed("刷新令牌过期"));
            }

            var account = await _accountRepository.GetAsync(authInfo.AccountId);

            var checkAccountResult = CheckAccount(account);

            if (!checkAccountResult.Successful)
            {
                return(result.Failed(checkAccountResult.Msg));
            }

            return(result.Success(new LoginResultModel
            {
                Account = account,
                AuthInfo = authInfo
            }));
        }
        public async Task <IResultModel> Select(string group, string code)
        {
            if (group.IsNull() || code.IsNull())
            {
                return(ResultModel.Failed("请指定分组和编码"));
            }

            var config = _configProvider.Get <CommonConfig>();
            var key    = $"{CacheKeys.DICT_SELECT}:{group.ToUpper()}_{code.ToUpper()}";

            if (config.DictCacheEnabled && _cacheHandler.TryGetValue(key, out List <OptionResultModel> result))
            {
                return(ResultModel.Success(result));
            }

            var list = await _itemRepository.QueryChildren(group, code);

            result = list.Select(m => new OptionResultModel
            {
                Label = m.Name,
                Value = m.Value,
                Data  = new
                {
                    m.Id,
                    m.Name,
                    m.Value,
                    m.Extend,
                    m.Icon,
                    m.Level
                }
            }).ToList();

            if (config.DictCacheEnabled)
            {
                await _cacheHandler.SetAsync(key, result);
            }

            return(ResultModel.Success(result));
        }
예제 #16
0
        public async Task <IResultModel> GetTree()
        {
            if (_cacheHandler.TryGetValue(CacheKeys.MENU_TREE, out List <TreeResultModel <string, MenuTreeResultModel> > list))
            {
                return(ResultModel.Success(list));
            }

            var all = await _menuRepository.GetListAsync(m => m.IsDel == false);

            list = ResolveTree(all, Guid.Empty.ToString("N"));

            await _cacheHandler.SetAsync(CacheKeys.MENU_TREE, list);

            return(ResultModel.Success(list));
        }
예제 #17
0
        public async Task <IResultModel> GetTree()
        {
            if (_cacheHandler.TryGetValue(CacheKeys.DEPARTMENT_TREE, out List <TreeResultModel <Guid, DepartmentTreeResultModel> > list))
            {
                return(ResultModel.Success(list));
            }

            var all = await _repository.GetAllAsync();

            list = ResolveTree(all, Guid.Empty);

            await _cacheHandler.SetAsync(CacheKeys.DEPARTMENT_TREE, list);

            return(ResultModel.Success(list));
        }
예제 #18
0
        public async Task <IResultModel> Select()
        {
            if (!_cacheHandler.TryGetValue(CacheKeys.POST_SELECT, out List <OptionResultModel> list))
            {
                var all = await _repository.GetAllAsync();

                list = all.Select(m => new OptionResultModel
                {
                    Label = m.Name,
                    Value = m.Id
                }).ToList();

                await _cacheHandler.SetAsync(CacheKeys.POST_SELECT, list);
            }

            return(ResultModel.Success(list));
        }
        public async Task <IList <string> > Resolve(Guid uid)
        {
            if (uid.IsEmpty())
            {
                return(new List <string>());
            }

            var key = $"{CacheKeys.ACCOUNT_PERMISSIONS}{uid}";

            if (!_cache.TryGetValue(key, out IList <string> list))
            {
                list = await _rolePermissionRepository.QueryByAccount(uid);

                await _cache.SetAsync(key, list);
            }

            return(list);
        }
예제 #20
0
        public async Task <AccountEntity> Get(Guid id)
        {
            var key = CacheKeys.ACCOUNT + id;

            if (_cache.TryGetValue(key, out AccountEntity account))
            {
                return(account);
            }

            account = await _accountRepository.GetAsync(id);

            if (account != null)
            {
                await _cache.SetAsync(key, account);
            }

            return(account);
        }
예제 #21
0
        public async Task <ResultModel <LoginResultModel> > RefreshToken(string refreshToken)
        {
            var result   = new ResultModel <LoginResultModel>();
            var cacheKey = string.Format(CacheKeys.RefreshToken, refreshToken);

            if (!_cacheHandler.TryGetValue(cacheKey, out UserAuthEntity authInfo))
            {
                authInfo = await _userAuthRepository.FirstAsync(m => m.RefreshToken == refreshToken);

                if (authInfo == null)
                {
                    return(result.Failed("身份认证信息无效,请重新登录~"));
                }

                //加入缓存
                var expires = (int)(authInfo.ExpiredTime - DateTime.Now).TotalMinutes;
                await _cacheHandler.SetAsync(cacheKey, authInfo, expires);
            }

            if (authInfo.ExpiredTime <= DateTime.Now)
            {
                return(result.Failed("身份认证信息过期,请重新登录~"));
            }

            var user = await _userRepository.FirstAsync(authInfo.UserId);

            var checkAccountResult = CheckUser(user);

            if (!checkAccountResult.Successful)
            {
                return(result.Failed(checkAccountResult.Msg));
            }

            //获取用户角色
            var roles = await _roleUserRepository.QueryByUserId(user.Id);

            return(result.Success(new LoginResultModel
            {
                User = user,
                AuthInfo = authInfo,
                RoleCodes = string.Join(",", roles.Select(m => m.RoleCode).ToList()),
                RoleNames = string.Join(",", roles.Select(m => m.RoleName).ToList())
            }));
        }
예제 #22
0
        public async Task <List <PermissionEntity> > QueryPermissionList(Guid id)
        {
            var entity = await _accountRepository.GetAsync(id);

            if (entity == null)
            {
                return(new List <PermissionEntity>());
            }

            var key = CacheKeys.AccountPermissionListKey + id;

            if (!_cache.TryGetValue(key, out List <PermissionEntity> list))
            {
                list = (await _permissionRepository.QueryByAccount(id)).ToList();
                await _cache.SetAsync(key, list);
            }

            return(list);
        }
예제 #23
0
        public async Task <IResultModel <SystemConfigModel> > GetConfig(string host = null)
        {
            var result = new ResultModel <SystemConfigModel>();

            if (!_cache.TryGetValue(CacheKeys.SystemConfigCacheKey, out SystemConfigModel model))
            {
                var configList = await _configRepository.QueryByPrefix("sys_");

                model = new SystemConfigModel();

                GetConfig(model, configList);

                await _cache.SetAsync(CacheKeys.SystemConfigCacheKey, model);
            }

            if (model.Base.Logo.NotNull() && !model.Base.Logo.StartsWith("http") && host.NotNull())
            {
                model.Base.Logo = new Uri($"{host}/upload/{model.Base.Logo}").ToString().ToLower();
            }

            return(result.Success(model));
        }
예제 #24
0
        public async Task <TDataEntity> FindById(string entityId)
        {
            if (string.IsNullOrWhiteSpace(entityId))
            {
                throw new ArgumentNullException(nameof(entityId));
            }

            if (_cacheHandler.TryGetValue(entityId, out TDataEntity dataEntity))
            {
                return(dataEntity);
            }

            var command = BuildFindByIdQuery();

            using (var connection = new SqlConnection(_databaseConfiguration.ConnectionString))
            {
                var result = await connection.QuerySingleAsync <TDataEntity>(command, new { Id = entityId });

                _cacheHandler.AddToCache(result);

                return(result);
            }
        }
예제 #25
0
        public async Task <IResultModel <SystemConfigModel> > GetConfig(string host = null)
        {
            var result = new ResultModel <SystemConfigModel>();

            if (!_cache.TryGetValue(CacheKeys.SystemConfigCacheKey, out SystemConfigModel model))
            {
                model = new SystemConfigModel();

                var configList = await _configRepository.QueryByPrefix(SystemConfigPrefix);

                foreach (var config in configList)
                {
                    switch (config.Key)
                    {
                    case SystemConfigKey.Title:
                        model.Title = config.Value;
                        break;

                    case SystemConfigKey.Logo:
                        model.Logo = config.Value;
                        break;

                    case SystemConfigKey.Home:
                        model.Home = config.Value;
                        break;

                    case SystemConfigKey.UserInfoPage:
                        model.UserInfoPage = config.Value;
                        break;

                    case SystemConfigKey.ButtonPermission:
                        model.ButtonPermission = config.Value.ToBool();
                        break;

                    case SystemConfigKey.PermissionValidate:
                        model.PermissionValidate = config.Value.ToBool();
                        break;

                    case SystemConfigKey.Auditing:
                        model.Auditing = config.Value.ToBool();
                        break;

                    case SystemConfigKey.LoginVerifyCode:
                        model.LoginVerifyCode = config.Value.ToBool();
                        break;

                    case SystemConfigKey.ToolbarFullscreen:
                        model.Toolbar.Fullscreen = config.Value.ToBool();
                        break;

                    case SystemConfigKey.ToolbarSkin:
                        model.Toolbar.Skin = config.Value.ToBool();
                        break;

                    case SystemConfigKey.ToolbarLogout:
                        model.Toolbar.Logout = config.Value.ToBool();
                        break;

                    case SystemConfigKey.ToolbarUserInfo:
                        model.Toolbar.UserInfo = config.Value.ToBool();
                        break;

                    case SystemConfigKey.CustomCss:
                        model.CustomCss = config.Value;
                        break;
                    }
                }

                await _cache.SetAsync(CacheKeys.SystemConfigCacheKey, model);
            }

            if (host.NotNull() && model.Logo.NotNull())
            {
                model.LogoUrl = new Uri($"{host}/upload/{model.Logo}").ToString().ToLower();
            }

            return(result.Success(model));
        }
예제 #26
0
        public async Task <IResultModel> GetTree()
        {
            //先取缓存
            if (_cacheHandler.TryGetValue(CacheKeys.PermissionTree, out TreeResultModel <int, PermissionTreeResultModel> root))
            {
                return(ResultModel.Success(root));
            }

            var id = 0;

            root = new TreeResultModel <int, PermissionTreeResultModel>
            {
                Id    = id,
                Label = _systemConfig.Base.Title,
                Item  = new PermissionTreeResultModel()
            };
            root.Path.Add(root.Label);

            var modules     = _moduleRepository.GetAllAsync();
            var permissions = await _repository.GetAllAsync();

            //模块
            foreach (var module in await modules)
            {
                var moduleNode = new TreeResultModel <int, PermissionTreeResultModel>
                {
                    Id    = ++id,
                    Label = module.Name,
                    Item  = new PermissionTreeResultModel
                    {
                        Label = module.Name,
                        Code  = module.Code
                    }
                };

                moduleNode.Path.AddRange(root.Path);
                moduleNode.Path.Add(module.Name);

                var controllers = permissions.Where(m => m.ModuleCode.EqualsIgnoreCase(module.Code)).DistinctBy(m => m.Controller);
                //控制器
                foreach (var controller in controllers)
                {
                    var controllerName = controller.Name.Split('_')[0];
                    var controllerNode = new TreeResultModel <int, PermissionTreeResultModel>
                    {
                        Id    = ++id,
                        Label = controllerName,
                        Item  = new PermissionTreeResultModel
                        {
                            Label = controllerName,
                            Code  = controller.Controller
                        }
                    };

                    controllerNode.Path.AddRange(moduleNode.Path);
                    controllerNode.Path.Add(controllerName);

                    var permissionList = permissions.Where(m => m.ModuleCode.EqualsIgnoreCase(module.Code) && m.Controller.EqualsIgnoreCase(controller.Controller));
                    //权限
                    foreach (var permission in permissionList)
                    {
                        var permissionName = permission.Name.Contains("_") ? permission.Name.Split('_')[1] : permission.Name;
                        var permissionNode = new TreeResultModel <int, PermissionTreeResultModel>
                        {
                            Id    = ++id,
                            Label = permissionName,
                            Item  = new PermissionTreeResultModel
                            {
                                Label        = permissionName,
                                Code         = permission.Code,
                                IsPermission = true
                            }
                        };

                        permissionNode.Path.AddRange(controllerNode.Path);
                        permissionNode.Path.Add(permissionName);

                        controllerNode.Children.Add(permissionNode);
                    }

                    moduleNode.Children.Add(controllerNode);
                }
                root.Children.Add(moduleNode);
            }

            await _cacheHandler.SetAsync(CacheKeys.PermissionTree, root);

            return(ResultModel.Success(root));
        }