Merge pull request #797 from erri120/mega-api-update-181

Added MFA support for INeedsLoginCredentials
This commit is contained in:
Timothy Baldridge 2020-05-05 14:12:10 -06:00 committed by GitHub
commit 7908ff15a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 59 additions and 26 deletions

View File

@ -16,20 +16,29 @@ namespace Wabbajack.Lib.Downloaders
Uri? IconUri { get; }
}
public enum LoginReturnCode
{
InternalError = -1,
Success = 0,
BadInput = 1,
BadCredentials = 2,
NeedsMFA = 3,
}
public struct LoginReturnMessage
{
public string Message;
public bool Failure;
public LoginReturnCode ReturnCode;
public LoginReturnMessage(string message, bool failure)
public LoginReturnMessage(string message, LoginReturnCode returnCode)
{
Message = message;
Failure = failure;
ReturnCode = returnCode;
}
}
public interface INeedsLoginCredentials : INeedsLogin
{
LoginReturnMessage LoginWithCredentials(string username, SecureString password);
LoginReturnMessage LoginWithCredentials(string username, SecureString password, string? mfa);
}
}

View File

@ -38,34 +38,34 @@ namespace Wabbajack.Lib.Downloaders
{
Email = infos.Email,
Hash = infos.Hash,
PasswordAesKey = infos.PasswordAesKey
PasswordAesKey = infos.PasswordAesKey,
MFAKey = infos.MFAKey
};
}
public MegaApiClient.AuthInfos ToAuthInfos()
{
//TODO: MFAKey in the update
return new MegaApiClient.AuthInfos(Email, Hash, PasswordAesKey);
return new MegaApiClient.AuthInfos(Email, Hash, PasswordAesKey, MFAKey);
}
}
public LoginReturnMessage LoginWithCredentials(string username, SecureString password)
public LoginReturnMessage LoginWithCredentials(string username, SecureString password, string? mfa)
{
MegaApiClient.AuthInfos authInfos;
try
{
authInfos = MegaApiClient.GenerateAuthInfos(username, password.ToNormalString());
authInfos = MegaApiClient.GenerateAuthInfos(username, password.ToNormalString(), mfa);
}
catch (ApiException e)
{
return e.ApiResultCode switch
{
ApiResultCode.BadArguments => new LoginReturnMessage($"Email or password was wrong! {e.Message}",
true),
LoginReturnCode.BadCredentials),
ApiResultCode.InternalError => new LoginReturnMessage(
$"Internal error occured! Please report this to the Wabbajack Team! {e.Message}", true),
_ => new LoginReturnMessage($"Error generating authentication information! {e.Message}", true)
$"Internal error occured! Please report this to the Wabbajack Team! {e.Message}", LoginReturnCode.InternalError),
_ => new LoginReturnMessage($"Error generating authentication information! {e.Message}", LoginReturnCode.InternalError)
};
}
@ -78,10 +78,14 @@ namespace Wabbajack.Lib.Downloaders
return e.ApiResultCode switch
{
ApiResultCode.TwoFactorAuthenticationError => new LoginReturnMessage(
$"Two-Factor Authentication needs to be disabled before login! {e.Message}", true),
$"Two-Factor Authentication is enabled. Input your TFA key above and try again! {e.Message}", LoginReturnCode.NeedsMFA),
ApiResultCode.InternalError => new LoginReturnMessage(
$"Internal error occured! Please report this to the Wabbajack Team! {e.Message}", true),
_ => new LoginReturnMessage($"Error during login: {e.Message}", true)
$"Internal error occured! Please report this to the Wabbajack Team! {e.Message}", LoginReturnCode.InternalError),
ApiResultCode.RequestIncomplete => new LoginReturnMessage(
$"Bad credentials! {e.Message}", LoginReturnCode.BadCredentials),
ApiResultCode.ResourceNotExists => new LoginReturnMessage(
$"Bad credentials! {e.Message}", LoginReturnCode.BadCredentials),
_ => new LoginReturnMessage($"Error during login: {e.Message}", LoginReturnCode.InternalError)
};
}
@ -92,7 +96,7 @@ namespace Wabbajack.Lib.Downloaders
}
return new LoginReturnMessage("Logged in successfully, you can now close this window.",
!MegaApiClient.IsLoggedIn || !Utils.HaveEncryptedJson(DataName));
!MegaApiClient.IsLoggedIn || !Utils.HaveEncryptedJson(DataName) ? LoginReturnCode.Success : LoginReturnCode.InternalError);
}
public MegaDownloader()
@ -133,7 +137,7 @@ namespace Wabbajack.Lib.Downloaders
private static MegaApiClient MegaApiClient => DownloadDispatcher.GetInstance<MegaDownloader>().MegaApiClient;
private static AsyncLock _loginLock = new AsyncLock();
private static readonly AsyncLock _loginLock = new AsyncLock();
private static async Task MegaLogin()
{
using var _ = await _loginLock.WaitAsync();

View File

@ -26,7 +26,7 @@
<Version>1.11.23</Version>
</PackageReference>
<PackageReference Include="MegaApiClient">
<Version>1.8.0</Version>
<Version>1.8.1</Version>
</PackageReference>
<PackageReference Include="Microsoft.CSharp">
<Version>4.7.0</Version>

View File

@ -15,12 +15,18 @@ namespace Wabbajack
[Reactive]
public string Username { get; set; }
[Reactive]
public string MFAKey { get; set; }
[Reactive]
public LoginReturnMessage ReturnMessage { get; set; }
private readonly ObservableAsPropertyHelper<bool> _loginEnabled;
public bool LoginEnabled => _loginEnabled.Value;
private readonly ObservableAsPropertyHelper<bool> _mfaVisible;
public bool MFAVisible => _mfaVisible.Value;
private readonly INeedsLoginCredentials _downloader;
public CredentialsLoginVM(INeedsLoginCredentials downloader)
@ -31,6 +37,10 @@ namespace Wabbajack
.Select(IsValidAddress)
.ToGuiProperty(this,
nameof(LoginEnabled));
_mfaVisible = this.WhenAny(x => x.ReturnMessage)
.Select(x => x.ReturnCode == LoginReturnCode.NeedsMFA)
.ToGuiProperty(this, nameof(MFAVisible));
}
public void Login(SecureString password)
@ -39,17 +49,17 @@ namespace Wabbajack
{
if (password == null || password.Length == 0)
{
ReturnMessage = new LoginReturnMessage("You need to input a password!", true);
ReturnMessage = new LoginReturnMessage("You need to input a password!", LoginReturnCode.BadInput);
return;
}
ReturnMessage = _downloader.LoginWithCredentials(Username, password);
ReturnMessage = _downloader.LoginWithCredentials(Username, password, string.IsNullOrWhiteSpace(MFAKey) ? null : MFAKey);
password.Clear();
}
catch (Exception e)
{
Utils.Error(e, "Exception while trying to login");
ReturnMessage = new LoginReturnMessage($"Unhandled exception: {e.Message}", true);
ReturnMessage = new LoginReturnMessage($"Unhandled exception: {e.Message}", LoginReturnCode.InternalError);
}
}

View File

@ -11,10 +11,11 @@
d:DesignHeight="450" d:DesignWidth="800">
<Grid Margin="16">
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition Height="40"/>
<RowDefinition Height="60"/>
<RowDefinition Height="40"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="40"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
@ -27,12 +28,15 @@
<TextBox FontSize="20" x:Name="Username" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2"/>
<TextBlock FontSize="20" Grid.Row="1" Grid.Column="0" Margin="0 16 8 0">Password:</TextBlock>
<PasswordBox Margin="0 16 0 -8" FontSize="20" x:Name="Password" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"/>
<PasswordBox Margin="0 16 0 8" FontSize="20" x:Name="Password" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"/>
<Button Margin="8 8 0 0" x:Name="LoginButton" Grid.Row="2" Grid.Column="3" Click="LoginButton_OnClick">
<TextBlock FontSize="20" Grid.Row="2" Grid.Column="0" Margin="0 16 8 0" x:Name="MFAText">MFA Key:</TextBlock>
<TextBox FontSize="20" x:Name="MFA" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2"/>
<Button Margin="8 8 0 0" x:Name="LoginButton" Grid.Row="3" Grid.Column="3" Click="LoginButton_OnClick">
<TextBlock FontSize="14">Login</TextBlock>
</Button>
<TextBlock x:Name="Message" FontSize="20" Margin="0 16 0 0" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3"/>
<TextBlock x:Name="Message" FontSize="20" Margin="0 16 0 0" Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="3" TextWrapping="Wrap"/>
</Grid>
</rxui:ReactiveUserControl>

View File

@ -24,6 +24,12 @@ namespace Wabbajack
.DisposeWith(disposable);
this.Bind(ViewModel, x => x.LoginEnabled, x => x.LoginButton.IsEnabled)
.DisposeWith(disposable);
this.Bind(ViewModel, x => x.MFAKey, x => x.MFA.Text)
.DisposeWith(disposable);
this.OneWayBind(ViewModel, x => x.MFAVisible, x => x.MFA.Visibility)
.DisposeWith(disposable);
this.OneWayBind(ViewModel, x => x.MFAVisible, x => x.MFAText.Visibility)
.DisposeWith(disposable);
this.OneWayBind(ViewModel, x => x.ReturnMessage.Message, x => x.Message.Text)
.DisposeWith(disposable);
});