// 修改用户 public int ChangeUser( string strLibraryCodeList, string strUserName, string strOperator, UserInfo userinfo, string strClientAddress, out string strError) { strError = ""; int nRet = 0; if (String.IsNullOrEmpty(strUserName) == true) { strError = "strUserName参数值不能为空"; return -1; } if (strUserName != userinfo.UserName) { strError = "strUserName参数值和userinfo.UserName不一致"; return -1; } XmlNode nodeAccount = null; string strOldOuterXml = ""; this.m_lock.AcquireWriterLock(m_nLockTimeout); try { // 查重 nodeAccount = this.LibraryCfgDom.DocumentElement.SelectSingleNode("//accounts/account[@name='" + strUserName + "']"); if (nodeAccount == null) { strError = "用户 '" + strUserName + "' 不存在"; return -1; } strOldOuterXml = nodeAccount.OuterXml; string strExistLibraryCodeList = DomUtil.GetAttr(nodeAccount, "libraryCode"); // 2012/9/9 // 分馆用户只允许修改馆代码属于管辖分馆的帐户 if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false) { if (string.IsNullOrEmpty(strExistLibraryCodeList) == true || IsListInList(strExistLibraryCodeList, strLibraryCodeList) == false) { strError = "当前用户只能修改图书馆代码完全属于 '" + strLibraryCodeList + "' 范围的用户信息"; return -1; } } // 2012/9/9 // 分馆用户只允许将帐户的馆代码修改到指定范围内 if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false) { if (string.IsNullOrEmpty(userinfo.LibraryCode) == true || IsListInList(userinfo.LibraryCode, strLibraryCodeList) == false) { strError = "当前用户只能将用户信息的馆代码修改到完全属于 '" + strLibraryCodeList + "' 范围内的值"; return -1; } } DomUtil.SetAttr(nodeAccount, "name", userinfo.UserName); DomUtil.SetAttr(nodeAccount, "type", userinfo.Type); DomUtil.SetAttr(nodeAccount, "rights", userinfo.Rights); DomUtil.SetAttr(nodeAccount, "libraryCode", userinfo.LibraryCode); DomUtil.SetAttr(nodeAccount, "access", userinfo.Access); DomUtil.SetAttr(nodeAccount, "comment", userinfo.Comment); // 强制修改密码。无需验证旧密码 if (userinfo.SetPassword == true) { #if NO // 以前的做法 string strPassword = Cryptography.Encrypt(userinfo.Password, EncryptKey); DomUtil.SetAttr(nodeAccount, "password", strPassword); #endif string strHashed = ""; nRet = LibraryServerUtil.SetUserPassword(userinfo.Password, out strHashed, out strError); if (nRet == -1) return -1; DomUtil.SetAttr(nodeAccount, "password", strHashed); } this.Changed = true; // 2014/9/16 if (userinfo.UserName == "reader") this.ClearLoginCache(""); } finally { this.m_lock.ReleaseWriterLock(); } // 写入日志 { XmlDocument domOperLog = PrepareOperlogDom("change", strOperator); if (string.IsNullOrEmpty(strOldOuterXml) == false) { XmlNode node_old = domOperLog.CreateElement("oldAccount"); domOperLog.DocumentElement.AppendChild(node_old); node_old = DomUtil.SetElementOuterXml(node_old, strOldOuterXml); DomUtil.RenameNode(node_old, null, "oldAccount"); } XmlNode node = domOperLog.CreateElement("account"); domOperLog.DocumentElement.AppendChild(node); DomUtil.SetElementOuterXml(node, nodeAccount.OuterXml); // 写入日志 nRet = this.OperLog.WriteOperLog(domOperLog, strClientAddress, out strError); if (nRet == -1) { strError = "SetUser() API 写入日志时发生错误: " + strError; return -1; } } return 0; }
// 包装 public int SetUser( string strLibraryCodeList, string strAction, string strOperator, UserInfo info, string strClientAddress, out string strError) { if (strAction == "new") { return this.CreateUser(strLibraryCodeList, info.UserName, strOperator, info, strClientAddress, out strError); } if (strAction == "change") { return this.ChangeUser(strLibraryCodeList, info.UserName, strOperator, info, strClientAddress, out strError); } if (strAction == "resetpassword") { return this.ResetUserPassword(strLibraryCodeList, info.UserName, strOperator, info.Password, strClientAddress, out strError); } if (strAction == "delete") { return this.DeleteUser(strLibraryCodeList, info.UserName, strOperator, strClientAddress, out strError); } strError = "未知的动作 '" + strAction + "'"; return -1; }
// 创建新用户 // TODO: 对DOM加锁 public int CreateUser( string strLibraryCodeList, string strUserName, string strOperator, UserInfo userinfo, string strClientAddress, out string strError) { strError = ""; if (String.IsNullOrEmpty(strUserName) == true) { strError = "strUserName参数值不能为空"; return -1; } if (strUserName != userinfo.UserName) { strError = "strUserName参数值和userinfo.UserName不一致"; return -1; } // 2012/9/9 // 分馆用户只允许创建馆代码属于管辖分馆的帐户 if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false) { if (string.IsNullOrEmpty(userinfo.LibraryCode) == true || IsListInList(userinfo.LibraryCode, strLibraryCodeList) == false) { strError = "当前用户只能创建图书馆代码完全属于 '" + strLibraryCodeList + "' 范围的新用户"; return -1; } } int nResultValue = -1; // 检查名字空间。 // return: // -2 not found script // -1 出错 // 0 成功 int nRet = this.DoVerifyBarcodeScriptFunction( null, "", strUserName, out nResultValue, out strError); if (nRet == -2) { // 没有校验条码号功能,所以无法校验用户名和条码号名字空间的冲突 goto SKIP_VERIFY; } if (nRet == -1) { strError = "校验用户名 '" + strUserName + "' 和条码号潜在冲突过程中(调用函数DoVerifyBarcodeScriptFunction()时)发生错误: " + strError; return -1; } Debug.Assert(nRet == 0, ""); if (nResultValue == -1) { strError = "校验用户名 '" + strUserName + "' 和条码号潜在冲突过程中发生错误: " + strError; return -1; } if (nResultValue == 1) { strError = "名字 '" + strUserName + "' 和条码号名字空间发生冲突,不能作为用户名。"; return -1; } SKIP_VERIFY: XmlNode nodeAccount = null; this.m_lock.AcquireWriterLock(m_nLockTimeout); try { // 查重 nodeAccount = this.LibraryCfgDom.DocumentElement.SelectSingleNode("//accounts/account[@name='" + strUserName + "']"); if (nodeAccount != null) { strError = "用户 '" + strUserName + "' 已经存在"; return -1; } XmlNode root = this.LibraryCfgDom.DocumentElement.SelectSingleNode("accounts"); if (root == null) { root = this.LibraryCfgDom.CreateElement("accounts"); this.LibraryCfgDom.DocumentElement.AppendChild(root); } nodeAccount = this.LibraryCfgDom.CreateElement("account"); root.AppendChild(nodeAccount); DomUtil.SetAttr(nodeAccount, "name", userinfo.UserName); if (String.IsNullOrEmpty(userinfo.Type) == false) DomUtil.SetAttr(nodeAccount, "type", userinfo.Type); DomUtil.SetAttr(nodeAccount, "rights", userinfo.Rights); DomUtil.SetAttr(nodeAccount, "libraryCode", userinfo.LibraryCode); DomUtil.SetAttr(nodeAccount, "access", userinfo.Access); DomUtil.SetAttr(nodeAccount, "comment", userinfo.Comment); // 设置密码 if (userinfo.SetPassword == true) { #if NO // 以前的做法 string strPassword = Cryptography.Encrypt(userinfo.Password, EncryptKey); DomUtil.SetAttr(nodeAccount, "password", strPassword); #endif string strHashed = ""; nRet = LibraryServerUtil.SetUserPassword(userinfo.Password, out strHashed, out strError); if (nRet == -1) return -1; DomUtil.SetAttr(nodeAccount, "password", strHashed); } this.Changed = true; // 2014/9/16 if (userinfo.UserName == "reader") this.ClearLoginCache(""); } finally { this.m_lock.ReleaseWriterLock(); } // 写入日志 { XmlDocument domOperLog = PrepareOperlogDom("new", strOperator); XmlNode node = domOperLog.CreateElement("account"); domOperLog.DocumentElement.AppendChild(node); DomUtil.SetElementOuterXml(node, nodeAccount.OuterXml); // 写入日志 nRet = this.OperLog.WriteOperLog(domOperLog, strClientAddress, out strError); if (nRet == -1) { strError = "SetUser() API 写入日志时发生错误: " + strError; return -1; } } return 0; }
// 列出指定的用户 // parameters: // strUserName 用户名。如果为空,表示列出全部用户名 // return: // -1 出错 // 其他 用户总数(不是本批的个数) public int ListUsers( string strLibraryCodeList, string strUserName, int nStart, int nCount, out UserInfo[] userinfos, out string strError) { this.m_lock.AcquireReaderLock(m_nLockTimeout); try { strError = ""; userinfos = null; string strXPath = ""; if (String.IsNullOrEmpty(strUserName) == true) { strXPath = "//accounts/account"; } else { strXPath = "//accounts/account[@name='" + strUserName + "']"; } List<UserInfo> userList = new List<UserInfo>(); XmlNodeList nodes = this.LibraryCfgDom.DocumentElement.SelectNodes(strXPath); // 过滤为当前能管辖的小范围node数组 List<XmlNode> smallerlist = new List<XmlNode>(); for (int i = 0; i < nodes.Count; i++) { XmlNode node = nodes[i]; // 2012/9/9 // 分馆用户只允许列出管辖分馆的所有用户 if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false) { string strCurrentLibraryCodeList = DomUtil.GetAttr(node, "libraryCode"); // TODO: 帐户定义中的馆代码列表中不允许 ,, 这样的情况 if (IsListInList(strCurrentLibraryCodeList, strLibraryCodeList) == false) continue; } smallerlist.Add(node); } if (nCount == -1) nCount = Math.Max(0, smallerlist.Count - nStart); nCount = Math.Min(100, nCount); // 限制每批最多100个 for (int i = nStart; i < Math.Min(nStart + nCount, smallerlist.Count); i++) // { XmlNode node = smallerlist[i]; string strCurrentLibraryCodeList = DomUtil.GetAttr(node, "libraryCode"); UserInfo userinfo = new UserInfo(); userinfo.UserName = DomUtil.GetAttr(node, "name"); userinfo.Type = DomUtil.GetAttr(node, "type"); userinfo.Rights = DomUtil.GetAttr(node, "rights"); userinfo.LibraryCode = strCurrentLibraryCodeList; userinfo.Access = DomUtil.GetAttr(node, "access"); userinfo.Comment = DomUtil.GetAttr(node, "comment"); userList.Add(userinfo); } userinfos = new UserInfo[userList.Count]; userList.CopyTo(userinfos); return smallerlist.Count; } finally { this.m_lock.ReleaseReaderLock(); } }
// 获得一个账户的信息。不受当前用户的管辖范围的限制。所以这个函数只能提供内部使用,要谨慎 // return: // -1 出错 // 0 没有找到 // 1 找到 public int GetUserInfo(string strUserName, out UserInfo userinfo, out string strError) { strError = ""; userinfo = null; if (string.IsNullOrEmpty(strUserName) == true) { strError = "用户名不能为空"; return -1; } UserInfo[] userinfos = null; // return: // -1 出错 // 其他 用户总数(不是本批的个数) int nRet = ListUsers( "", strUserName, 0, 1, out userinfos, out strError); if (nRet == -1) return -1; if (nRet == 0) return 0; // not found if (userinfos == null || userinfos.Length < 1) { strError = "userinfos error"; return -1; } userinfo = userinfos[0]; return 1; }
public static void SetUserXml(UserInfo userinfo, XmlElement nodeAccount) { DomUtil.SetAttr(nodeAccount, "name", userinfo.UserName); if (String.IsNullOrEmpty(userinfo.Type) == false) DomUtil.SetAttr(nodeAccount, "type", userinfo.Type); DomUtil.SetAttr(nodeAccount, "rights", userinfo.Rights); DomUtil.SetAttr(nodeAccount, "libraryCode", userinfo.LibraryCode); DomUtil.SetAttr(nodeAccount, "access", userinfo.Access); DomUtil.SetAttr(nodeAccount, "comment", userinfo.Comment); DomUtil.SetAttr(nodeAccount, "binding", userinfo.Binding); }
static bool AutoBindingIP(UserInfo info, string strClientAddress) { string strBinding = info.Binding; if (string.IsNullOrEmpty(strBinding)) return false; bool bChanged = false; List<string> temp = StringUtil.ParseTwoPart(strClientAddress, "@"); string ip = temp[0]; if (ip == "::1" || ip == "127.0.0.1") ip = "localhost"; List<string> results = new List<string>(); string[] parts = strBinding.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string s in parts) { string strLine = s.Trim(); if (string.IsNullOrEmpty(strLine)) continue; string strLeft = ""; string strRight = ""; StringUtil.ParseTwoPart(strLine, ":", out strLeft, out strRight); if (strLeft == "ip") { if (strRight == "[current]") { // 替换为当前前端的 ip 地址 results.Add("ip:" + ip); bChanged = true; continue; } } results.Add(strLine); } info.Binding = StringUtil.MakePathList(results, ","); return bChanged; }