using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.Linq; using Aitex.Common.Util; using Aitex.Core.RT.Log; namespace MECF.Framework.Common.Account.Extends { /// /// 角色加载器,从_Account.xml文件加载角色。 /// public class RoleLoader : XmlLoader { #region Variables private List _roleList; private List _accountList; #endregion #region Constructors /// /// 创建角色加载器对象实例。 /// /// 角色配置文件名称,通常为_Account.xml public RoleLoader(string fileName) : base(fileName) { } #endregion #region Properties /// /// 返回角色列表。 /// public List RoleList { get => _roleList; set => _roleList = value; } /// /// 返回账号列表。 /// public List AccountList { get => _accountList; set => _accountList = value; } #endregion #region Methods /// /// 获取所有非超级用户角色列表。 /// /// public List GetRoles() { return _roleList.Where((Role e) => !e.IsSuper).ToList(); } /// /// 获取所有非超级用户账号列表。 /// /// public List GetAccounts() { return _accountList.Where((AccountEx e) => !e.IsSuper).ToList(); } /// /// 解析Account.xml文件。 /// protected override void AnalyzeXml() { if (XmlDoc == null) { return; } var roleItems = from r in XmlDoc.Descendants("roleItem") select (r); var list = new List(); foreach (var roleNode in roleItems) { var strRoleId = roleNode.Attribute("id").Value; var strRoleName = roleNode.Attribute("name").Value; var strIsAutoLogout = roleNode.Attribute("autologout").Value; var strAutoLogoutTime = roleNode.Attribute("logouttime").Value; int.TryParse(strAutoLogoutTime, out var logoutTime); var isAutoLogout = ((strIsAutoLogout == "1")); var strBuildIn = roleNode.Attribute("buildin")?.Value ?? "false"; if (!bool.TryParse(strBuildIn, out var isBuildIn)) isBuildIn = false; // ID为0 ~ 3的角色强制为系统内置角色,禁止删除 if (strRoleId is "0" or "1" or "2" or "3") isBuildIn = true; var strDescription = roleNode.Attribute("description")?.Value ?? ""; // 旧版的权限保存方式为字符串形式,新版更改为节点列表。 // 为兼容旧格式,此处应该判断roleNode节点中的内容,将旧版自动转换为PermissionControlItem列表 if (roleNode.FirstNode is XText) { var permContent = roleNode.Value; var helper = new PermissionHelper(); helper.ParsePermission(permContent); var role = new Role(strRoleId, strRoleName, isAutoLogout, logoutTime, helper.MenuPermissionDictionary, isBuildIn, strDescription); list.Add(role); } else { var permList = new Dictionary(); foreach (var xe in roleNode.Elements("Perm")) { var permName = xe.Attribute("name")?.Value; var strPermValue = xe.Attribute("value")?.Value ?? "1"; if (!int.TryParse(strPermValue, out var permValue)) permValue = (int)MenuPermissionEnum.MP_NONE; if (!string.IsNullOrEmpty(permName)) permList[permName] = (MenuPermissionEnum)permValue; } var role = new Role(strRoleId, strRoleName, isAutoLogout, logoutTime, permList, isBuildIn, strDescription); list.Add(role); } } var roleAdmin = new Role("-1", "Administrators", true, 20, null, true, null) { IsSuper = true }; list.Add(roleAdmin); _roleList = list; var users = from r in XmlDoc.Descendants("userItem") select (r); var lstUsers = new List(); foreach (var userNode in users) { var lstRolesBelongTo = new List(); var strUserId = userNode.Attribute("id").Value; var strLoginName = userNode.Attribute("loginname").Value; var strPassword = Decrypt(userNode.Attribute("password").Value); var strFirstName = userNode.Attribute("firstname").Value; var strLastName = userNode.Attribute("lastname").Value; var strEmail = userNode.Attribute("email").Value; var strDescription = ""; if (userNode.Attribute("description") != null) { strDescription = userNode.Attribute("description").Value; } var userRoles = from ro in userNode.Descendants("role") select (ro); foreach (var userRoleNode in userRoles) { var strRoleId = userRoleNode.Attribute("id").Value; lstRolesBelongTo.Add(strRoleId); } var item3 = new AccountEx(strUserId, strLoginName, strPassword, strFirstName, strLastName, strEmail, lstRolesBelongTo, strDescription); lstUsers.Add(item3); } var item4 = new AccountEx("-1", "admin", "admin", "", "", "", new List { "-1" }) { IsSuper = true }; lstUsers.Add(item4); _accountList = lstUsers; } /// /// 更新指定的角色。 /// /// /// public bool UpdateRole(Role newRole) { var oldRole = _roleList.Find((Role item) => item.RoleId == newRole.RoleId); if (oldRole == null) { _roleList.Add(newRole); } else { _roleList[_roleList.IndexOf(oldRole)] = newRole; } var doc = XmlDoc; var list = (from m_xRole in doc.Descendants("roleItem") where m_xRole.Attribute("id").Value == newRole.RoleId select m_xRole).ToList(); XElement content = null; if (list.Count > 0) { // 修改现有的Role content = list[0]; content.RemoveNodes(); } else { // 新增Role content = new XElement("roleItem"); doc.Root.Element("roles").Add(content); } // 设置属性 content.SetAttributeValue("name", newRole.RoleName); content.SetAttributeValue("autologout", (newRole.IsAutoLogout ? "1" : "0")); content.SetAttributeValue("logouttime", newRole.LogoutTime.ToString()); content.SetAttributeValue("buildin", newRole.IsBuildIn.ToString()); content.SetAttributeValue("description", newRole.Description); // 创建权限清单 var permList = new XElement("Perms"); foreach (var perm in newRole.PermissionControlItems) permList.Add(new XElement(perm.Key, (int)perm.Value)); content.Add(permList); doc.Save(FileName); return true; } public bool DeleteRole(string roleId) { Load(); var roleToDelete = _roleList.Find((Role item) => item.RoleId == roleId); if (roleToDelete != null) { _roleList.Remove(roleToDelete); var xmlDoc = XmlDoc; var list = (from m_xRole in xmlDoc.Descendants("roleItem") where m_xRole.Attribute("id").Value == roleId select m_xRole).ToList(); if (list.Count > 0) { list[0].Remove(); foreach (var item in _accountList) { if (item.RoleIDs.Contains(roleToDelete.RoleId)) { item.RoleIDs.Remove(roleToDelete.RoleId); } } list = (from m_xRole in xmlDoc.Descendants("role") where m_xRole.Attribute("id").Value == roleToDelete.RoleId select m_xRole).ToList(); if (list.Count > 0) { list.Remove(); } xmlDoc.Save(FileName); return true; } return false; } return false; } private Dictionary GetRolePermission(string roleId) { var perms = _roleList.FirstOrDefault(x => x.RoleId == roleId)?.PermissionControlItems; if(perms == null) LOG.Error($"Unable to find the Role by ID {roleId}, or the permission list is empty."); return perms; } public List GetAllMenus() { return AccountExManager.Instance.MenuLoader.MenuList; } public List GetMenusByRole(string roleId) { var list = new List(); var rolePermission = GetRolePermission(roleId); if (rolePermission == null) return null; foreach (var menu in AccountExManager.Instance.MenuLoader.MenuList) { var appMenusHasPerm = new List(); foreach (var menuItem in menu.MenuItems) { if (!rolePermission.TryGetValue(menuItem.MenuID, out var perm)) { // 当前菜单的权限未定义 LOG.Error($"The permission of {menuItem.MenuID} is not defined."); continue; } var appMenu = new AppMenu(menuItem.MenuID, menuItem.ViewModel, menuItem.ResKey, null, menuItem.Description) { System = menuItem.System, AlarmModule = menuItem.AlarmModule, Permission = (int)perm }; if (appMenu.Permission > (int)MenuPermissionEnum.MP_NONE) { appMenusHasPerm.Add(appMenu); } } if (appMenusHasPerm.Count > 0) { var appMenu2 = new AppMenu(menu.MenuID, menu.ViewModel, menu.ResKey, appMenusHasPerm, menu.Description); appMenu2.System = menu.System; appMenu2.AlarmModule = menu.AlarmModule; list.Add(appMenu2); } } return list; } public int GetMenuPermission(string roleId, string menuName) { var rolePermission = GetRolePermission(roleId); if (rolePermission.TryGetValue(menuName, out var perm)) return (int)perm; return (int)MenuPermissionEnum.MP_NONE; } public bool UpdateAccount(AccountEx p_newAccount) { var accountEx = _accountList.Find((AccountEx item) => item.UserId == p_newAccount.UserId); if (accountEx == null) { _accountList.Add(p_newAccount); } else { _accountList[_accountList.IndexOf(accountEx)] = p_newAccount; } var xdoc = XmlDoc; var list = (from xAccount in xdoc.Descendants("userItem") where xAccount.Attribute("id").Value == p_newAccount.UserId select xAccount).ToList(); if (list.Count > 0) { list[0].SetAttributeValue("loginname", p_newAccount.LoginName); list[0].SetAttributeValue("password", Encrypt(p_newAccount.Password)); list[0].SetAttributeValue("firstname", p_newAccount.FirstName); list[0].SetAttributeValue("lastname", p_newAccount.LastName); list[0].SetAttributeValue("email", p_newAccount.Email); list[0].SetAttributeValue("description", p_newAccount.Description); list[0].Element("rolegroup").RemoveAll(); foreach (var roleID in p_newAccount.RoleIDs) { list[0].Element("rolegroup").Add(new XElement("role", new XAttribute("id", roleID))); } } else { var xElement = new XElement("userItem", new XAttribute("id", p_newAccount.UserId), new XAttribute("loginname", p_newAccount.LoginName), new XAttribute("password", Encrypt(p_newAccount.Password)), new XAttribute("firstname", p_newAccount.FirstName), new XAttribute("lastname", p_newAccount.LastName), new XAttribute("email", p_newAccount.Email), new XAttribute("description", p_newAccount.Description), new XElement("rolegroup")); foreach (var roleID2 in p_newAccount.RoleIDs) { xElement.Element("rolegroup").Add(new XElement("role", new XAttribute("id", roleID2))); } xdoc.Root.Element("users").Add(xElement); } xdoc.Save(FileName); return true; } public bool DeleteAccount(string p_strUserID) { var accountEx = _accountList.Find((AccountEx item) => item.UserId == p_strUserID); if (accountEx != null) { _accountList.Remove(accountEx); var xdoc = XmlDoc; var list = (from xAccount in xdoc.Descendants("userItem") where xAccount.Attribute("id").Value == p_strUserID select xAccount).ToList(); if (list.Count > 0) { list[0].Remove(); xdoc.Save(FileName); return true; } return false; } return false; } public string Encrypt(string encrytStr) { if (string.IsNullOrWhiteSpace(encrytStr)) { return string.Empty; } try { var bytes = Encoding.UTF8.GetBytes(encrytStr); return Convert.ToBase64String(bytes); } catch { return encrytStr; } } public string Decrypt(string decryptStr) { if (string.IsNullOrWhiteSpace(decryptStr)) { return string.Empty; } try { var bytes = Convert.FromBase64String(decryptStr); return Encoding.UTF8.GetString(bytes); } catch { return decryptStr; } } #endregion } }