From 4e7ceaf5b5f91a636fb59592f166b5b71fe6e2df Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Mon, 24 Jan 2022 13:25:46 -0300 Subject: [PATCH] Account Deletion on SSO with CME (#1721) * WIP Added Verification Code page and a verification flow helper to coordinate things * Improved Verification Code page verification flow helper and fix some issues, also added flag ApiService to choose whether to logout on Unanuthorized * Improved Verification Code page UI/UX verification flow helper and fix some issues and made some cleanups * Fix spelling --- src/Android/MainApplication.cs | 16 ++ src/App/App.csproj | 2 + .../Pages/Accounts/DeleteAccountViewModel.cs | 63 +++++-- .../Pages/Accounts/VerificationCodePage.xaml | 99 ++++++++++ .../Accounts/VerificationCodePage.xaml.cs | 49 +++++ .../Accounts/VerificationCodeViewModel.cs | 176 ++++++++++++++++++ src/App/Resources/AppResources.Designer.cs | 36 ++++ src/App/Resources/AppResources.resx | 18 ++ .../VerificationActionsFlowHelper.cs | 147 +++++++++++++++ src/Core/Abstractions/IApiService.cs | 2 +- src/Core/Services/ApiService.cs | 22 ++- src/iOS.Core/Utilities/iOSCoreHelpers.cs | 16 ++ 12 files changed, 622 insertions(+), 24 deletions(-) create mode 100644 src/App/Pages/Accounts/VerificationCodePage.xaml create mode 100644 src/App/Pages/Accounts/VerificationCodePage.xaml.cs create mode 100644 src/App/Pages/Accounts/VerificationCodeViewModel.cs create mode 100644 src/App/Utilities/VerificationActionsFlowHelper.cs diff --git a/src/Android/MainApplication.cs b/src/Android/MainApplication.cs index b2854aebe..3e58b4cab 100644 --- a/src/Android/MainApplication.cs +++ b/src/Android/MainApplication.cs @@ -18,6 +18,8 @@ using Plugin.Fingerprint; using Xamarin.Android.Net; using System.Net.Http; using System.Net; +using Bit.App.Utilities; +using Bit.App.Pages; #if !FDROID using Android.Gms.Security; #endif @@ -45,6 +47,20 @@ namespace Bit.Droid var deviceActionService = ServiceContainer.Resolve("deviceActionService"); ServiceContainer.Init(deviceActionService.DeviceUserAgent, Constants.ClearCiphersCacheKey, Constants.AndroidAllClearCipherCacheKeys); + + // TODO: Update when https://github.com/bitwarden/mobile/pull/1662 gets merged + var deleteAccountActionFlowExecutioner = new DeleteAccountActionFlowExecutioner( + ServiceContainer.Resolve("apiService"), + ServiceContainer.Resolve("messagingService"), + ServiceContainer.Resolve("cryptoService"), + ServiceContainer.Resolve("platformUtilsService"), + ServiceContainer.Resolve("deviceActionService")); + ServiceContainer.Register("deleteAccountActionFlowExecutioner", deleteAccountActionFlowExecutioner); + + var verificationActionsFlowHelper = new VerificationActionsFlowHelper( + ServiceContainer.Resolve("keyConnectorService"), + ServiceContainer.Resolve("passwordRepromptService")); + ServiceContainer.Register("verificationActionsFlowHelper", verificationActionsFlowHelper); } #if !FDROID if (Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat) diff --git a/src/App/App.csproj b/src/App/App.csproj index c9ab94f02..b0916f2ed 100644 --- a/src/App/App.csproj +++ b/src/App/App.csproj @@ -20,6 +20,7 @@ + @@ -414,5 +415,6 @@ + diff --git a/src/App/Pages/Accounts/DeleteAccountViewModel.cs b/src/App/Pages/Accounts/DeleteAccountViewModel.cs index 3fa0dd3e1..53c195e58 100644 --- a/src/App/Pages/Accounts/DeleteAccountViewModel.cs +++ b/src/App/Pages/Accounts/DeleteAccountViewModel.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using Bit.App.Abstractions; using Bit.App.Resources; +using Bit.App.Utilities; using Bit.Core.Abstractions; using Bit.Core.Exceptions; using Bit.Core.Utilities; @@ -12,21 +13,13 @@ namespace Bit.App.Pages { public class DeleteAccountViewModel : BaseViewModel { - readonly IApiService _apiService; - readonly IPasswordRepromptService _passwordRepromptService; - readonly IMessagingService _messagingService; - readonly ICryptoService _cryptoService; readonly IPlatformUtilsService _platformUtilsService; - readonly IDeviceActionService _deviceActionService; + readonly IVerificationActionsFlowHelper _verificationActionsFlowHelper; public DeleteAccountViewModel() { - _apiService = ServiceContainer.Resolve("apiService"); - _passwordRepromptService = ServiceContainer.Resolve("passwordRepromptService"); - _messagingService = ServiceContainer.Resolve("messagingService"); - _cryptoService = ServiceContainer.Resolve("cryptoService"); _platformUtilsService = ServiceContainer.Resolve("platformUtilsService"); - _deviceActionService = ServiceContainer.Resolve("deviceActionService"); + _verificationActionsFlowHelper = ServiceContainer.Resolve("verificationActionsFlowHelper"); PageTitle = AppResources.DeleteAccount; } @@ -42,15 +35,53 @@ namespace Bit.App.Pages return; } - var (password, valid) = await _passwordRepromptService.ShowPasswordPromptAndGetItAsync(); - if (!valid) - { - return; - } + await _verificationActionsFlowHelper + .Configure(VerificationFlowAction.DeleteAccount, + null, + AppResources.DeleteAccount, + true) + .ValidateAndExecuteAsync(); + } + catch (System.Exception ex) + { +#if !FDROID + Crashes.TrackError(ex); +#endif + await _platformUtilsService.ShowDialogAsync(AppResources.AnErrorHasOccurred); + } + } + } + public interface IDeleteAccountActionFlowExecutioner : IActionFlowExecutioner { } + + public class DeleteAccountActionFlowExecutioner : IDeleteAccountActionFlowExecutioner + { + readonly IApiService _apiService; + readonly IMessagingService _messagingService; + readonly ICryptoService _cryptoService; + readonly IPlatformUtilsService _platformUtilsService; + readonly IDeviceActionService _deviceActionService; + + public DeleteAccountActionFlowExecutioner(IApiService apiService, + IMessagingService messagingService, + ICryptoService cryptoService, + IPlatformUtilsService platformUtilsService, + IDeviceActionService deviceActionService) + { + _apiService = apiService; + _messagingService = messagingService; + _cryptoService = cryptoService; + _platformUtilsService = platformUtilsService; + _deviceActionService = deviceActionService; + } + + public async Task Execute(IActionFlowParmeters parameters) + { + try + { await _deviceActionService.ShowLoadingAsync(AppResources.DeletingYourAccount); - var masterPasswordHashKey = await _cryptoService.HashPasswordAsync(password, null); + var masterPasswordHashKey = await _cryptoService.HashPasswordAsync(parameters.Secret, null); await _apiService.DeleteAccountAsync(new Core.Models.Request.DeleteAccountRequest { MasterPasswordHash = masterPasswordHashKey diff --git a/src/App/Pages/Accounts/VerificationCodePage.xaml b/src/App/Pages/Accounts/VerificationCodePage.xaml new file mode 100644 index 000000000..3fe2b643e --- /dev/null +++ b/src/App/Pages/Accounts/VerificationCodePage.xaml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + +