using AutoMapper; using AutoMapper.QueryableExtensions; using IRaCIS.Application.ExpressionExtend; using IRaCIS.Application.Interfaces; using IRaCIS.Application.ViewModels; using IRaCIS.Core.Application.Contracts.RequestAndResponse; using IRaCIS.Core.Domain.Interfaces; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infrastructure; using IRaCIS.Infra.Data.ExpressionExtend; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text.RegularExpressions; using System.Threading.Tasks; using IRaCIS.Core.Domain.Share.AuthUser; namespace IRaCIS.Application.Services { public class UserService : IUserService { private readonly IUserRepository _userRepository; private readonly IUserRoleRepository _userRoleRepository; private readonly IRoleMenuFunctionRepository _roleMenuRepository; private readonly IRoleRepository _roleRepository; private readonly IMenuFunctionRepository _menuRepository; private readonly IDictionaryRepository _dictionaryRepository; private readonly IMailVerificationService _mailVerificationService; private readonly IVerificationCodeRepository _verificationCodeRepository; private readonly IDoctorRepository _doctorRepository; private readonly IUserInfo _userInfo; private readonly IMapper _mapper; public UserService(IUserRepository userRepository, IUserRoleRepository userRoleRepository, IRoleMenuFunctionRepository roleMenuRepository, IRoleRepository roleRepository, IMenuFunctionRepository menuRepository, IDictionaryRepository dictionaryRepository, IMailVerificationService mailVerificationService, IVerificationCodeRepository verificationCodeRepository, IDoctorRepository doctorRepository, IUserInfo userInfo, IMapper mapper) { _userRepository = userRepository; _userRoleRepository = userRoleRepository; _roleMenuRepository = roleMenuRepository; _roleRepository = roleRepository; _menuRepository = menuRepository; _dictionaryRepository = dictionaryRepository; _mailVerificationService = mailVerificationService; _verificationCodeRepository = verificationCodeRepository; _doctorRepository = doctorRepository; _userInfo = userInfo; _mapper = mapper; } public async Task SendVerificationCode(string emailOrPhone, int verificationType, bool isReviewer = false) { if (string.IsNullOrEmpty(emailOrPhone)) { return ResponseOutput.NotOk(verificationType == 0 ? "Please input email" : "Please input Phone"); } //防止输入前后有空格 var emailOrPhoneStr = emailOrPhone.Trim(); //检查手机或者邮箱是否有效 if (!Regex.IsMatch(emailOrPhoneStr, @"/^1[34578]\d{9}$/") && !Regex.IsMatch(emailOrPhoneStr, @"^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$")) { return ResponseOutput.NotOk(verificationType == 0 ? "Please input a legal email" : "Please input a legal phone"); } //医生登录 if (isReviewer) { var exist = _doctorRepository.GetAll().Any(t => t.EMail == emailOrPhoneStr || t.Phone == emailOrPhoneStr); if (!exist) { return ResponseOutput.NotOk(verificationType == 0 ? "No user has this email" : "No user has this phone"); } var user = _doctorRepository.GetAll().First(t => t.EMail == emailOrPhoneStr || t.Phone == emailOrPhoneStr); //邮箱 if (verificationType == 0) { //验证码 6位 int verificationCode = new Random().Next(100000, 1000000); await _mailVerificationService.SendMail(user.Id, user.ChineseName, emailOrPhoneStr, verificationCode); } //手机短信 else { } } else//管理用户登录 { //查找改邮箱或者手机的用户 var exist = _userRepository.GetAll().Any(t => t.EMail == emailOrPhoneStr || t.Phone == emailOrPhoneStr); if (!exist) { return ResponseOutput.NotOk(verificationType == 0 ? "No user has this email" : "No user has this phone"); } var user = _userRepository.GetAll().First(t => t.EMail == emailOrPhoneStr || t.Phone == emailOrPhoneStr); //邮箱 if (verificationType == 0) { //验证码 6位 int verificationCode = new Random().Next(100000, 1000000); await _mailVerificationService.SendMail(user.Id, user.RealName, emailOrPhoneStr, verificationCode); } //手机短信 else { } } return ResponseOutput.Ok(); } public IResponseOutput SetNewPassword(string emailOrPhone, int verificationType, string verificationCode, string newPwd, bool isReviewer) { if (isReviewer) { var emailOrPhoneStr = emailOrPhone.Trim(); var verificationCodeStr = verificationCode.Trim(); var user = _doctorRepository.GetAll().First(t => t.EMail == emailOrPhoneStr || t.Phone == emailOrPhoneStr); var verificationRecord = _verificationCodeRepository .GetAll().FirstOrDefault(t => t.UserId == user.Id && t.Code == verificationCodeStr && t.CodeType == verificationType); //检查数据库是否存在该验证码 if (verificationRecord == null) { return ResponseOutput.NotOk("Verification code error"); } else { //检查验证码是否失效 if (verificationRecord.ExpirationTime < DateTime.Now) { return ResponseOutput.NotOk("Verification code time has expired"); } else //验证码正确 并且 没有超时 { //更新密码 var success = _doctorRepository.Update(t => t.Id == user.Id, u => new Doctor() { Password = newPwd }); //删除验证码历史记录 _verificationCodeRepository.Delete(t => t.UserId == user.Id && t.CodeType == verificationType); return ResponseOutput.Result(success, "database update failed"); } } } else { var emailOrPhoneStr = emailOrPhone.Trim(); var verificationCodeStr = verificationCode.Trim(); var user = _userRepository.GetAll().First(t => t.EMail == emailOrPhoneStr || t.Phone == emailOrPhoneStr); var verificationRecord = _verificationCodeRepository .GetAll().FirstOrDefault(t => t.UserId == user.Id && t.Code == verificationCodeStr && t.CodeType == verificationType); //检查数据库是否存在该验证码 if (verificationRecord == null) { return ResponseOutput.NotOk("Verification code error"); } else { //检查验证码是否失效 if (verificationRecord.ExpirationTime < DateTime.Now) { return ResponseOutput.NotOk("Verification code time has expired"); } else //验证码正确 并且 没有超时 { //更新密码 //var pwd = MD5Helper.Md5(newPwd); //var count = _doctorRepository.Update().Where(t => t.Id == doctor.Id).Set(d => d.Password == pwd).ExecuteAffrows(); var success = _userRepository.Update(t => t.Id == user.Id, u => new User() { Password = newPwd }); //删除验证码历史记录 _verificationCodeRepository.Delete(t => t.UserId == user.Id && t.CodeType == verificationType); return ResponseOutput.Result(success, "database update failed"); } } } } public IResponseOutput Login(string userName, string password) { var name = userName.Trim(); var passwordMd5 = password.Trim(); var user = _userRepository.GetAll().FirstOrDefault(u => u.UserName == name && u.Password == passwordMd5); if (user != null) { if (user.Status == 0) { return ResponseOutput.NotOk("用户已被禁用!", new LoginReturnDTO()); } var userLoginReturnModel = new LoginReturnDTO(); userLoginReturnModel.BasicInfo = new UserBasicInfo() { Id = user.Id, UserName = user.UserName, RealName = user.RealName, Sex = user.Sex }; if (user.SuperAdmin) { userLoginReturnModel.BasicInfo.IsAdmin = true; userLoginReturnModel.MenuTree = GetAdminMenuTree().FirstOrDefault()?.Childrens; userLoginReturnModel.FuncDictionary = DealFunction(GetAdminFunctionTree().FirstOrDefault()?.Childrens); } else { var menuTree = GetUserMenuTreeNew(userLoginReturnModel.BasicInfo.Id) .FirstOrDefault()?.Childrens; userLoginReturnModel.MenuTree = menuTree ?? new List(); userLoginReturnModel.FuncDictionary = DealFunction(GetUserFuncTreeNew(userLoginReturnModel.BasicInfo.Id)?.First().Childrens); } return ResponseOutput.Ok(userLoginReturnModel); } //此处下面 代码 为了支持医生也能登录 而且前端不加选择到底是管理用户 还是医生用户 var doctor = _doctorRepository.GetAll().FirstOrDefault(u => u.Phone == name && u.Password == passwordMd5); if (doctor != null) { var userLoginReturnModel = new LoginReturnDTO(); userLoginReturnModel.BasicInfo = new UserBasicInfo() { Id = doctor.Id, UserName = doctor.LastName + " / " + doctor.FirstName, RealName = doctor.ChineseName, Sex = doctor.Sex, IsReviewer = true, ReviewerCode = doctor.Code }; var menuTree = GetUserMenuTreeNew(userLoginReturnModel.BasicInfo.Id, true) .FirstOrDefault()?.Childrens; userLoginReturnModel.MenuTree = menuTree ?? new List(); userLoginReturnModel.FuncDictionary = DealFunction(GetUserFuncTreeNew(userLoginReturnModel.BasicInfo.Id, true)?.FirstOrDefault()?.Childrens); return ResponseOutput.Ok(userLoginReturnModel); } return ResponseOutput.NotOk("Please check the user name or password.", new LoginReturnDTO()); } public IResponseOutput VerifySignature(string userName, string password) { var name = userName.Trim(); var passwordMd5 = password.Trim(); var user = _userRepository.GetAll().FirstOrDefault(u => u.UserName == name && u.Password == passwordMd5); if (user != null) { if (user.Status == 0) { return ResponseOutput.NotOk("用户已被禁用!", false); } return ResponseOutput.Ok(true); } return ResponseOutput.NotOk("Password error!", false); } public Dictionary> DealFunction(List functionTreeNodes) { Dictionary> returnDictionary = new Dictionary>(); functionTreeNodes?.ForEach(t => { List functionNames = new List(); returnDictionary.Add(t.RouteName, Test(t.Childrens, functionNames)); }); return returnDictionary; } public List Test(List functionTreeNodes, List functionNames) { functionTreeNodes?.ForEach(t => { if (!string.IsNullOrEmpty(t.FunctionName)) { functionNames.Add(t.FunctionName); } else { Test(t.Childrens, functionNames); } }); return functionNames; } /// /// 管理员获取菜单树 /// /// public List GetAdminMenuTree() { var allMenuList = _menuRepository.GetAll().Where(t => t.Status == 1 && t.IsFunction == false && t.SuperAdmin).Select(menu => new MenuFuncTreeNodeView() { Id = menu.Id, ParentId = menu.ParentId, component = menu.Component, meta = new Meta { MetaActiveMenu = menu.MetaActiveMenu, MetaBreadcrumb = menu.MetaBreadcrumb, MetaIcon = menu.MetaIcon, MetaTitle = menu.MetaTitle, }, hidden = menu.Hidden, redirect = menu.Redirect, routeName = menu.RouteName, path = menu.Path, ShowOrder = menu.ShowOrder }).ToList(); return GetMenuTree(Guid.Empty, allMenuList); } public List GetUserMenuTreeNew(Guid userId, bool isReviewer = false) { if (!isReviewer) { var allMenuList = (from menuId in (from userRole in _userRoleRepository.GetAll() .Where(t => t.UserId == userId) join roleMenu in _roleMenuRepository.GetAll() on userRole.RoleId equals roleMenu.RoleId select roleMenu.MenuFunctionId).Distinct() join menu in _menuRepository.GetAll().Where(t => t.IsFunction == false) on menuId equals menu.Id select new MenuFuncTreeNodeView() { Id = menu.Id, ParentId = menu.ParentId, component = menu.Component, hidden = menu.Hidden, redirect = menu.Redirect, routeName = menu.RouteName, path = menu.Path, ShowOrder = menu.ShowOrder, meta = new Meta { MetaActiveMenu = menu.MetaActiveMenu, MetaBreadcrumb = menu.MetaBreadcrumb, MetaIcon = menu.MetaIcon, MetaTitle = menu.MetaTitle, }, }).Distinct().ToList(); return GetMenuTree(Guid.Empty, allMenuList); } else { //内置角色Id 不允许删除 var roleId = Guid.Parse("4062ECFF-C6D4-4C22-2CAF-08D85F6F9A95"); var allMenuList = (from roleMenu in _roleMenuRepository.GetAll().Where(t => t.RoleId == roleId) join menu in _menuRepository.GetAll().Where(t => t.IsFunction == false) on roleMenu.MenuFunctionId equals menu.Id select new MenuFuncTreeNodeView() { Id = menu.Id, ParentId = menu.ParentId, component = menu.Component, hidden = menu.Hidden, redirect = menu.Redirect, routeName = menu.RouteName, path = menu.Path, ShowOrder = menu.ShowOrder, meta = new Meta { MetaActiveMenu = menu.MetaActiveMenu, MetaBreadcrumb = menu.MetaBreadcrumb, MetaIcon = menu.MetaIcon, MetaTitle = menu.MetaTitle, }, }).Distinct().ToList(); return GetMenuTree(Guid.Empty, allMenuList); } } public List GetMenuTree(Guid parentId, List allMenuList) { //树节点集合 每个节点包含一个菜单项 和一个子菜单集合 List treeList = new List(); // 根据父菜单节点获取子菜单节点 并且进行排序 List menuList = allMenuList.Where(x => x.ParentId == parentId).OrderBy(t => t.ShowOrder).ToList(); foreach (var menuItem in menuList) { MenuFuncTreeNodeView treeItem = new MenuFuncTreeNodeView() { Id = menuItem.Id, component = menuItem.component, hidden = menuItem.hidden, routeName = menuItem.routeName, path = menuItem.path, ParentId = menuItem.ParentId, ShowOrder = menuItem.ShowOrder, redirect = menuItem.redirect, meta = new Meta { MetaActiveMenu = menuItem.meta.MetaActiveMenu, MetaBreadcrumb = menuItem.meta.MetaBreadcrumb, MetaIcon = menuItem.meta.MetaIcon, MetaTitle = menuItem.meta.MetaTitle, }, Childrens = GetMenuTree(menuItem.Id, allMenuList) }; treeList.Add(treeItem); } return treeList; } public List GetFuncTree(Guid parentId, List allFuncList) { //树节点集合 每个节点包含一个菜单项 和一个子菜单集合 List treeList = new List(); // 根据父菜单节点获取子菜单节点 并且进行排序 List menuList = allFuncList.Where(x => x.ParentId == parentId).OrderBy(t => t.ShowOrder).ToList(); foreach (var menuItem in menuList) { FunctionTreeNodeDTO treeItem = new FunctionTreeNodeDTO() { Id = menuItem.Id, FunctionName = menuItem.FunctionName, RouteName = menuItem.RouteName, ParentId = menuItem.ParentId, ShowOrder = menuItem.ShowOrder, Childrens = GetFuncTree(menuItem.Id, allFuncList) }; treeList.Add(treeItem); } return treeList; } public List GetAdminFunctionTree() { var allFuncList = _menuRepository.GetAll().Where(t => t.Status == 1).Select(menu => new FunctionTreeNodeDTO() { Id = menu.Id, ParentId = menu.ParentId, FunctionName = menu.FunctionName, RouteName = menu.RouteName, ShowOrder = menu.ShowOrder }).ToList(); //var root = _menuRepository.GetAll().Where(t => t.Status == 1 && t.RouteName == "Root").Select(menu => // new FunctionTreeNodeView() // { // Id = menu.Id, // ParentId = menu.ParentId, // FunctionName = menu.FunctionName, // RouteName = menu.RouteName, // ShowOrder = menu.ShowOrder // }).First(); //allFuncList.Add(root); return GetFuncTree(Guid.Empty, allFuncList); } public List GetUserFuncTreeNew(Guid userId, bool isReviewer = false) { if (!isReviewer) { var allFuncList = (from menuId in (from userRole in _userRoleRepository.GetAll() .Where(t => t.UserId == userId) join roleMenu in _roleMenuRepository.GetAll() on userRole.RoleId equals roleMenu.RoleId select roleMenu.MenuFunctionId).Distinct() join menu in _menuRepository.GetAll() on menuId equals menu.Id select new FunctionTreeNodeDTO() { Id = menu.Id, ParentId = menu.ParentId, RouteName = menu.RouteName, FunctionName = menu.FunctionName, ShowOrder = menu.ShowOrder }).Distinct().ToList(); return GetFuncTree(Guid.Empty, allFuncList); } else { //内置角色Id 不允许删除 var roleId = Guid.Parse("4062ECFF-C6D4-4C22-2CAF-08D85F6F9A95"); var allFuncList = (from menuId in _roleMenuRepository.GetAll().Where(t => t.RoleId == roleId) .Select(t => t.MenuFunctionId) join menu in _menuRepository.GetAll() on menuId equals menu.Id select new FunctionTreeNodeDTO() { Id = menu.Id, ParentId = menu.ParentId, RouteName = menu.RouteName, FunctionName = menu.FunctionName, ShowOrder = menu.ShowOrder }).Distinct().ToList(); return GetFuncTree(Guid.Empty, allFuncList); } } public IEnumerable GetAllUser() { return _userRepository.GetAll().ProjectTo(_mapper.ConfigurationProvider).ToList(); } private Expression> GetUserSearchLambda(UserListQueryDTO userQueryModel) { Expression> userLambda = x => x.SuperAdmin == false; if (!string.IsNullOrWhiteSpace(userQueryModel.UserName)) { userLambda = userLambda.And(t => t.UserName.Contains(userQueryModel.UserName.Trim())); } if (!string.IsNullOrWhiteSpace(userQueryModel.Phone)) { userLambda = userLambda.And(t => t.Phone.Contains(userQueryModel.Phone.Trim())); } if (!string.IsNullOrWhiteSpace(userQueryModel.OrganizationName)) { userLambda = userLambda.And(t => t.OrganizationName.Contains(userQueryModel.OrganizationName.Trim())); } if (Guid.Empty != userQueryModel.UserType && userQueryModel.UserType != null) { userLambda = userLambda.And(t => t.UserTypeId == userQueryModel.UserType); } if (userQueryModel.UserState != null) { switch (userQueryModel.UserState) { case 1: userLambda = userLambda.And(t => t.Status == 1);//可用 break; case 0: userLambda = userLambda.And(t => t.Status == 0);//禁用 break; default: break; } } return userLambda; } /// 获取用户列表 public PageOutput GetUserList(UserListQueryDTO param) { var userLambda = GetUserSearchLambda(param); IQueryable userQueryable = default; userQueryable = from user in _userRepository.GetAll().Where(userLambda) join dicItem in _dictionaryRepository.GetAll() on user.UserTypeId equals dicItem.Id into d from userType in d.DefaultIfEmpty() select new UserListDTO() { Id = user.Id, Password = user.Password, RealName = user.RealName, Sex = user.Sex, UserName = user.UserName, Status = user.Status, Phone = user.Phone, EMail = user.EMail, UserTypeId = userType == null ? Guid.Empty : userType.Id, UserType = userType == null ? string.Empty : userType.Value, OrganizationName = user.OrganizationName, Code = user.Code, }; var count = userQueryable.Count(); var propName = param.SortField == string.Empty ? "UserName" : param.SortField; userQueryable = param.Asc ? userQueryable.OrderBy(propName) : userQueryable.OrderByDescending(propName); userQueryable = userQueryable.Skip((param.PageIndex - 1) * param.PageSize).Take(param.PageSize); var userList = userQueryable.ToList(); var userIds = userList.Select(t => t.Id).ToList(); var userRoleList = (from userRole in _userRoleRepository.GetAll().Where(t => userIds.Contains(t.UserId)) join role in _roleRepository.GetAll() on userRole.RoleId equals role.Id select new UserIdRoleName { RoleName = role.RoleName, RoleDescription = role.RoleDescription, UserId = userRole.UserId }).ToList().GroupBy(t => t.UserId).Select(u => new UserIdRoleNameList { UserId = u.Key, RoleList = u.Select(t => new RoleDTO() { RoleName = t.RoleName, RoleDescription = t.RoleDescription }) }); userList.ForEach(t => { var temp = userRoleList.FirstOrDefault(u => u.UserId == t.Id); if (temp != null) { t.RoleNameList = temp.RoleList; } }); return new PageOutput(param.PageIndex, param.PageSize, count, userList); } public UserDetailDTO GetUserById(Guid id) { var temp = _userRepository.GetAll().ProjectTo(_mapper.ConfigurationProvider).FirstOrDefault(t => t.Id == id); var dicItem = _dictionaryRepository.FindSingleOrDefault(u => u.Id == temp.UserTypeId); temp.UserTypeName = dicItem == null ? string.Empty : dicItem.Value; return temp; } public IResponseOutput AddUser(UserCommand userAddModel, Guid userId) { if (_userRepository.GetAll().Any(t => t.UserName == userAddModel.UserName || t.EMail == userAddModel.EMail)) { return ResponseOutput.NotOk("User name or email already exist.", new UserAddedReturnDTO()); } var saveItem = _mapper.Map(userAddModel); #region 处理code var last = _userRepository.GetAll().OrderByDescending(c => c.Code).FirstOrDefault(); if (last != null) { var num = 0; if (int.TryParse(last.Code.Substring(1, 4), out num)) { saveItem.Code = SystemConfig.UserCodePrefix + (++num).ToString().PadLeft(4, '0'); } else { return ResponseOutput.NotOk("Generated Code failed.", new UserAddedReturnDTO()); } } else { saveItem.Code = SystemConfig.UserCodePrefix + 1.ToString().PadLeft(4, '0'); } if (userAddModel.OrganizationName.ToUpper().Contains(StaticData.MainCompany)) { saveItem.IsZhiZhun = true; } else { saveItem.IsZhiZhun = false; } #endregion saveItem.Password = MD5Helper.Md5(StaticData.DefaultPassword); saveItem.CreateUserId = Guid.Empty; _userRepository.Add(saveItem); var success = _userRepository.SaveChanges(); return ResponseOutput.Result(success, new UserAddedReturnDTO { Id = saveItem.Id, Code = saveItem.Code }); } public IResponseOutput UpdateUser(UserCommand model, Guid userId) { var userType = _dictionaryRepository.FindSingleOrDefault(u => u.Id == model.UserTypeId); if (userType == null) { return ResponseOutput.NotOk("selected wrong user type."); } // 判断当前用户名是否已经存在 if (_userRepository.GetAll().Any(t => (t.UserName == model.UserName && t.Id != model.Id) || (t.EMail == model.EMail && t.Id != model.Id) )) { return ResponseOutput.NotOk("User name or enmail already exist."); } if (model.OrganizationName.ToUpper().Contains(StaticData.MainCompany)) { model.IsZhiZhun = true; } else { model.IsZhiZhun = false; } #region 方式一 直接更新需要的字段 字段多 很麻烦 容易掉 //var success = _userRepository.Update(t => t.Id == model.Id, u => new User() //{ // Status = model.Status, // UpdateTime = DateTime.Now, // UpdateUserId = userId, // RealName = model.RealName, // UserName = model.UserName, // Phone = model.Phone, // EMail = model.EMail, // Sex = model.Sex, // UserTypeId = model.UserTypeId, // UserType = model.UserType, // OrganizationId = model.OrganizationId, // OrganizationName = model.OrganizationName, // OrganizationType = model.OrganizationType, // OrganizationTypeId = model.OrganizationTypeId, // DepartmentName = model.DepartmentName, // PositionName = model.PositionName, // IsZhiZhun = model.IsZhiZhun //}); #endregion var user = _userRepository.GetAll().First(t => t.Id == model.Id); _mapper.Map(model, user); _userRepository.Update(user); var success = _userRepository.SaveChanges(); return ResponseOutput.Result(success); } public IResponseOutput UpdateUserState(Guid userId, int state) { var success = _userRepository.Update(u => u.Id == userId, t => new User { Status = state }); return ResponseOutput.Result(success); } public IResponseOutput ResetPassword(Guid userId) { var success = _userRepository.Update(t => t.Id == userId, u => new User() { Password = MD5Helper.Md5(StaticData.DefaultPassword) }); return ResponseOutput.Result(success); } public IResponseOutput ModifyPassword(EditPasswordCommand editPwModel) { if (_userRepository.GetAll().FirstOrDefault(t => t.Id == _userInfo.Id && t.Password == editPwModel.OldPassWord) != null) { var success = _userRepository.Update(t => t.Id == _userInfo.Id, u => new User() { Password = editPwModel.NewPassWord }); return ResponseOutput.Result(success); } if (_doctorRepository.GetAll().Any(t => t.Id == _userInfo.Id && t.Password == editPwModel.OldPassWord)) { var success = _doctorRepository.Update(t => t.Id == _userInfo.Id, u => new Doctor() { Password = editPwModel.NewPassWord }); return ResponseOutput.Result(success); } return ResponseOutput.NotOk("Old password is wrong."); } public List GetUserRolesById(Guid userId) { var query = from userRole in _userRoleRepository.Find(u => u.UserId == userId) join role in _roleRepository.GetAll() on userRole.RoleId equals role.Id into t from userRoleItem in t.DefaultIfEmpty() select userRoleItem.RoleName; return query.ToList(); } public int GetUserRoleMaxPrivilegeLevel(Guid userId) { var user = _userRepository.FindSingleOrDefault(u => u.Id == userId); if (user.SuperAdmin) { return 9999; } var query = from userRole in _userRoleRepository.Find(u => u.UserId == userId) join role in _roleRepository.GetAll() on userRole.RoleId equals role.Id into t from userRoleItem in t.DefaultIfEmpty() select userRoleItem.PrivilegeLevel; var list = query.ToList(); if (list.Count == 0) { return 0; } return list.Max(); } } }