Sic.Framework-Nanjing-Baishi/MECF.Framework.Common/MECF/Framework/Common/Account/Extends/RoleAccountLoader.cs

502 lines
14 KiB
C#
Raw Normal View History

2023-04-13 11:51:03 +08:00
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;
using MECF.Framework.Common.Account.Permissions;
2023-04-13 11:51:03 +08:00
namespace MECF.Framework.Common.Account.Extends
{
/// <summary>
/// 角色账号加载器从_AccountEx.xml文件加载角色。
/// </summary>
public class RoleAccountLoader : XmlLoader
2023-04-13 11:51:03 +08:00
{
#region Variables
private const string NODE_NAME_PERMS_GROUP = "Perms";
private const string NODE_NAME_PERMS_ITEM = "Perm";
private readonly MenuLoader _menuLoader;
private List<Role> _roleList;
private List<AccountEx> _accountList;
2023-04-13 11:51:03 +08:00
#endregion
#region Constructors
2023-09-05 09:27:56 +08:00
/// <summary>
/// 创建角色加载器对象实例。
/// </summary>
/// <param name="fileName">角色配置文件名称通常为_Account.xml</param>
public RoleAccountLoader(string fileName)
: base(fileName)
2023-04-13 11:51:03 +08:00
{
_menuLoader = new MenuLoader(PathManager.GetCfgDir() + "menu.xml");
_menuLoader.Load();
2023-04-13 11:51:03 +08:00
}
#endregion
#region Methods
2023-04-13 11:51:03 +08:00
/// <summary>
/// 获取配置文件中定义的所有菜单项。
/// </summary>
/// <returns></returns>
public List<AppMenu> GetAllMenus()
{
return _menuLoader.MenuList;
}
/// <summary>
/// 获取所有非超级用户角色列表。
/// </summary>
/// <returns></returns>
public List<Role> GetRoles(bool includeSuper = false)
{
if (includeSuper)
return _roleList;
return _roleList.Where(x => !x.IsSuper).ToList();
2023-04-13 11:51:03 +08:00
}
/// <summary>
/// 获取所有非超级用户账号列表。
/// </summary>
/// <returns></returns>
public List<AccountEx> GetAccounts(bool includeSuper = false)
2023-04-13 11:51:03 +08:00
{
if (includeSuper)
return _accountList;
return _accountList.Where(x => !x.IsSuper).ToList();
2023-04-13 11:51:03 +08:00
}
/// <summary>
/// 解析Account.xml文件。
/// </summary>
2023-04-13 11:51:03 +08:00
protected override void AnalyzeXml()
{
if (XmlDoc == null)
2023-04-13 11:51:03 +08:00
{
return;
}
var roleItems = from r in XmlDoc.Descendants("roleItem")
2023-04-13 11:51:03 +08:00
select (r);
var list = new List<Role>();
foreach (var roleNode in roleItems)
2023-04-13 11:51:03 +08:00
{
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 ?? "";
// 旧版的权限保存方式为字符串形式,新版更改为<Perm />节点列表。
// 为兼容旧格式此处应该判断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<string, MenuPermissionEnum>();
foreach (var grpPerms in roleNode.Elements(NODE_NAME_PERMS_GROUP))
{
foreach (var xe in grpPerms.Elements(NODE_NAME_PERMS_ITEM))
{
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);
}
2023-04-13 11:51:03 +08:00
}
var roleAdmin = new Role("-1", "Administrators", true, 20, null, true, null)
2023-04-13 11:51:03 +08:00
{
IsSuper = true
};
list.Add(roleAdmin);
_roleList = list;
var users = from r in XmlDoc.Descendants("userItem")
2023-04-13 11:51:03 +08:00
select (r);
var lstUsers = new List<AccountEx>();
foreach (var userNode in users)
2023-04-13 11:51:03 +08:00
{
var lstRolesBelongTo = new List<string>();
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)
2023-04-13 11:51:03 +08:00
{
strDescription = userNode.Attribute("description").Value;
2023-04-13 11:51:03 +08:00
}
var userRoles = from ro in userNode.Descendants("role")
2023-04-13 11:51:03 +08:00
select (ro);
foreach (var userRoleNode in userRoles)
2023-04-13 11:51:03 +08:00
{
var strRoleId = userRoleNode.Attribute("id").Value;
lstRolesBelongTo.Add(strRoleId);
2023-04-13 11:51:03 +08:00
}
var item3 = new AccountEx(strUserId, strLoginName, strPassword, strFirstName, strLastName, strEmail, lstRolesBelongTo, strDescription);
lstUsers.Add(item3);
2023-04-13 11:51:03 +08:00
}
var admin = new AccountEx("-1", "sic_admin", "sic_admin", "", "", "", new List<string> { "-1" })
2023-04-13 11:51:03 +08:00
{
IsSuper = true
};
lstUsers.Add(admin);
var readOnly = new AccountEx("-2", "Read-Only", "read-only", "", "", "", new List<string> { "-1" })
{
IsSuper = true
};
lstUsers.Add(readOnly);
_accountList = lstUsers;
2023-04-13 11:51:03 +08:00
}
/// <summary>
/// 获取一个可用的角色ID。
/// </summary>
/// <returns></returns>
public string GetAvailableRoleID()
{
// 4以下的ID为系统保留ID。
var id = 4;
while (true)
{
var ro = _roleList.FirstOrDefault(x => x.RoleId == id.ToString());
if (ro == null)
break;
if (id >= 10000)
throw new IndexOutOfRangeException("no available role ID.");
id++;
}
return id.ToString();
}
/// <summary>
/// 更新指定的角色。
/// </summary>
/// <param name="newRole"></param>
/// <returns></returns>
public bool UpdateRole(Role newRole)
2023-04-13 11:51:03 +08:00
{
var oldRole = _roleList.Find((Role item) => item.RoleId == newRole.RoleId);
if (oldRole == null)
_roleList.Add(newRole);
2023-04-13 11:51:03 +08:00
else
_roleList[_roleList.IndexOf(oldRole)] = newRole;
var doc = XmlDoc;
var roleToUpdate = doc.Descendants("roleItem").FirstOrDefault(x => x.Attribute("id").Value == newRole.RoleId);
if (roleToUpdate != null)
2023-04-13 11:51:03 +08:00
{
// 修改现有的Role
roleToUpdate.RemoveNodes();
2023-04-13 11:51:03 +08:00
}
else
{
// 新增Role
roleToUpdate = new XElement("roleItem");
doc.Root.Element("roles").Add(roleToUpdate);
2023-04-13 11:51:03 +08:00
}
// 设置属性
roleToUpdate.SetAttributeValue("id", newRole.RoleId);
roleToUpdate.SetAttributeValue("name", newRole.RoleName);
roleToUpdate.SetAttributeValue("autologout", (newRole.IsAutoLogout ? "1" : "0"));
roleToUpdate.SetAttributeValue("logouttime", newRole.LogoutTime.ToString());
roleToUpdate.SetAttributeValue("buildin", newRole.IsBuildIn.ToString());
roleToUpdate.SetAttributeValue("description", newRole.Description);
// 创建权限清单
var permList = new XElement(NODE_NAME_PERMS_GROUP);
foreach (var perm in newRole.PermissionControlItems)
permList.Add(new XElement(NODE_NAME_PERMS_ITEM,
new XAttribute("name", perm.Key),
new XAttribute("value", (int)perm.Value)));
roleToUpdate.Add(permList);
doc.Save(FileName);
2023-04-13 11:51:03 +08:00
return true;
}
/// <summary>
/// 删除指定ID的角色。
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public bool DeleteRole(string roleId)
2023-04-13 11:51:03 +08:00
{
Load();
var roleToDelete = _roleList.Find((Role item) => item.RoleId == roleId);
if (roleToDelete != null)
2023-04-13 11:51:03 +08:00
{
_roleList.Remove(roleToDelete);
var xmlDoc = XmlDoc;
var list = (from m_xRole in xmlDoc.Descendants("roleItem")
where m_xRole.Attribute("id").Value == roleId
2023-04-13 11:51:03 +08:00
select m_xRole).ToList();
if (list.Count > 0)
{
list[0].Remove();
foreach (var item in _accountList)
2023-04-13 11:51:03 +08:00
{
if (item.RoleIDs.Contains(roleToDelete.RoleId))
2023-04-13 11:51:03 +08:00
{
item.RoleIDs.Remove(roleToDelete.RoleId);
2023-04-13 11:51:03 +08:00
}
}
list = (from m_xRole in xmlDoc.Descendants("role")
where m_xRole.Attribute("id").Value == roleToDelete.RoleId
2023-04-13 11:51:03 +08:00
select m_xRole).ToList();
if (list.Count > 0)
{
list.Remove();
}
xmlDoc.Save(FileName);
2023-04-13 11:51:03 +08:00
return true;
}
return false;
}
return false;
}
private Dictionary<string, MenuPermissionEnum> GetRolePermission(string roleId)
2023-04-13 11:51:03 +08:00
{
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;
2023-04-13 11:51:03 +08:00
}
/// <summary>
///
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public List<AppMenu> GetAccessibleMenusByRole(string roleId)
2023-04-13 11:51:03 +08:00
{
var list = new List<AppMenu>();
var rolePermission = GetRolePermission(roleId);
if (rolePermission == null)
return null;
foreach (var menu in GetAllMenus())
2023-04-13 11:51:03 +08:00
{
var appMenusHasPerm = new List<AppMenu>();
foreach (var menuItem in menu.MenuItems)
2023-04-13 11:51:03 +08:00
{
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 = perm
};
if (appMenu.Permission > MenuPermissionEnum.MP_NONE)
2023-04-13 11:51:03 +08:00
{
appMenusHasPerm.Add(appMenu);
2023-04-13 11:51:03 +08:00
}
}
if (appMenusHasPerm.Count > 0)
2023-04-13 11:51:03 +08:00
{
var appMenu2 = new AppMenu(menu.MenuID, menu.ViewModel, menu.ResKey, appMenusHasPerm, menu.Description);
appMenu2.System = menu.System;
appMenu2.AlarmModule = menu.AlarmModule;
2023-04-13 11:51:03 +08:00
list.Add(appMenu2);
}
}
2023-04-13 11:51:03 +08:00
return list;
}
/// <summary>
/// 获取指定角色指定菜单的访问权限。
/// </summary>
/// <param name="roleId"></param>
/// <param name="menuName"></param>
/// <returns></returns>
public MenuPermissionEnum GetMenuPermission(string roleId, string menuName)
2023-04-13 11:51:03 +08:00
{
var rolePermission = GetRolePermission(roleId);
if (rolePermission.TryGetValue(menuName, out var perm))
return perm;
return MenuPermissionEnum.MP_NONE;
2023-04-13 11:51:03 +08:00
}
/// <summary>
/// 保存账号。如果当前账号ID已存在则更新账号否则新建账号并保存。
/// </summary>
/// <param name="newAccount"></param>
/// <returns></returns>
public bool UpdateAccount(AccountEx newAccount)
2023-04-13 11:51:03 +08:00
{
var accountEx = _accountList.Find((AccountEx item) => item.UserId == newAccount.UserId);
2023-04-13 11:51:03 +08:00
if (accountEx == null)
{
_accountList.Add(newAccount);
2023-04-13 11:51:03 +08:00
}
else
{
_accountList[_accountList.IndexOf(accountEx)] = newAccount;
2023-04-13 11:51:03 +08:00
}
var xmlDoc = XmlDoc;
var list = (from xAccount in xmlDoc.Descendants("userItem")
where xAccount.Attribute("id")?.Value == newAccount.UserId
2023-04-13 11:51:03 +08:00
select xAccount).ToList();
2023-04-13 11:51:03 +08:00
if (list.Count > 0)
{
list[0].SetAttributeValue("loginname", newAccount.LoginName);
list[0].SetAttributeValue("password", Encrypt(newAccount.Password));
list[0].SetAttributeValue("firstname", newAccount.FirstName);
list[0].SetAttributeValue("lastname", newAccount.LastName);
list[0].SetAttributeValue("email", newAccount.Email);
list[0].SetAttributeValue("description", newAccount.Description);
2023-04-13 11:51:03 +08:00
list[0].Element("rolegroup").RemoveAll();
foreach (var roleID in newAccount.RoleIDs)
2023-04-13 11:51:03 +08:00
{
list[0].Element("rolegroup").Add(new XElement("role", new XAttribute("id", roleID)));
}
}
else
{
var xElement = new XElement("userItem", new XAttribute("id", newAccount.UserId), new XAttribute("loginname", newAccount.LoginName), new XAttribute("password", Encrypt(newAccount.Password)), new XAttribute("firstname", newAccount.FirstName), new XAttribute("lastname", newAccount.LastName), new XAttribute("email", newAccount.Email), new XAttribute("description", newAccount.Description), new XElement("rolegroup"));
foreach (var roleID2 in newAccount.RoleIDs)
2023-04-13 11:51:03 +08:00
{
xElement.Element("rolegroup").Add(new XElement("role", new XAttribute("id", roleID2)));
}
xmlDoc.Root.Element("users").Add(xElement);
2023-04-13 11:51:03 +08:00
}
xmlDoc.Save(FileName);
2023-04-13 11:51:03 +08:00
return true;
}
/// <summary>
/// 删除账号。
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool DeleteAccount(string id)
2023-04-13 11:51:03 +08:00
{
var accountEx = _accountList.Find((AccountEx item) => item.UserId == id);
2023-04-13 11:51:03 +08:00
if (accountEx != null)
{
_accountList.Remove(accountEx);
var xdoc = XmlDoc;
var list = (from xAccount in xdoc.Descendants("userItem")
where xAccount.Attribute("id")?.Value == id
2023-04-13 11:51:03 +08:00
select xAccount).ToList();
if (list.Count > 0)
{
list[0].Remove();
xdoc.Save(FileName);
2023-04-13 11:51:03 +08:00
return true;
}
return false;
}
return false;
}
/// <summary>
/// 加密字符串。
/// </summary>
/// <param name="encrytStr"></param>
/// <returns></returns>
2023-04-13 11:51:03 +08:00
public string Encrypt(string encrytStr)
{
if (string.IsNullOrWhiteSpace(encrytStr))
{
return string.Empty;
}
try
{
var bytes = Encoding.UTF8.GetBytes(encrytStr);
2023-04-13 11:51:03 +08:00
return Convert.ToBase64String(bytes);
}
catch
{
return encrytStr;
}
}
/// <summary>
/// 解密字符串。
/// </summary>
/// <param name="decryptStr"></param>
/// <returns></returns>
2023-04-13 11:51:03 +08:00
public string Decrypt(string decryptStr)
{
if (string.IsNullOrWhiteSpace(decryptStr))
{
return string.Empty;
}
try
{
var bytes = Convert.FromBase64String(decryptStr);
2023-04-13 11:51:03 +08:00
return Encoding.UTF8.GetString(bytes);
}
catch
{
return decryptStr;
}
}
#endregion
2023-04-13 11:51:03 +08:00
}
}