143 lines
3.6 KiB
C#
143 lines
3.6 KiB
C#
using Avalonia;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Markup.Xaml;
|
|
using System.Threading.Tasks;
|
|
using ReactiveUI;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Avalonia.Data;
|
|
|
|
namespace LibationAvalonia.Dialogs.Login
|
|
{
|
|
public partial class MfaDialog : DialogWindow
|
|
{
|
|
public string SelectedName { get; private set; }
|
|
public string SelectedValue { get; private set; }
|
|
private RbValues Values { get; } = new();
|
|
|
|
public MfaDialog()
|
|
{
|
|
InitializeComponent();
|
|
|
|
if (Design.IsDesignMode)
|
|
{
|
|
var mfaConfig = new AudibleApi.MfaConfig { Title = "My title" };
|
|
mfaConfig.Buttons.Add(new() { Text = "Enter the OTP from the authenticator app", Name = "otpDeviceContext", Value = "aAbBcC=, TOTP" });
|
|
mfaConfig.Buttons.Add(new() { Text = "Send an SMS to my number ending with 123", Name = "otpDeviceContext", Value = "dDeEfE=, SMS" });
|
|
mfaConfig.Buttons.Add(new() { Text = "Call me on my number ending with 123", Name = "otpDeviceContext", Value = "dDeEfE=, VOICE" });
|
|
|
|
loadRadioButtons(mfaConfig);
|
|
}
|
|
}
|
|
|
|
public MfaDialog(AudibleApi.MfaConfig mfaConfig) : this()
|
|
{
|
|
loadRadioButtons(mfaConfig);
|
|
}
|
|
|
|
private void loadRadioButtons(AudibleApi.MfaConfig mfaConfig)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(mfaConfig.Title))
|
|
Title = mfaConfig.Title;
|
|
|
|
rbStackPanel = this.Find<StackPanel>(nameof(rbStackPanel));
|
|
|
|
foreach (var conf in mfaConfig.Buttons)
|
|
{
|
|
var rb = new RbValue(conf);
|
|
Values.AddButton(rb);
|
|
|
|
RadioButton radioButton = new()
|
|
{
|
|
Content = new TextBlock { Text = conf.Text },
|
|
Margin = new Thickness(0, 10, 0, 0),
|
|
};
|
|
|
|
radioButton.Bind(
|
|
RadioButton.IsCheckedProperty,
|
|
new Binding
|
|
{
|
|
Source = rb,
|
|
Path = nameof(rb.IsChecked)
|
|
});
|
|
|
|
rbStackPanel.Children.Add(radioButton);
|
|
}
|
|
}
|
|
|
|
private void InitializeComponent()
|
|
{
|
|
AvaloniaXamlLoader.Load(this);
|
|
}
|
|
|
|
protected override async Task SaveAndCloseAsync()
|
|
{
|
|
var selected = Values.CheckedButton;
|
|
|
|
Serilog.Log.Logger.Information("Submit button clicked: {@DebugInfo}", new
|
|
{
|
|
text = selected?.Text,
|
|
name = selected?.Name,
|
|
value = selected?.Value
|
|
});
|
|
if (selected is null)
|
|
{
|
|
await MessageBox.Show("No MFA option selected", "None selected", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
SelectedName = selected.Name;
|
|
SelectedValue = selected.Value;
|
|
|
|
await base.SaveAndCloseAsync();
|
|
}
|
|
|
|
public async void Submit_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
|
=> await SaveAndCloseAsync();
|
|
|
|
|
|
private class RbValue : ViewModels.ViewModelBase
|
|
{
|
|
private bool _isChecked;
|
|
public bool IsChecked
|
|
{
|
|
get => _isChecked;
|
|
set => this.RaiseAndSetIfChanged(ref _isChecked, value);
|
|
}
|
|
public AudibleApi.MfaConfigButton MfaConfigButton { get; }
|
|
public RbValue(AudibleApi.MfaConfigButton mfaConfig)
|
|
{
|
|
MfaConfigButton = mfaConfig;
|
|
}
|
|
}
|
|
|
|
private class RbValues
|
|
{
|
|
private List<RbValue> ButtonValues { get; } = new();
|
|
|
|
public AudibleApi.MfaConfigButton CheckedButton => ButtonValues.SingleOrDefault(rb => rb.IsChecked)?.MfaConfigButton;
|
|
|
|
public void AddButton(RbValue rbValue)
|
|
{
|
|
if (ButtonValues.Contains(rbValue))
|
|
return;
|
|
|
|
rbValue.PropertyChanged += RbValue_PropertyChanged;
|
|
rbValue.IsChecked = ButtonValues.Count == 0;
|
|
ButtonValues.Add(rbValue);
|
|
}
|
|
|
|
private void RbValue_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
|
{
|
|
var button = sender as RbValue;
|
|
|
|
if (button.IsChecked)
|
|
{
|
|
foreach (var rb in ButtonValues.Where(rb => rb != button))
|
|
rb.IsChecked = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|