Sic.Framework/MECF.Framework.Common/MECF/Framework/Common/Account/Extends/RoleAccountLoader.cs

502 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
namespace MECF.Framework.Common.Account.Extends
{
/// <summary>
/// 角色账号加载器从_AccountEx.xml文件加载角色。
/// </summary>
public class RoleAccountLoader : XmlLoader
{
#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;
#endregion
#region Constructors
/// <summary>
/// 创建角色加载器对象实例。
/// </summary>
/// <param name="fileName">角色配置文件名称通常为_Account.xml</param>
public RoleAccountLoader(string fileName)
: base(fileName)
{
_menuLoader = new MenuLoader(PathManager.GetCfgDir() + "menu.xml");
_menuLoader.Load();
}
#endregion
#region Methods
/// <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();
}
/// <summary>
/// 获取所有非超级用户账号列表。
/// </summary>
/// <returns></returns>
public List<AccountEx> GetAccounts(bool includeSuper = false)
{
if (includeSuper)
return _accountList;
return _accountList.Where(x => !x.IsSuper).ToList();
}
/// <summary>
/// 解析Account.xml文件。
/// </summary>
protected override void AnalyzeXml()
{
if (XmlDoc == null)
{
return;
}
var roleItems = from r in XmlDoc.Descendants("roleItem")
select (r);
var list = new List<Role>();
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 ?? "";
// 旧版的权限保存方式为字符串形式,新版更改为<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);
}
}
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<AccountEx>();
foreach (var userNode in users)
{
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)
{
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 admin = new AccountEx("-1", "sic_admin", "sic_admin", "", "", "", new List<string> { "-1" })
{
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;
}
/// <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)
{
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 roleToUpdate = doc.Descendants("roleItem").FirstOrDefault(x => x.Attribute("id").Value == newRole.RoleId);
if (roleToUpdate != null)
{
// 修改现有的Role
roleToUpdate.RemoveNodes();
}
else
{
// 新增Role
roleToUpdate = new XElement("roleItem");
doc.Root.Element("roles").Add(roleToUpdate);
}
// 设置属性
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);
return true;
}
/// <summary>
/// 删除指定ID的角色。
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
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<string, MenuPermissionEnum> 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;
}
/// <summary>
///
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public List<AppMenu> GetAccessibleMenusByRole(string roleId)
{
var list = new List<AppMenu>();
var rolePermission = GetRolePermission(roleId);
if (rolePermission == null)
return null;
foreach (var menu in GetAllMenus())
{
var appMenusHasPerm = new List<AppMenu>();
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 = perm
};
if (appMenu.Permission > 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;
}
/// <summary>
/// 获取指定角色指定菜单的访问权限。
/// </summary>
/// <param name="roleId"></param>
/// <param name="menuName"></param>
/// <returns></returns>
public MenuPermissionEnum GetMenuPermission(string roleId, string menuName)
{
var rolePermission = GetRolePermission(roleId);
if (rolePermission.TryGetValue(menuName, out var perm))
return perm;
return MenuPermissionEnum.MP_NONE;
}
/// <summary>
/// 保存账号。如果当前账号ID已存在则更新账号否则新建账号并保存。
/// </summary>
/// <param name="newAccount"></param>
/// <returns></returns>
public bool UpdateAccount(AccountEx newAccount)
{
var accountEx = _accountList.Find((AccountEx item) => item.UserId == newAccount.UserId);
if (accountEx == null)
{
_accountList.Add(newAccount);
}
else
{
_accountList[_accountList.IndexOf(accountEx)] = newAccount;
}
var xmlDoc = XmlDoc;
var list = (from xAccount in xmlDoc.Descendants("userItem")
where xAccount.Attribute("id")?.Value == newAccount.UserId
select xAccount).ToList();
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);
list[0].Element("rolegroup").RemoveAll();
foreach (var roleID in newAccount.RoleIDs)
{
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)
{
xElement.Element("rolegroup").Add(new XElement("role", new XAttribute("id", roleID2)));
}
xmlDoc.Root.Element("users").Add(xElement);
}
xmlDoc.Save(FileName);
return true;
}
/// <summary>
/// 删除账号。
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool DeleteAccount(string id)
{
var accountEx = _accountList.Find((AccountEx item) => item.UserId == id);
if (accountEx != null)
{
_accountList.Remove(accountEx);
var xdoc = XmlDoc;
var list = (from xAccount in xdoc.Descendants("userItem")
where xAccount.Attribute("id")?.Value == id
select xAccount).ToList();
if (list.Count > 0)
{
list[0].Remove();
xdoc.Save(FileName);
return true;
}
return false;
}
return false;
}
/// <summary>
/// 加密字符串。
/// </summary>
/// <param name="encrytStr"></param>
/// <returns></returns>
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;
}
}
/// <summary>
/// 解密字符串。
/// </summary>
/// <param name="decryptStr"></param>
/// <returns></returns>
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
}
}