[Common]
CredentialManager的_dictCredentialsRequesting字典的Key变更为string,已LoginName为主键。 CredentialKeepAliveResults枚举中增加RequestingLogin定义,用于指示已登录的客户端有其它客户端请求使用此用户名登录。 移除IAccountService实现类中多余的函数。 [UI.Client] 新增LoginRequestConfirmDialog窗体。
This commit is contained in:
parent
9a8c73664d
commit
0f032ac783
|
@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -264,9 +251,9 @@ namespace Aitex.Core.Account
|
|||
/// </summary>
|
||||
/// <param name="token">客户端登录凭据令牌。</param>
|
||||
/// <returns></returns>
|
||||
public CredentialKeepAliveResults KeepAlive(Guid token)
|
||||
public CredentialKeepAliveResults KeepAlive(Credential cred)
|
||||
{
|
||||
return CredentialManager.Instance.KeepAlive(token);
|
||||
return CredentialManager.Instance.KeepAlive(cred);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<CredentialManager>
|
|||
private readonly Dictionary<Guid, Credential> _dictCredentialsLoggedIn = new ();
|
||||
|
||||
/// <summary>
|
||||
/// 正在等在登录请求确认的凭据。
|
||||
/// 正在等在登录请求确认的凭据,LoginName为字典Key。
|
||||
/// </summary>
|
||||
private readonly Dictionary<Guid, Credential> _dictCredentialsRequesting = new ();
|
||||
private readonly Dictionary<string, Credential> _dictCredentialsRequesting = new ();
|
||||
|
||||
private readonly PeriodicJob _threadMonitorCred;
|
||||
private bool _isInitialized;
|
||||
|
@ -87,32 +88,35 @@ public class CredentialManager : Singleton<CredentialManager>
|
|||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
var removableList = new List<Guid>();
|
||||
var loginRemovableList = new List<Guid>();
|
||||
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<string>();
|
||||
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<CredentialManager>
|
|||
return _dictCredentialsLoggedIn.ContainsKey(token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 报告客户端处于活动状态。
|
||||
/// </summary>
|
||||
/// <param name="token">客户端登录凭据令牌。</param>
|
||||
/// <param name="cred">客户端登录凭据</param>
|
||||
/// <returns></returns>
|
||||
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<CredentialManager>
|
|||
{
|
||||
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<CredentialManager>
|
|||
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<CredentialManager>
|
|||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
_dictCredentialsRequesting.Remove(cred.Token);
|
||||
_dictCredentialsRequesting.Remove(cred.AccountInfo.LoginName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,20 +288,7 @@ public class CredentialManager : Singleton<CredentialManager>
|
|||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
return _dictCredentialsRequesting.Values.FirstOrDefault(x => x.AccountInfo.LoginName == userName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定令牌的正在等在登录请求的凭据。
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,10 +41,25 @@ public enum CredentialState
|
|||
Reject
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 凭据激活结果
|
||||
/// </summary>
|
||||
public enum CredentialKeepAliveResults
|
||||
{
|
||||
/// <summary>
|
||||
/// 未找到凭据
|
||||
/// </summary>
|
||||
NotFound,
|
||||
Alived
|
||||
|
||||
/// <summary>
|
||||
/// 凭据被激活
|
||||
/// </summary>
|
||||
Alive,
|
||||
|
||||
/// <summary>
|
||||
/// 其它客户端正在请求登录
|
||||
/// </summary>
|
||||
RequestingLogin
|
||||
}
|
||||
|
||||
public class Misc
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<Window x:Class="MECF.Framework.UI.Client.ClientBase.Dialog.LoginRequestConfirmationDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
Height="220" Width="400"
|
||||
d:Background="White"
|
||||
Title="Login Request Confirmation"
|
||||
ResizeMode="CanResize"
|
||||
WindowStyle="None"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Closing="Window_Closing">
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome ResizeBorderThickness="0" CaptionHeight="0"/>
|
||||
</WindowChrome.WindowChrome>
|
||||
<Window.Effect>
|
||||
<DropShadowEffect Color="Gray" BlurRadius="10" Direction="-90" RenderingBias="Quality" ShadowDepth="4"/>
|
||||
</Window.Effect>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="20"/>
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border Background="{StaticResource Color_BG_TopStrip}"/>
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="50"/>
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="70"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Text="Login Request" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<StackPanel Grid.Row="1" Margin="20 0" HorizontalAlignment="Center" >
|
||||
<TextBlock
|
||||
Text="The current user is requesting to login from somewhere, do you agree to it's request and logout from the system?"
|
||||
TextWrapping="Wrap"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Button x:Name="BtnAccept" Content="Accept" VerticalAlignment="Center" Height="30" Width="120" Margin="0,0,5,0" Click="BtnAccept_Click" />
|
||||
<Button x:Name="BtnRejected" Content="Reject" VerticalAlignment="Center" Height="30" Width="120" Margin="5,0,0,0" Click="BtnRejected_Click" IsCancel="True" IsDefault="True" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
|
@ -0,0 +1,76 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace MECF.Framework.UI.Client.ClientBase.Dialog
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for LoginRequestConfirmationDialog.xaml
|
||||
/// </summary>
|
||||
public partial class LoginRequestConfirmationDialog : Window
|
||||
{
|
||||
#region Variables
|
||||
|
||||
private readonly CancellationTokenSource _ctsCountDownTask;
|
||||
private readonly IProgress<double> _progCountDown;
|
||||
|
||||
#endregion
|
||||
|
||||
public LoginRequestConfirmationDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_ctsCountDownTask = new CancellationTokenSource ();
|
||||
|
||||
_progCountDown = new Progress<double>(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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -243,6 +243,9 @@
|
|||
<Compile Include="CenterViews\Modules\PM\ProcessMonitorView.xaml.cs" />
|
||||
<Compile Include="CenterViews\Modules\PM\ProcessMonitorViewModel.cs" />
|
||||
<Compile Include="CenterViews\Modules\PM\ShowCloseMonitorWinEvent.cs" />
|
||||
<Compile Include="ClientBase\Dialog\LoginRequestConfirmationDialog.xaml.cs">
|
||||
<DependentUpon>LoginRequestConfirmationDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Ctrlib\Controls\CoolingWaterDataPresenter.xaml.cs">
|
||||
<DependentUpon>CoolingWaterDataPresenter.xaml</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -890,6 +893,10 @@
|
|||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="ClientBase\Dialog\LoginRequestConfirmationDialog.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Ctrlib\Controls\CoolingWaterDataPresenter.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
<GradientStop Offset="0" Color="#FF1B85D8" />
|
||||
<GradientStop Offset="0.988" Color="#FF004D89" />
|
||||
</LinearGradientBrush>
|
||||
<SolidColorBrush x:Key="Color_BG_TopStrip" Color="#FF1A5E94" />
|
||||
<SolidColorBrush x:Key="Color_BD_LoginTitle" Color="#FF6BBEFF" />
|
||||
<SolidColorBrush x:Key="Color_BD_LoginTitle_Shadow" Color="#FF0067AB" />
|
||||
<SolidColorBrush x:Key="Color_BD_LoginTitle_Highlight" Color="#FF6BBEFF" />
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
|
@ -29,6 +30,7 @@
|
|||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugWithoutCopyFiles|AnyCPU'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -36,7 +38,7 @@
|
|||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue