mirror of
https://github.com/achiez/NebulaAuth-Steam-Desktop-Authenticator-by-Achies.git
synced 2026-07-25 06:14:31 +00:00
Merge pull request #29 from achiez/feat/login-again-on-session-expired
feat(session): show LoginAgainDialog on permanent session expiry
This commit is contained in:
@@ -77,6 +77,10 @@ public partial class HintBox : UserControl
|
|||||||
IconKind = PackIconKind.ErrorOutline;
|
IconKind = PackIconKind.ErrorOutline;
|
||||||
IconBrush = (Brush) Application.Current.FindResource("ErrorBrush")!;
|
IconBrush = (Brush) Application.Current.FindResource("ErrorBrush")!;
|
||||||
break;
|
break;
|
||||||
|
case HintBoxSeverity.Warning:
|
||||||
|
IconKind = PackIconKind.WarningOutline;
|
||||||
|
IconBrush = (Brush) Application.Current.FindResource("WarningBrush")!;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
IconKind = PackIconKind.InfoCircleOutline;
|
IconKind = PackIconKind.InfoCircleOutline;
|
||||||
IconBrush = (Brush) Application.Current.FindResource("InfoBrush")!;
|
IconBrush = (Brush) Application.Current.FindResource("InfoBrush")!;
|
||||||
@@ -94,5 +98,6 @@ public partial class HintBox : UserControl
|
|||||||
public enum HintBoxSeverity
|
public enum HintBoxSeverity
|
||||||
{
|
{
|
||||||
Info,
|
Info,
|
||||||
|
Warning,
|
||||||
Error
|
Error
|
||||||
}
|
}
|
||||||
@@ -15,13 +15,15 @@ namespace NebulaAuth.Core;
|
|||||||
|
|
||||||
public static class DialogsController
|
public static class DialogsController
|
||||||
{
|
{
|
||||||
public static async Task<LoginAgainVM?> ShowLoginAgainDialog(string username, string? currentPassword = null)
|
public static async Task<LoginAgainVM?> ShowLoginAgainDialog(string username, string? currentPassword = null,
|
||||||
|
bool showNoProxyWarning = false)
|
||||||
{
|
{
|
||||||
var vm = new LoginAgainVM
|
var vm = new LoginAgainVM
|
||||||
{
|
{
|
||||||
UserName = username,
|
UserName = username,
|
||||||
Password = currentPassword ?? string.Empty,
|
Password = currentPassword ?? string.Empty,
|
||||||
SavePassword = PHandler.IsPasswordSet
|
SavePassword = PHandler.IsPasswordSet,
|
||||||
|
ShowNoProxyWarning = showNoProxyWarning
|
||||||
};
|
};
|
||||||
var content = new LoginAgainDialog
|
var content = new LoginAgainDialog
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -79,6 +79,16 @@
|
|||||||
"es": "Pulsa 'DEL' para eliminar",
|
"es": "Pulsa 'DEL' para eliminar",
|
||||||
"tr": "Silmek için 'DEL' tuşuna bas",
|
"tr": "Silmek için 'DEL' tuşuna bas",
|
||||||
"kk": "Жою үшін 'DEL' пернесін басыңыз"
|
"kk": "Жою үшін 'DEL' пернесін басыңыз"
|
||||||
|
},
|
||||||
|
"NoProxyWarning": {
|
||||||
|
"en": "No proxy is assigned",
|
||||||
|
"ru": "Прокси не установлен",
|
||||||
|
"zh": "未分配代理",
|
||||||
|
"uk": "Проксі не призначено",
|
||||||
|
"fr": "Aucun proxy assigné",
|
||||||
|
"es": "No hay ningún proxy asignado",
|
||||||
|
"tr": "Proxy atanmamış",
|
||||||
|
"kk": "Прокси тағайындалмаған"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ public static class MAACRequestHandler
|
|||||||
{
|
{
|
||||||
return withSessionHandler
|
return withSessionHandler
|
||||||
? Result<T>.Success(await SessionHandler.Handle(req, client.Mafile, client.Chp(),
|
? Result<T>.Success(await SessionHandler.Handle(req, client.Mafile, client.Chp(),
|
||||||
GetTimerPrefix(client.Mafile)))
|
GetTimerPrefix(client.Mafile), false))
|
||||||
: Result<T>.Success(await req());
|
: Result<T>.Success(await req());
|
||||||
}
|
}
|
||||||
catch (SessionInvalidException ex)
|
catch (SessionInvalidException ex)
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ using AchiesUtilities.Web.Models;
|
|||||||
using MaterialDesignThemes.Wpf;
|
using MaterialDesignThemes.Wpf;
|
||||||
using NebulaAuth.Core;
|
using NebulaAuth.Core;
|
||||||
using NebulaAuth.Model.Entities;
|
using NebulaAuth.Model.Entities;
|
||||||
|
using NebulaAuth.Utility;
|
||||||
using NebulaAuth.View.Dialogs;
|
using NebulaAuth.View.Dialogs;
|
||||||
|
using NebulaAuth.ViewModel.Other;
|
||||||
using SteamLib.Exceptions.Authorization;
|
using SteamLib.Exceptions.Authorization;
|
||||||
|
|
||||||
namespace NebulaAuth.Model;
|
namespace NebulaAuth.Model;
|
||||||
@@ -16,13 +18,13 @@ public static partial class SessionHandler
|
|||||||
private static readonly SemaphoreSlim Semaphore = new(1, 1);
|
private static readonly SemaphoreSlim Semaphore = new(1, 1);
|
||||||
|
|
||||||
public static async Task<T> Handle<T>(Func<Task<T>> func, Mafile mafile,
|
public static async Task<T> Handle<T>(Func<Task<T>> func, Mafile mafile,
|
||||||
HttpClientHandlerPair? chp = null, string? snackbarPrefix = null)
|
HttpClientHandlerPair? chp = null, string? snackbarPrefix = null, bool allowInteractiveLogin = true)
|
||||||
{
|
{
|
||||||
chp ??= MaClient.GetHttpClientHandlerPair(mafile);
|
chp ??= MaClient.GetHttpClientHandlerPair(mafile);
|
||||||
await Semaphore.WaitAsync();
|
await Semaphore.WaitAsync();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return await HandleInternal(func, chp.Value, mafile, snackbarPrefix);
|
return await HandleInternal(func, chp.Value, mafile, snackbarPrefix, allowInteractiveLogin);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -31,7 +33,7 @@ public static partial class SessionHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<T> HandleInternal<T>(Func<Task<T>> func, HttpClientHandlerPair chp, Mafile mafile,
|
private static async Task<T> HandleInternal<T>(Func<Task<T>> func, HttpClientHandlerPair chp, Mafile mafile,
|
||||||
string? snackbarPrefix = null)
|
string? snackbarPrefix = null, bool allowInteractiveLogin = true)
|
||||||
{
|
{
|
||||||
using var scope = Shell.Logger.PushScopeProperty("Scope", "SessionHandler");
|
using var scope = Shell.Logger.PushScopeProperty("Scope", "SessionHandler");
|
||||||
Exception? currentException = null;
|
Exception? currentException = null;
|
||||||
@@ -86,6 +88,32 @@ public static partial class SessionHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allowInteractiveLogin && !DialogHost.IsDialogOpen(null))
|
||||||
|
{
|
||||||
|
var noProxy = mafile.Proxy == null && MaClient.DefaultProxy == null;
|
||||||
|
var currentPassword = GetPassword(mafile);
|
||||||
|
|
||||||
|
Task<LoginAgainVM?> dialogTask = null!;
|
||||||
|
Application.Current.Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
dialogTask = DialogsController.ShowLoginAgainDialog(mafile.AccountName, currentPassword, noProxy);
|
||||||
|
});
|
||||||
|
|
||||||
|
var vm = await dialogTask;
|
||||||
|
if (vm != null)
|
||||||
|
{
|
||||||
|
Shell.Logger.Info("User provided credentials interactively for {name}, attempting login",
|
||||||
|
mafile.AccountName);
|
||||||
|
var logged = await LoginAgainInternal(chp, mafile, vm.Password, vm.SavePassword);
|
||||||
|
if (logged)
|
||||||
|
{
|
||||||
|
Shell.Logger.Debug("Interactive login for {name} succeeded, retrying operation",
|
||||||
|
mafile.AccountName);
|
||||||
|
return await func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throw new SessionPermanentlyExpiredException(SessionPermanentlyExpiredException.SESSION_EXPIRED_MSG,
|
throw new SessionPermanentlyExpiredException(SessionPermanentlyExpiredException.SESSION_EXPIRED_MSG,
|
||||||
currentException);
|
currentException);
|
||||||
}
|
}
|
||||||
@@ -118,6 +146,7 @@ public static partial class SessionHandler
|
|||||||
{
|
{
|
||||||
Shell.Logger.Debug(ex, "Failed to relogin mafile {name} {steamid}", mafile.AccountName,
|
Shell.Logger.Debug(ex, "Failed to relogin mafile {name} {steamid}", mafile.AccountName,
|
||||||
mafile.SessionData?.SteamId);
|
mafile.SessionData?.SteamId);
|
||||||
|
ExceptionHandler.Handle(ex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public static class ExceptionHandler
|
|||||||
}
|
}
|
||||||
case LoginException e:
|
case LoginException e:
|
||||||
{
|
{
|
||||||
return "LoginException".GetCodeBehindLocalization() + ": " +
|
return "LoginException".GetCodeBehindLocalization() +
|
||||||
ErrorTranslatorHelper.TranslateLoginError(e.Error);
|
ErrorTranslatorHelper.TranslateLoginError(e.Error);
|
||||||
}
|
}
|
||||||
case UnsupportedAuthTypeException e:
|
case UnsupportedAuthTypeException e:
|
||||||
|
|||||||
@@ -25,24 +25,30 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<TextBox TabIndex="0" Text="{Binding Password, UpdateSourceTrigger=PropertyChanged}"
|
<nebulaAuth:HintBox Grid.Row="0"
|
||||||
|
Margin="10,10,10,0"
|
||||||
|
Severity="Warning"
|
||||||
|
FontSize="14"
|
||||||
|
Visibility="{Binding ShowNoProxyWarning, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||||
|
Text="{Tr LoginAgainDialog.NoProxyWarning}" />
|
||||||
|
<TextBox TabIndex="0" Grid.Row="1" Text="{Binding Password, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
|
||||||
materialDesign:TextFieldAssist.HasClearButton="True"
|
materialDesign:TextFieldAssist.HasClearButton="True"
|
||||||
Padding="10"
|
Padding="10"
|
||||||
FontSize="15"
|
FontSize="15"
|
||||||
Margin="10,10,10,0"
|
Margin="10,10,10,0"
|
||||||
Grid.Row="0"
|
|
||||||
Style="{StaticResource MaterialDesignOutlinedTextBox}"
|
Style="{StaticResource MaterialDesignOutlinedTextBox}"
|
||||||
|
|
||||||
materialDesign:HintAssist.Hint="{Tr LoginAgainDialog.PasswordBox}"
|
materialDesign:HintAssist.Hint="{Tr LoginAgainDialog.PasswordBox}"
|
||||||
materialDesign:HintAssist.IsFloating="False"
|
materialDesign:HintAssist.IsFloating="False"
|
||||||
materialDesign:TextFieldAssist.LeadingIcon="Key"
|
materialDesign:TextFieldAssist.LeadingIcon="Key"
|
||||||
materialDesign:TextFieldAssist.HasLeadingIcon="True" />
|
materialDesign:TextFieldAssist.HasLeadingIcon="True" />
|
||||||
<CheckBox FontSize="15" Grid.Row="1" Margin="10,5,10,0"
|
<CheckBox FontSize="15" Grid.Row="2" Margin="10,5,10,0"
|
||||||
IsEnabled="{Binding Source={x:Static model:PHandler.IsPasswordSet}}"
|
IsEnabled="{Binding Source={x:Static model:PHandler.IsPasswordSet}}"
|
||||||
IsChecked="{Binding SavePassword}" Content="{Tr LoginAgainDialog.SaveEncryptedPassword}" />
|
IsChecked="{Binding SavePassword}" Content="{Tr LoginAgainDialog.SaveEncryptedPassword}" />
|
||||||
<Grid Grid.Row="2" Margin="10,10,10,0">
|
<Grid Grid.Row="3" Margin="10,10,10,0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition />
|
<ColumnDefinition />
|
||||||
<ColumnDefinition />
|
<ColumnDefinition />
|
||||||
|
|||||||
@@ -11,5 +11,7 @@ public partial class LoginAgainVM : ObservableObject
|
|||||||
|
|
||||||
[ObservableProperty] private bool _savePassword;
|
[ObservableProperty] private bool _savePassword;
|
||||||
|
|
||||||
|
[ObservableProperty] private bool _showNoProxyWarning;
|
||||||
|
|
||||||
[ObservableProperty] private string _userName = null!;
|
[ObservableProperty] private string _userName = null!;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user