mirror of
https://github.com/bitwarden/android.git
synced 2024-12-28 20:08:43 +03:00
156 lines
5.9 KiB
C#
156 lines
5.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
using Bit.App.Abstractions;
|
|
using Bit.App.Pages;
|
|
using Bit.App.Pages.Accounts;
|
|
using Bit.Core.Abstractions;
|
|
using Bit.Core.Enums;
|
|
using Bit.Core.Utilities;
|
|
using Xamarin.Forms;
|
|
|
|
namespace Bit.App.Utilities
|
|
{
|
|
public interface IVerificationActionsFlowHelper
|
|
{
|
|
IVerificationActionsFlowHelper Configure(VerificationFlowAction action,
|
|
IActionFlowParmeters parameters = null,
|
|
string verificatioCodeMainActionText = null,
|
|
bool isVerificationCodeMainActionStyleDanger = false);
|
|
IActionFlowParmeters GetParameters();
|
|
Task ValidateAndExecuteAsync();
|
|
Task ExecuteAsync(IActionFlowParmeters parameters);
|
|
}
|
|
|
|
public interface IActionFlowParmeters
|
|
{
|
|
VerificationType VerificationType { get; set; }
|
|
|
|
string Secret { get; set; }
|
|
}
|
|
|
|
public class DefaultActionFlowParameters : IActionFlowParmeters
|
|
{
|
|
public VerificationType VerificationType { get; set; }
|
|
|
|
public string Secret { get; set; }
|
|
}
|
|
|
|
public interface IActionFlowExecutioner
|
|
{
|
|
Task Execute(IActionFlowParmeters parameters);
|
|
}
|
|
|
|
public enum VerificationFlowAction
|
|
{
|
|
ExportVault,
|
|
DeleteAccount
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifies and execute actions on the corresponding order.
|
|
///
|
|
/// Use: From the caller
|
|
/// - Configure it on <see cref="Configure(VerificationFlowAction, IActionFlowParmeters)"/>
|
|
/// - Call <see cref="ValidateAndExecuteAsync"/>
|
|
///
|
|
/// For every <see cref="VerificationFlowAction"/> we need an implementation of <see cref="IActionFlowExecutioner"/>
|
|
/// and it to be configured in the inner dictionary.
|
|
/// Also, inherit from <see cref="DefaultActionFlowParameters"/> if more custom parameters are needed for the executioner.
|
|
/// </summary>
|
|
public class VerificationActionsFlowHelper : IVerificationActionsFlowHelper
|
|
{
|
|
private readonly IKeyConnectorService _keyConnectorService;
|
|
private readonly IPasswordRepromptService _passwordRepromptService;
|
|
private readonly ICryptoService _cryptoService;
|
|
|
|
private VerificationFlowAction? _action;
|
|
private IActionFlowParmeters _parameters;
|
|
private string _verificationCodeMainActionText;
|
|
private bool _isVerificationCodeMainActionStyleDanger;
|
|
|
|
private readonly Dictionary<VerificationFlowAction, IActionFlowExecutioner> _actionExecutionerDictionary = new Dictionary<VerificationFlowAction, IActionFlowExecutioner>();
|
|
|
|
public VerificationActionsFlowHelper(IKeyConnectorService keyConnectorService,
|
|
IPasswordRepromptService passwordRepromptService,
|
|
ICryptoService cryptoService)
|
|
{
|
|
_keyConnectorService = keyConnectorService;
|
|
_passwordRepromptService = passwordRepromptService;
|
|
_cryptoService = cryptoService;
|
|
|
|
_actionExecutionerDictionary.Add(VerificationFlowAction.DeleteAccount, ServiceContainer.Resolve<IDeleteAccountActionFlowExecutioner>("deleteAccountActionFlowExecutioner"));
|
|
}
|
|
|
|
public IVerificationActionsFlowHelper Configure(VerificationFlowAction action,
|
|
IActionFlowParmeters parameters = null,
|
|
string verificationCodeMainActionText = null,
|
|
bool isVerificationCodeMainActionStyleDanger = false)
|
|
{
|
|
_action = action;
|
|
_parameters = parameters;
|
|
_verificationCodeMainActionText = verificationCodeMainActionText;
|
|
_isVerificationCodeMainActionStyleDanger = isVerificationCodeMainActionStyleDanger;
|
|
|
|
return this;
|
|
}
|
|
|
|
public IActionFlowParmeters GetParameters()
|
|
{
|
|
if (_parameters is null)
|
|
{
|
|
_parameters = new DefaultActionFlowParameters();
|
|
}
|
|
|
|
return _parameters;
|
|
}
|
|
|
|
public async Task ValidateAndExecuteAsync()
|
|
{
|
|
var verificationType = await _keyConnectorService.GetUsesKeyConnector()
|
|
? VerificationType.OTP
|
|
: VerificationType.MasterPassword;
|
|
|
|
switch (verificationType)
|
|
{
|
|
case VerificationType.MasterPassword:
|
|
var (password, valid) = await _passwordRepromptService.ShowPasswordPromptAndGetItAsync();
|
|
if (!valid)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var parameters = GetParameters();
|
|
parameters.Secret = await _cryptoService.HashPasswordAsync(password, null);
|
|
parameters.VerificationType = VerificationType.MasterPassword;
|
|
await ExecuteAsync(parameters);
|
|
break;
|
|
case VerificationType.OTP:
|
|
await Application.Current.MainPage.Navigation.PushModalAsync(new NavigationPage(
|
|
new VerificationCodePage(_verificationCodeMainActionText, _isVerificationCodeMainActionStyleDanger)));
|
|
break;
|
|
default:
|
|
throw new NotImplementedException($"There is no implementation for {verificationType}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Executes the action with the given parameters after we have gotten the verification secret
|
|
/// </summary>
|
|
public async Task ExecuteAsync(IActionFlowParmeters parameters)
|
|
{
|
|
if (!_action.HasValue)
|
|
{
|
|
// this should never happen
|
|
throw new InvalidOperationException("A problem occurred while getting the action value after validation");
|
|
}
|
|
|
|
if (!_actionExecutionerDictionary.TryGetValue(_action.Value, out var executioner))
|
|
{
|
|
throw new InvalidOperationException($"There is no executioner for {_action}");
|
|
}
|
|
|
|
await executioner.Execute(GetParameters());
|
|
}
|
|
}
|
|
}
|