更新库文件600d1bc,完善单一用户登录机制,增加登录测试项目UserLoginTester。

This commit is contained in:
SL 2023-09-14 09:01:23 +08:00
parent ad1f13c3e0
commit f9197020b8
9 changed files with 132 additions and 138 deletions

View File

@ -59,7 +59,7 @@
BorderBrush="Gray"
BorderThickness="3"
Message="{Binding RequestLoginIndicatorText}"
Visibility="{Binding IsShowRequestLoginIndicator, Converter={StaticResource BoolVisibilityConverter}}">
Visibility="{Binding IsShowLoginWaiter, Converter={StaticResource BoolVisibilityConverter}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Canceled">
<cal:ActionMessage MethodName="CancelRequestLogin" />
@ -1098,7 +1098,7 @@
Style="{DynamicResource Logout_Button}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="Logout" />
<cal:ActionMessage MethodName="ShowLogoutDialog" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>

View File

@ -27,10 +27,7 @@ using Sicentury.Core.Collections;
using System.Diagnostics;
using System.Net;
using System.Threading.Tasks;
using Aitex.Core.WCF.Interface;
using Caliburn.Micro.Core;
using AuthorizeResult = MECF.Framework.UI.Client.ClientBase.AuthorizeResult;
using Newtonsoft.Json.Linq;
namespace SicUI.Client
{
@ -412,27 +409,31 @@ namespace SicUI.Client
break;
case EventType.LoginBySameUser_Notify:
if (evt.Tag is Credential cred)
if (Guid.TryParse(evt.Description, out var token) && evt.Tag is Credential requestingCred)
{
if (cred.LoginName == BaseApp.Instance.UserContext.LoginName
|| cred.Token == BaseApp.Instance.UserContext.Token)
if (token == BaseApp.Instance.UserContext.Token)
{
Execute.OnUIThread(()=>
{
var ret = DialogBox.ShowDialog(
DialogButton.Yes | DialogButton.No,
DialogType.INFO,
"Some users is logging into the system, you will be forced to switch to read-only mode, do you agree?");
"Some users is requesting to login the system, you will be forced to switch to read-only mode, do you agree?");
if (ret == DialogButton.Yes)
{
AccountClient.Instance.Service.ConfirmLoginRequest(requestingCred);
Logoff();
User.LoginName = "Read-Only";
// 降级为仅查看模式
BaseApp.Instance.UserContext.Credential = Credential.ReadOnlyOne;
IsReadOnlyMode = true;
}
else
{
AccountClient.Instance.Service.RejectLoginRequest(requestingCred);
}
});
}
}
@ -455,20 +456,21 @@ namespace SicUI.Client
}
#region login part
#region Login/Logout Operations
public void Enter(KeyEventArgs args, string loginName, PasswordBox password, Role role)
{
if (args.Key == Key.Enter)
Login(loginName, password, role);
RequestLogin(loginName, password, role);
}
private bool _isShowRequestLoginIndicator;
public bool IsShowRequestLoginIndicator
private bool _isShowLoginWaiter;
public bool IsShowLoginWaiter
{
get=>_isShowRequestLoginIndicator;
get=>_isShowLoginWaiter;
set
{
_isShowRequestLoginIndicator = value;
_isShowLoginWaiter = value;
NotifyOfPropertyChange();
}
}
@ -484,12 +486,14 @@ namespace SicUI.Client
}
}
private Task<LoginRequestResults> _loginTask;
private Task<LoginResult> _loginTask;
private CancellationTokenSource _ctsWaitingTask;
private string _lastLoginUserName = "";
public void CancelRequestLogin()
{
AccountClient.Instance.Service.CancelLoginRequest();
if(string.IsNullOrEmpty(_lastLoginUserName) == false)
AccountClient.Instance.Service.CancelLoginRequest(_lastLoginUserName);
}
public Task ShowRequestLoginIndicator()
@ -508,7 +512,7 @@ namespace SicUI.Client
if (token.IsCancellationRequested)
return;
Execute.OnUIThread(() => IsShowRequestLoginIndicator = true);
Execute.OnUIThread(() => IsShowLoginWaiter = true);
while (true)
{
@ -529,7 +533,7 @@ namespace SicUI.Client
Execute.OnUIThread(() =>
{
RequestLoginIndicatorText = "Waiting for RT to confirm login request, 0s remained";
IsShowRequestLoginIndicator = false;
IsShowLoginWaiter = false;
});
}
});
@ -540,13 +544,17 @@ namespace SicUI.Client
if (_loginTask is { Status: TaskStatus.Running })
return;
Task taskWaiting = default;
_lastLoginUserName = loginName;
var myInfo = new LoginClientInfo();
myInfo.HostName = Dns.GetHostName();
myInfo.HostIP = (await Dns.GetHostEntryAsync(myInfo.HostName)).AddressList[0];
// 向RT请求登录
try
{
taskWaiting =ShowRequestLoginIndicator();
_loginTask = AccountClient.Instance.Service.RequestLogin();
var taskWaiting = ShowRequestLoginIndicator();
_loginTask = AccountClient.Instance.Service.LoginEx(loginName, password.Password, role.RoleId, myInfo);
await Task.WhenAny(_loginTask, taskWaiting);
@ -554,120 +562,81 @@ namespace SicUI.Client
if (taskWaiting.Status == TaskStatus.RanToCompletion)
{
// 等待超时
DialogBox.ShowError("Login failed, timeout of waiting login request confirmation.");
AccountClient.Instance.Service.CancelLoginRequest(loginName);
}
else if (_loginTask.Status == TaskStatus.RanToCompletion)
{
switch (_loginTask.Result.Result)
{
case LoginRequestResults.Error:
DialogBox.ShowError("Error occurred when login, see log for details.");
break;
case LoginRequestResults.WrongPwd:
DialogBox.ShowError("Invalid password.");
break;
case LoginRequestResults.NoMatchRole:
DialogBox.ShowError("The user does not belong to the role.");
break;
case LoginRequestResults.NoMatchUser:
DialogBox.ShowError("The user is not found.");
break;
case LoginRequestResults.Rejected:
DialogBox.ShowError("Login Request is rejected.");
break;
case LoginRequestResults.RequstingLogin:
DialogBox.ShowError(
"The same user is requesting to login from other place, please try again later.");
break;
case LoginRequestResults.Timeout:
DialogBox.ShowError("Timeout to wait login request confirmation.");
break;
case LoginRequestResults.Confirmed:
var cred = _loginTask.Result.Credential;
BaseApp.Instance.UserMode = UserMode.Normal;
BaseApp.Instance.UserContext.Credential = cred;
BaseApp.Instance.UserContext.Role = role;
BaseApp.Instance.UserContext.LastAccessTime = DateTime.Now;
BaseApp.Instance.UserContext.IsLogin = true;
//Load menu by role
//filer menu if necessary...
BaseApp.Instance.MenuManager.LoadMenu(
RoleAccountProvider.Instance.GetMenusByRole(role.RoleId));
IsAutoLogout = role.IsAutoLogout;
LogoutTime = role.LogoutTime;
IsPermission = RoleAccountProvider.Instance.GetMenuPermission(role.RoleId, "Header") == 3;
InitMenu(); //bind menu to main view
IsLogin = true; //control the display logic of main view
IsReadOnlyMode = false;
LOG.Info($"{loginName} login as {role.RoleName}");
break;
default:
DialogBox.ShowError("Unknown login result, see log for details.");
break;
}
if (_loginTask.Result == LoginRequestResults.Rejected)
DialogBox.ShowError("Login failed, rejected by RT.");
else
Login(loginName, password, role);
}
}
catch (InvalidOperationException ex)
{
}
}
public void Login(string loginName, PasswordBox password, Role role)
{
try
{
var myInfo = new LoginClientInfo();
myInfo.HostName = Dns.GetHostName();
myInfo.HostIP = Dns.GetHostEntry(myInfo.HostName).AddressList[0];
var result = AccountClient.Instance.Service.LoginEx(loginName, password.Password, role.RoleId, myInfo);
if (result.ActSucc)
{
BaseApp.Instance.UserMode = UserMode.Normal;
BaseApp.Instance.UserContext.LoginName = loginName;
BaseApp.Instance.UserContext.Role = role;
BaseApp.Instance.UserContext.LoginTime = result.LoginTime;
BaseApp.Instance.UserContext.Token = result.Token;
BaseApp.Instance.UserContext.LastAccessTime = DateTime.Now;
BaseApp.Instance.UserContext.IsLogin = true;
//Load menu by role
//filer menu if necessary...
BaseApp.Instance.MenuManager.LoadMenu(RoleAccountProvider.Instance.GetMenusByRole(role.RoleId));
IsAutoLogout = role.IsAutoLogout;
LogoutTime = role.LogoutTime;
IsPermission = RoleAccountProvider.Instance.GetMenuPermission(role.RoleId, "Header") == 3;
InitMenu(); //bind menu to main view
IsLogin = true; //control the display logic of main view
IsReadOnlyMode = false;
LOG.Info($"{loginName} login as {role.RoleName}");
}
else
{
Enum.TryParse(result.Description, out AuthorizeResult errCode);
switch (errCode)
{
case AuthorizeResult.None:
DialogBox.ShowError("Not connected with RT.");
break;
case AuthorizeResult.WrongPwd:
DialogBox.ShowError("Invalid password.");
break;
case AuthorizeResult.HasLogin:
DialogBox.ShowError("{0} has already logged in.", loginName);
break;
case AuthorizeResult.NoMatchRole:
DialogBox.ShowError("{0} does not match {1} role.", loginName, role.RoleName);
break;
case AuthorizeResult.NoMatchUser:
DialogBox.ShowError("{0} does not exists.", loginName);
break;
case AuthorizeResult.NoSession:
DialogBox.ShowError("The current session is invalid.");
break;
}
}
password.Clear();
LOG.Error(ex.Message);
}
catch (Exception ex)
{
LOG.Error(ex.Message, ex);
}
}
#endregion
public void SetModuleOnline(string module)
{
if (MessageBoxResult.Yes == MessageBox.Show($"Set {module} Online ?", "", MessageBoxButton.YesNo, MessageBoxImage.Warning))
{
InvokeClient.Instance.Service.DoOperation($"{module}.SetOnline");
}
}
public void SetModuleOffline(string module)
{
if (MessageBoxResult.Yes == MessageBox.Show($"Set {module} Offline ?", "", MessageBoxButton.YesNo, MessageBoxImage.Warning))
{
InvokeClient.Instance.Service.DoOperation($"{module}.SetOffline");
LOG.Error(ex.Message);
}
}
public void Logout()
{
OnLogoutCommand();
}
public void OnLogoutCommand()
public void ShowLogoutDialog()
{
if (!IsReadOnlyMode)
{
@ -715,6 +684,7 @@ namespace SicUI.Client
}
}
public void Logoff()
{
BaseApp.Instance.UserMode = UserMode.Logoff;
@ -735,9 +705,25 @@ namespace SicUI.Client
}
IsLogin = false; //no independent login page
Roles = RoleAccountProvider.Instance.GetRoles();
// 如果 ProcessMonitor 打开,则关闭
//if (_eventAggregator?.HandlerExistsFor(typeof(ShowCloseMonitorWinEvent)) == true)
// _eventAggregator?.PublishOnUIThread(new ShowCloseMonitorWinEvent(false));
}
#endregion
public void SetModuleOnline(string module)
{
if (MessageBoxResult.Yes == MessageBox.Show($"Set {module} Online ?", "", MessageBoxButton.YesNo, MessageBoxImage.Warning))
{
InvokeClient.Instance.Service.DoOperation($"{module}.SetOnline");
}
}
public void SetModuleOffline(string module)
{
if (MessageBoxResult.Yes == MessageBox.Show($"Set {module} Offline ?", "", MessageBoxButton.YesNo, MessageBoxImage.Warning))
{
InvokeClient.Instance.Service.DoOperation($"{module}.SetOffline");
}
}
public void Reset()
@ -751,15 +737,13 @@ namespace SicUI.Client
}
#region override functions
public override void CanClose(Action<bool> callback)
{
if (BaseApp.Instance.UserMode == UserMode.Normal)
{
callback(false);
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, (ThreadStart)delegate
{
OnLogoutCommand();
});
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, (ThreadStart)ShowLogoutDialog);
}
else
callback(true);
@ -774,7 +758,7 @@ namespace SicUI.Client
StartTimer();
if (Debugger.IsAttached)
{
Login("admin", new PasswordBox() { Password = "admin" }, new Role("0", "Manager", false, 1000, null));
RequestLogin("admin", new PasswordBox() { Password = "admin" }, new Role("0", "Manager", false, 1000, null));
}
}
@ -942,23 +926,34 @@ namespace SicUI.Client
if (_alarmMenu != null)
_alarmMenu.IsAlarm = SystemHasAlarm;
}
protected override bool OnTimer()
{
try
{
base.Poll();
List<Role> roles = RoleAccountProvider.Instance.GetRoles();
if (!string.IsNullOrEmpty(BaseApp.Instance.UserContext.Role.RoleName))
var roles = RoleAccountProvider.Instance.GetRoles();
if (!Credential.IsEmpty(BaseApp.Instance.UserContext.Credential))
{
Role role = roles.Find(x => x.RoleName == BaseApp.Instance.UserContext.Role.RoleName);
var role = roles.Find(x => x.RoleName == BaseApp.Instance.UserContext.Role.RoleName);
LogoutTime = role.LogoutTime;
IsAutoLogout = role.IsAutoLogout;
int intervaltime = GetLastInputTime();
//if (System.DateTime.Now >= ClientApp.Instance.UserContext.LoginTime.AddMinutes(LogoutTime) && IsLogin && IsAutoLogout)
if (intervaltime >= LogoutTime * 60 && IsLogin && IsAutoLogout)
var idleDuration = GetLastInputTime();
if (idleDuration >= LogoutTime * 60 && IsLogin && IsAutoLogout)
Logoff();
}
else
{
// keep credential alive
var ret = AccountClient.Instance.Service.KeepAlive(BaseApp.Instance.UserContext.Token);
if (ret == CredentialKeepAliveResults.NotFound)
{
Logoff();
Execute.OnUIThread(() => { DialogBox.ShowError("You are kicked by RT."); });
}
}
}
}
catch (Exception ex)
{

View File

@ -5,7 +5,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Aitex.Core.RT.Log;