diff --git a/SicUI/MainView.xaml b/SicUI/MainView.xaml index 6cce120..0342f87 100644 --- a/SicUI/MainView.xaml +++ b/SicUI/MainView.xaml @@ -59,7 +59,7 @@ BorderBrush="Gray" BorderThickness="3" Message="{Binding RequestLoginIndicatorText}" - Visibility="{Binding IsShowRequestLoginIndicator, Converter={StaticResource BoolVisibilityConverter}}"> + Visibility="{Binding IsShowLoginWaiter, Converter={StaticResource BoolVisibilityConverter}}"> @@ -1098,7 +1098,7 @@ Style="{DynamicResource Logout_Button}"> - + diff --git a/SicUI/MainViewModel.cs b/SicUI/MainViewModel.cs index d2c0a81..f822d81 100644 --- a/SicUI/MainViewModel.cs +++ b/SicUI/MainViewModel.cs @@ -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 _loginTask; + private Task _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 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 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) { diff --git a/SicUI/TimeredMainViewModel.cs b/SicUI/TimeredMainViewModel.cs index d120bfa..54d93b1 100644 --- a/SicUI/TimeredMainViewModel.cs +++ b/SicUI/TimeredMainViewModel.cs @@ -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; diff --git a/ThirdParty/MECF.Framework/MECF.Framework.Common.dll b/ThirdParty/MECF.Framework/MECF.Framework.Common.dll index d6ee059..d7e02cd 100644 Binary files a/ThirdParty/MECF.Framework/MECF.Framework.Common.dll and b/ThirdParty/MECF.Framework/MECF.Framework.Common.dll differ diff --git a/ThirdParty/MECF.Framework/MECF.Framework.RT.Core.dll b/ThirdParty/MECF.Framework/MECF.Framework.RT.Core.dll index 18b2b29..5522d86 100644 Binary files a/ThirdParty/MECF.Framework/MECF.Framework.RT.Core.dll and b/ThirdParty/MECF.Framework/MECF.Framework.RT.Core.dll differ diff --git a/ThirdParty/MECF.Framework/MECF.Framework.RT.EquipmentLibrary.dll b/ThirdParty/MECF.Framework/MECF.Framework.RT.EquipmentLibrary.dll index 7265c70..85cc649 100644 Binary files a/ThirdParty/MECF.Framework/MECF.Framework.RT.EquipmentLibrary.dll and b/ThirdParty/MECF.Framework/MECF.Framework.RT.EquipmentLibrary.dll differ diff --git a/ThirdParty/MECF.Framework/MECF.Framework.Simulator.Core.dll b/ThirdParty/MECF.Framework/MECF.Framework.Simulator.Core.dll index 3f03e3d..c0b4143 100644 Binary files a/ThirdParty/MECF.Framework/MECF.Framework.Simulator.Core.dll and b/ThirdParty/MECF.Framework/MECF.Framework.Simulator.Core.dll differ diff --git a/ThirdParty/MECF.Framework/MECF.Framework.UI.Client.dll b/ThirdParty/MECF.Framework/MECF.Framework.UI.Client.dll index 453cc6c..01db6a1 100644 Binary files a/ThirdParty/MECF.Framework/MECF.Framework.UI.Client.dll and b/ThirdParty/MECF.Framework/MECF.Framework.UI.Client.dll differ diff --git a/ThirdParty/MECF.Framework/MECF.Framework.UI.Core.dll b/ThirdParty/MECF.Framework/MECF.Framework.UI.Core.dll index f0b3094..5dabe54 100644 Binary files a/ThirdParty/MECF.Framework/MECF.Framework.UI.Core.dll and b/ThirdParty/MECF.Framework/MECF.Framework.UI.Core.dll differ