From 0f032ac7838ba3254ee3312430c34e02c00d36d3 Mon Sep 17 00:00:00 2001
From: SL <123@123.com>
Date: Thu, 14 Sep 2023 14:17:16 +0800
Subject: [PATCH] =?UTF-8?q?[Common]=20CredentialManager=E7=9A=84=5FdictCre?=
=?UTF-8?q?dentialsRequesting=E5=AD=97=E5=85=B8=E7=9A=84Key=E5=8F=98?=
=?UTF-8?q?=E6=9B=B4=E4=B8=BAstring=EF=BC=8C=E5=B7=B2LoginName=E4=B8=BA?=
=?UTF-8?q?=E4=B8=BB=E9=94=AE=E3=80=82=20CredentialKeepAliveResults?=
=?UTF-8?q?=E6=9E=9A=E4=B8=BE=E4=B8=AD=E5=A2=9E=E5=8A=A0RequestingLogin?=
=?UTF-8?q?=E5=AE=9A=E4=B9=89=EF=BC=8C=E7=94=A8=E4=BA=8E=E6=8C=87=E7=A4=BA?=
=?UTF-8?q?=E5=B7=B2=E7=99=BB=E5=BD=95=E7=9A=84=E5=AE=A2=E6=88=B7=E7=AB=AF?=
=?UTF-8?q?=E6=9C=89=E5=85=B6=E5=AE=83=E5=AE=A2=E6=88=B7=E7=AB=AF=E8=AF=B7?=
=?UTF-8?q?=E6=B1=82=E4=BD=BF=E7=94=A8=E6=AD=A4=E7=94=A8=E6=88=B7=E5=90=8D?=
=?UTF-8?q?=E7=99=BB=E5=BD=95=E3=80=82=20=E7=A7=BB=E9=99=A4IAccountService?=
=?UTF-8?q?=E5=AE=9E=E7=8E=B0=E7=B1=BB=E4=B8=AD=E5=A4=9A=E4=BD=99=E7=9A=84?=
=?UTF-8?q?=E5=87=BD=E6=95=B0=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
[UI.Client]
新增LoginRequestConfirmDialog窗体。
---
.../Aitex/Core/Account/AccountService.cs | 21 +----
.../Aitex/Core/Account/CredentialManager.cs | 68 ++++++++---------
.../Aitex/Core/Account/Misc.cs | 17 ++++-
.../Common/Account/AccountExManager.cs | 14 ++--
.../UI/Core/Accounts/AccountServiceClient.cs | 16 +---
.../LoginRequestConfirmationDialog.xaml | 47 ++++++++++++
.../LoginRequestConfirmationDialog.xaml.cs | 76 +++++++++++++++++++
.../MECF.Framework.UI.Client.csproj | 7 ++
.../Themes/SeaBlue/Skin.xaml | 1 +
.../Applications/UiApplication.cs | 10 ---
.../MECF.Framework.UI.Core.csproj | 4 +-
UIDebug/UserLoginTester/Program.cs | 6 +-
12 files changed, 200 insertions(+), 87 deletions(-)
create mode 100644 MECF.Framework.UI.Client/ClientBase/Dialog/LoginRequestConfirmationDialog.xaml
create mode 100644 MECF.Framework.UI.Client/ClientBase/Dialog/LoginRequestConfirmationDialog.xaml.cs
diff --git a/MECF.Framework.Common/Aitex/Core/Account/AccountService.cs b/MECF.Framework.Common/Aitex/Core/Account/AccountService.cs
index 522c22c..d595a17 100644
--- a/MECF.Framework.Common/Aitex/Core/Account/AccountService.cs
+++ b/MECF.Framework.Common/Aitex/Core/Account/AccountService.cs
@@ -16,19 +16,6 @@ namespace Aitex.Core.Account
public sealed class AccountService : IAccountService
{
public string Module => "System";
-
-
- public void Logout(string accountId)
- {
- EV.PostInfoLog(Module, $"User {accountId} logout sytem.");
- try
- {
- }
- catch
- {
- }
- AccountManager.Instance.Logout(accountId);
- }
public GetAccountInfoResult GetAccountInfo(string accountId)
{
@@ -254,9 +241,9 @@ namespace Aitex.Core.Account
}
- public void LogoutEx(Guid token)
+ public void LogoutEx(Credential cred)
{
- AccountExManager.Instance.Logout(token);
+ AccountExManager.Instance.Logout(cred);
}
///
@@ -264,9 +251,9 @@ namespace Aitex.Core.Account
///
/// 客户端登录凭据令牌。
///
- public CredentialKeepAliveResults KeepAlive(Guid token)
+ public CredentialKeepAliveResults KeepAlive(Credential cred)
{
- return CredentialManager.Instance.KeepAlive(token);
+ return CredentialManager.Instance.KeepAlive(cred);
}
}
}
diff --git a/MECF.Framework.Common/Aitex/Core/Account/CredentialManager.cs b/MECF.Framework.Common/Aitex/Core/Account/CredentialManager.cs
index 02369a7..09d4bf2 100644
--- a/MECF.Framework.Common/Aitex/Core/Account/CredentialManager.cs
+++ b/MECF.Framework.Common/Aitex/Core/Account/CredentialManager.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Aitex.Core.RT.Event;
using Aitex.Core.Util;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
namespace Aitex.Core.Account;
@@ -23,9 +24,9 @@ public class CredentialManager : Singleton
private readonly Dictionary _dictCredentialsLoggedIn = new ();
///
- /// 正在等在登录请求确认的凭据。
+ /// 正在等在登录请求确认的凭据,LoginName为字典Key。
///
- private readonly Dictionary _dictCredentialsRequesting = new ();
+ private readonly Dictionary _dictCredentialsRequesting = new ();
private readonly PeriodicJob _threadMonitorCred;
private bool _isInitialized;
@@ -87,32 +88,35 @@ public class CredentialManager : Singleton
{
lock (_syncRoot)
{
- var removableList = new List();
+ var loginRemovableList = new List();
foreach (var kvp in _dictCredentialsLoggedIn)
{
var cred = kvp.Value;
if ((DateTime.Now - cred.LastAliveTime).TotalSeconds > KEEP_ALIVE_TIMEOUT_SEC)
+ {
+ loginRemovableList.Add(cred.Token);
EV.PostLoginBySameUser(cred.Token, new Credential());
+ }
}
- if (removableList.Count > 0)
+ if (loginRemovableList.Count > 0)
{
- foreach (var token in removableList)
+ foreach (var token in loginRemovableList)
_dictCredentialsLoggedIn.Remove(token);
}
- removableList.Clear();
+ var requestRemovableList = new List();
foreach (var kvp in _dictCredentialsRequesting)
{
var cred = kvp.Value;
if ((DateTime.Now - cred.LastAliveTime).TotalSeconds > KEEP_ALIVE_TIMEOUT_SEC)
- removableList.Add(kvp.Key);
+ requestRemovableList.Add(kvp.Key);
}
- if (removableList.Count > 0)
+ if (requestRemovableList.Count > 0)
{
- foreach (var token in removableList)
- _dictCredentialsRequesting.Remove(token);
+ foreach (var loginName in requestRemovableList)
+ _dictCredentialsRequesting.Remove(loginName);
}
}
@@ -157,22 +161,27 @@ public class CredentialManager : Singleton
return _dictCredentialsLoggedIn.ContainsKey(token);
}
}
-
+
///
/// 报告客户端处于活动状态。
///
- /// 客户端登录凭据令牌。
+ /// 客户端登录凭据
///
- public CredentialKeepAliveResults KeepAlive(Guid token)
+ public CredentialKeepAliveResults KeepAlive(Credential cred)
{
lock (_syncRoot)
{
- if (_dictCredentialsLoggedIn.TryGetValue(token, out var cred))
+ if (_dictCredentialsLoggedIn.TryGetValue(cred.Token, out var loginCred))
{
- cred.LastAliveTime = DateTime.Now; // 刷新时间
- return CredentialKeepAliveResults.Alived;
- }
+ loginCred.LastAliveTime = DateTime.Now; // 刷新时间
+ // 如果当前用户名在请求登录列表中,则返回CredentialKeepAliveResults.RequestingLogin,通知
+ // 已登录的客户端,当前用户正在请求异地登录。
+ return _dictCredentialsRequesting.ContainsKey(cred.AccountInfo.LoginName)
+ ? CredentialKeepAliveResults.RequestingLogin
+ : CredentialKeepAliveResults.Alive;
+ }
+
return CredentialKeepAliveResults.NotFound;
}
}
@@ -186,10 +195,10 @@ public class CredentialManager : Singleton
{
lock (_syncRoot)
{
- if (_dictCredentialsRequesting.ContainsKey(cred.Token))
+ if (_dictCredentialsRequesting.ContainsKey(cred.AccountInfo.LoginName))
throw new InvalidOperationException("the credential has been existed in requesting list.");
- _dictCredentialsRequesting[cred.Token] = cred;
+ _dictCredentialsRequesting[cred.AccountInfo.LoginName] = cred;
}
}
@@ -211,12 +220,12 @@ public class CredentialManager : Singleton
if (_dictCredentialsLoggedIn.Count >= _maxCredentialAllowed)
throw new InvalidOperationException("maximum number of login credentials reached");
- if (!_dictCredentialsRequesting.ContainsKey(cred.Token))
+ if (!_dictCredentialsRequesting.ContainsKey(cred.AccountInfo.LoginName))
throw new InvalidOperationException("the credential is not found in requesting list.");
cred.State = CredentialState.Alive;
_dictCredentialsLoggedIn[cred.Token] = cred;
- _dictCredentialsRequesting.Remove(cred.Token);
+ _dictCredentialsRequesting.Remove(cred.AccountInfo.LoginName);
}
}
@@ -240,7 +249,7 @@ public class CredentialManager : Singleton
{
lock (_syncRoot)
{
- _dictCredentialsRequesting.Remove(cred.Token);
+ _dictCredentialsRequesting.Remove(cred.AccountInfo.LoginName);
}
}
@@ -279,20 +288,7 @@ public class CredentialManager : Singleton
{
lock (_syncRoot)
{
- return _dictCredentialsRequesting.Values.FirstOrDefault(x => x.AccountInfo.LoginName == userName);
- }
- }
-
- ///
- /// 获取指定令牌的正在等在登录请求的凭据。
- ///
- ///
- ///
- public Credential GetRequestingCredential(Guid token)
- {
- lock (_syncRoot)
- {
- return _dictCredentialsRequesting.TryGetValue(token, out var cred) ? cred : null;
+ return _dictCredentialsRequesting.TryGetValue(userName, out var cred) ? cred : null;
}
}
diff --git a/MECF.Framework.Common/Aitex/Core/Account/Misc.cs b/MECF.Framework.Common/Aitex/Core/Account/Misc.cs
index 0d738d3..c634f4f 100644
--- a/MECF.Framework.Common/Aitex/Core/Account/Misc.cs
+++ b/MECF.Framework.Common/Aitex/Core/Account/Misc.cs
@@ -41,10 +41,25 @@ public enum CredentialState
Reject
}
+///
+/// 凭据激活结果
+///
public enum CredentialKeepAliveResults
{
+ ///
+ /// 未找到凭据
+ ///
NotFound,
- Alived
+
+ ///
+ /// 凭据被激活
+ ///
+ Alive,
+
+ ///
+ /// 其它客户端正在请求登录
+ ///
+ RequestingLogin
}
public class Misc
diff --git a/MECF.Framework.Common/MECF/Framework/Common/Account/AccountExManager.cs b/MECF.Framework.Common/MECF/Framework/Common/Account/AccountExManager.cs
index 7949af5..d51fa4c 100644
--- a/MECF.Framework.Common/MECF/Framework/Common/Account/AccountExManager.cs
+++ b/MECF.Framework.Common/MECF/Framework/Common/Account/AccountExManager.cs
@@ -284,28 +284,28 @@ namespace MECF.Framework.Common.Account
public void ConfirmedLoginRequest(Credential requestingCred)
{
- var cred = CredentialManager.Instance.GetRequestingCredential(requestingCred.Token);
+ var cred = CredentialManager.Instance.GetRequestingCredential(requestingCred.AccountInfo.LoginName);
if (cred != null)
cred.State = CredentialState.Confirmed;
}
public void RejectLoginRequest(Credential requestingCred)
{
- var cred = CredentialManager.Instance.GetRequestingCredential(requestingCred.Token);
+ var cred = CredentialManager.Instance.GetRequestingCredential(requestingCred.AccountInfo.LoginName);
if (cred != null)
cred.State = CredentialState.Reject;
}
- internal void Logout(Guid token)
+ internal void Logout(Credential cred)
{
- var cred = CredentialManager.Instance.GetCredential(token);
- if (cred != null)
+ var loginCred = CredentialManager.Instance.GetCredential(cred.Token);
+ if (loginCred != null)
{
EV.PostMessage(ModuleName.System.ToString(), EventEnum.UserLoggedOff,
- cred.AccountInfo.LoginName);
+ loginCred.AccountInfo.LoginName);
}
- CredentialManager.Instance.Remove(token);
+ CredentialManager.Instance.Remove(cred.Token);
}
#endregion
diff --git a/MECF.Framework.Common/MECF/Framework/UI/Core/Accounts/AccountServiceClient.cs b/MECF.Framework.Common/MECF/Framework/UI/Core/Accounts/AccountServiceClient.cs
index 846242e..cc6e4cf 100644
--- a/MECF.Framework.Common/MECF/Framework/UI/Core/Accounts/AccountServiceClient.cs
+++ b/MECF.Framework.Common/MECF/Framework/UI/Core/Accounts/AccountServiceClient.cs
@@ -13,14 +13,6 @@ namespace MECF.Framework.UI.Core.Accounts
public AccountServiceClient()
{
}
-
- public void Logout(string accountId)
- {
- WCFProxy.Using(delegate(IAccountService svc)
- {
- svc.Logout(accountId);
- });
- }
public GetAccountInfoResult GetAccountInfo(string accountId)
{
@@ -314,20 +306,20 @@ namespace MECF.Framework.UI.Core.Accounts
});
}
- public void LogoutEx(Guid token)
+ public void LogoutEx(Credential cred)
{
WCFProxy.Using(delegate(IAccountService svc)
{
- svc.LogoutEx(token);
+ svc.LogoutEx(cred);
});
}
- public CredentialKeepAliveResults KeepAlive(Guid token)
+ public CredentialKeepAliveResults KeepAlive(Credential cred)
{
var result = CredentialKeepAliveResults.NotFound;
WCFProxy.Using(delegate(IAccountService svc)
{
- result = svc.KeepAlive(token);
+ result = svc.KeepAlive(cred);
});
return result;
}
diff --git a/MECF.Framework.UI.Client/ClientBase/Dialog/LoginRequestConfirmationDialog.xaml b/MECF.Framework.UI.Client/ClientBase/Dialog/LoginRequestConfirmationDialog.xaml
new file mode 100644
index 0000000..e035f4c
--- /dev/null
+++ b/MECF.Framework.UI.Client/ClientBase/Dialog/LoginRequestConfirmationDialog.xaml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MECF.Framework.UI.Client/ClientBase/Dialog/LoginRequestConfirmationDialog.xaml.cs b/MECF.Framework.UI.Client/ClientBase/Dialog/LoginRequestConfirmationDialog.xaml.cs
new file mode 100644
index 0000000..6fc4446
--- /dev/null
+++ b/MECF.Framework.UI.Client/ClientBase/Dialog/LoginRequestConfirmationDialog.xaml.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace MECF.Framework.UI.Client.ClientBase.Dialog
+{
+ ///
+ /// Interaction logic for LoginRequestConfirmationDialog.xaml
+ ///
+ public partial class LoginRequestConfirmationDialog : Window
+ {
+ #region Variables
+
+ private readonly CancellationTokenSource _ctsCountDownTask;
+ private readonly IProgress _progCountDown;
+
+ #endregion
+
+ public LoginRequestConfirmationDialog()
+ {
+ InitializeComponent();
+
+ _ctsCountDownTask = new CancellationTokenSource ();
+
+ _progCountDown = new Progress(countDown =>
+ {
+ if(countDown > 0)
+ BtnRejected.Content = $"Reject ({countDown:F0}s)";
+ else
+ DialogResult = false;
+ });
+ }
+
+ protected override void OnSourceInitialized(EventArgs e)
+ {
+ base.OnSourceInitialized(e);
+
+ var closeTime = DateTime.Now.Add(TimeSpan.FromSeconds(30));
+ Task.Run(() =>
+ {
+ while (true)
+ {
+ var timeRemained = (closeTime - DateTime.Now).TotalSeconds;
+ if (timeRemained <= 0)
+ {
+ // force to reject
+ _progCountDown.Report(0);
+ break;
+ }
+
+ _progCountDown.Report(timeRemained);
+ Thread.Sleep(500);
+
+ if (_ctsCountDownTask.Token.IsCancellationRequested)
+ break;
+ }
+ });
+ }
+
+ private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ _ctsCountDownTask?.Cancel();
+ }
+
+ private void BtnRejected_Click(object sender, RoutedEventArgs e)
+ {
+ DialogResult = false;
+ }
+
+ private void BtnAccept_Click(object sender, RoutedEventArgs e)
+ {
+ DialogResult = true;
+ }
+ }
+}
diff --git a/MECF.Framework.UI.Client/MECF.Framework.UI.Client.csproj b/MECF.Framework.UI.Client/MECF.Framework.UI.Client.csproj
index 37806c7..fb7a78d 100644
--- a/MECF.Framework.UI.Client/MECF.Framework.UI.Client.csproj
+++ b/MECF.Framework.UI.Client/MECF.Framework.UI.Client.csproj
@@ -243,6 +243,9 @@
+
+ LoginRequestConfirmationDialog.xaml
+
CoolingWaterDataPresenter.xaml
@@ -890,6 +893,10 @@
MSBuild:Compile
Designer
+
+ MSBuild:Compile
+ Designer
+
Designer
MSBuild:Compile
diff --git a/MECF.Framework.UI.Client/Themes/SeaBlue/Skin.xaml b/MECF.Framework.UI.Client/Themes/SeaBlue/Skin.xaml
index acfdc28..edc3b62 100644
--- a/MECF.Framework.UI.Client/Themes/SeaBlue/Skin.xaml
+++ b/MECF.Framework.UI.Client/Themes/SeaBlue/Skin.xaml
@@ -26,6 +26,7 @@
+
diff --git a/MECF.Framework.UI.Core/Applications/UiApplication.cs b/MECF.Framework.UI.Core/Applications/UiApplication.cs
index b46f62e..d2a8fd5 100644
--- a/MECF.Framework.UI.Core/Applications/UiApplication.cs
+++ b/MECF.Framework.UI.Core/Applications/UiApplication.cs
@@ -234,15 +234,5 @@ namespace MECF.Framework.UI.Core.Applications
OnWindowsLoaded();
}
-
- public void Logoff()
- {
- if (Current.EnableAccountModule)
- {
- AccountClient.Instance.Service.Logout(AccountClient.Instance.CurrentUser.AccountId);
- }
- _views.Logoff();
- }
-
}
}
diff --git a/MECF.Framework.UI.Core/MECF.Framework.UI.Core.csproj b/MECF.Framework.UI.Core/MECF.Framework.UI.Core.csproj
index 4fc8c42..80cd456 100644
--- a/MECF.Framework.UI.Core/MECF.Framework.UI.Core.csproj
+++ b/MECF.Framework.UI.Core/MECF.Framework.UI.Core.csproj
@@ -21,6 +21,7 @@
DEBUG;TRACE
prompt
4
+ latest
pdbonly
@@ -29,6 +30,7 @@
TRACE
prompt
4
+ latest
true
@@ -36,7 +38,7 @@
DEBUG;TRACE
full
AnyCPU
- 7.3
+ latest
prompt
diff --git a/UIDebug/UserLoginTester/Program.cs b/UIDebug/UserLoginTester/Program.cs
index 974cbf1..d2405a6 100644
--- a/UIDebug/UserLoginTester/Program.cs
+++ b/UIDebug/UserLoginTester/Program.cs
@@ -33,7 +33,7 @@ namespace UserLoginTester
Console.WriteLine(@"Press any key to exit...");
Console.ReadKey();
- AccountClient.Instance.Service.LogoutEx(retLogin.Credential.Token);
+ AccountClient.Instance.Service.LogoutEx(retLogin.Credential);
}
private static void Instance_OnDisconnectedWithRT()
@@ -55,7 +55,7 @@ namespace UserLoginTester
case EventType.LoginBySameUser_Notify:
if (Guid.TryParse(evt.Description, out var token) && evt.Tag is Credential requestingCred)
{
- if (token == _loginCred.Token)
+ if (_loginCred != null && token == _loginCred.Token)
{
Console.WriteLine(
@"Some users is requesting to login the system, you will be forced to switch to read-only mode, do you agree?");
@@ -67,7 +67,7 @@ namespace UserLoginTester
{
case "Y":
AccountClient.Instance.Service.ConfirmLoginRequest(requestingCred);
- AccountClient.Instance.Service.LogoutEx(_loginCred.Token);
+ AccountClient.Instance.Service.LogoutEx(_loginCred);
break;
case "N":
AccountClient.Instance.Service.RejectLoginRequest(requestingCred);