From 5008e1daa88d0de726472e1bec0b861b92ac5857 Mon Sep 17 00:00:00 2001 From: Matt Portune <59324545+mportune-bw@users.noreply.github.com> Date: Thu, 10 Mar 2022 09:02:01 -0500 Subject: [PATCH] fixed issues with logging out inactive accounts (#1836) --- src/App/Utilities/AppHelpers.cs | 45 +++++++++----------------- src/Core/Abstractions/IStateService.cs | 4 +-- src/Core/Services/StateService.cs | 40 +++++++++++------------ 3 files changed, 37 insertions(+), 52 deletions(-) diff --git a/src/App/Utilities/AppHelpers.cs b/src/App/Utilities/AppHelpers.cs index 18ee52aac..be90e364a 100644 --- a/src/App/Utilities/AppHelpers.cs +++ b/src/App/Utilities/AppHelpers.cs @@ -502,41 +502,25 @@ namespace Bit.App.Utilities public static async Task LogOutAsync(string userId, bool userInitiated = false) { - var tokenService = ServiceContainer.Resolve("tokenService"); - var cryptoService = ServiceContainer.Resolve("cryptoService"); - var settingsService = ServiceContainer.Resolve("settingsService"); - var cipherService = ServiceContainer.Resolve("cipherService"); - var folderService = ServiceContainer.Resolve("folderService"); - var collectionService = ServiceContainer.Resolve("collectionService"); - var passwordGenerationService = ServiceContainer.Resolve( - "passwordGenerationService"); - var vaultTimeoutService = ServiceContainer.Resolve("vaultTimeoutService"); var stateService = ServiceContainer.Resolve("stateService"); - var deviceActionService = ServiceContainer.Resolve("deviceActionService"); - var policyService = ServiceContainer.Resolve("policyService"); - var searchService = ServiceContainer.Resolve("searchService"); + var vaultTimeoutService = ServiceContainer.Resolve("vaultTimeoutService"); var isActiveAccount = await stateService.IsActiveAccountAsync(userId); + var isAccountRemoval = await vaultTimeoutService.IsLoggedOutByTimeoutAsync(userId) || + await vaultTimeoutService.ShouldLogOutByTimeoutAsync(userId); + if (userId == null) { userId = await stateService.GetActiveUserIdAsync(); } - await Task.WhenAll( - cipherService.ClearAsync(userId), - folderService.ClearAsync(userId), - collectionService.ClearAsync(userId), - passwordGenerationService.ClearAsync(userId), - deviceActionService.ClearCacheAsync(), - tokenService.ClearTokenAsync(userId), - cryptoService.ClearKeysAsync(userId), - settingsService.ClearAsync(userId), - vaultTimeoutService.ClearAsync(userId), - policyService.ClearAsync(userId), - stateService.LogoutAccountAsync(userId, userInitiated)); + await stateService.LogoutAccountAsync(userId, userInitiated); - searchService.ClearIndex(); + if (isActiveAccount) + { + await ClearServiceCacheAsync(); + } if (!userInitiated) { @@ -558,8 +542,7 @@ namespace Bit.App.Utilities if (!isActiveAccount) { var platformUtilsService = ServiceContainer.Resolve("platformUtilsService"); - if (await vaultTimeoutService.IsLoggedOutByTimeoutAsync(userId) || - await vaultTimeoutService.ShouldLogOutByTimeoutAsync()) + if (isAccountRemoval) { platformUtilsService.ShowToast("info", null, AppResources.AccountRemovedSuccessfully); return; @@ -571,6 +554,12 @@ namespace Bit.App.Utilities public static async Task OnAccountSwitchAsync() { var environmentService = ServiceContainer.Resolve("environmentService"); + await environmentService.SetUrlsFromStorageAsync(); + await ClearServiceCacheAsync(); + } + + public static async Task ClearServiceCacheAsync() + { var tokenService = ServiceContainer.Resolve("tokenService"); var cryptoService = ServiceContainer.Resolve("cryptoService"); var settingsService = ServiceContainer.Resolve("settingsService"); @@ -584,8 +573,6 @@ namespace Bit.App.Utilities var policyService = ServiceContainer.Resolve("policyService"); var searchService = ServiceContainer.Resolve("searchService"); - await environmentService.SetUrlsFromStorageAsync(); - await Task.WhenAll( cipherService.ClearCacheAsync(), deviceActionService.ClearCacheAsync()); diff --git a/src/Core/Abstractions/IStateService.cs b/src/Core/Abstractions/IStateService.cs index e354269fa..8eac4804f 100644 --- a/src/Core/Abstractions/IStateService.cs +++ b/src/Core/Abstractions/IStateService.cs @@ -63,8 +63,8 @@ namespace Bit.Core.Abstractions Task SetVaultTimeoutAsync(int? value, string userId = null); Task GetVaultTimeoutActionAsync(string userId = null); Task SetVaultTimeoutActionAsync(VaultTimeoutAction? value, string userId = null); - Task GetLastFileCacheClearAsync(string userId = null); - Task SetLastFileCacheClearAsync(DateTime? value, string userId = null); + Task GetLastFileCacheClearAsync(); + Task SetLastFileCacheClearAsync(DateTime? value); Task GetPreviousPageInfoAsync(string userId = null); Task SetPreviousPageInfoAsync(PreviousPageInfo value, string userId = null); Task GetInvalidUnlockAttemptsAsync(string userId = null); diff --git a/src/Core/Services/StateService.cs b/src/Core/Services/StateService.cs index ae64bee8a..131ddb7d4 100644 --- a/src/Core/Services/StateService.cs +++ b/src/Core/Services/StateService.cs @@ -48,7 +48,6 @@ namespace Bit.Core.Services { return true; } - await CheckStateAsync(); return userId == await GetActiveUserIdAsync(); } @@ -160,8 +159,9 @@ namespace Bit.Core.Services await CheckStateAsync(); await RemoveAccountAsync(userId, userInitiated); - // If user initiated logout (not vault timeout) find the next user to make active, if any - if (userInitiated && _state?.Accounts != null) + // If user initiated logout (not vault timeout) and ActiveUserId is null after account removal, find the + // next user to make active, if any + if (userInitiated && _state?.ActiveUserId == null && _state?.Accounts != null) { foreach (var account in _state.Accounts) { @@ -534,20 +534,18 @@ namespace Bit.Core.Services await SaveAccountAsync(account, reconciledOptions); } - public async Task GetLastFileCacheClearAsync(string userId = null) + public async Task GetLastFileCacheClearAsync() { - var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId }, - await GetDefaultStorageOptionsAsync()); + var options = await GetDefaultStorageOptionsAsync(); var key = Constants.LastFileCacheClearKey; - return await GetValueAsync(key, reconciledOptions); + return await GetValueAsync(key, options); } - public async Task SetLastFileCacheClearAsync(DateTime? value, string userId = null) + public async Task SetLastFileCacheClearAsync(DateTime? value) { - var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId }, - await GetDefaultStorageOptionsAsync()); + var options = await GetDefaultStorageOptionsAsync(); var key = Constants.LastFileCacheClearKey; - await SetValueAsync(key, value, reconciledOptions); + await SetValueAsync(key, value, options); } public async Task GetPreviousPageInfoAsync(string userId = null) @@ -1204,6 +1202,11 @@ namespace Bit.Core.Services private async Task SetValueGloballyAsync(Func keyPrefix, T value, StorageOptions options) { + if (value == null) + { + // don't remove values globally + return; + } await CheckStateAsync(); if (_state?.Accounts == null) { @@ -1246,14 +1249,11 @@ namespace Bit.Core.Services } // Storage - _state = await GetStateFromStorageAsync(); - if (_state?.Accounts?.ContainsKey(options.UserId) ?? false) + var state = await GetStateFromStorageAsync(); + if (state?.Accounts?.ContainsKey(options.UserId) ?? false) { - if (_state.Accounts[options.UserId].VolatileData == null) - { - _state.Accounts[options.UserId].VolatileData = new Account.AccountVolatileData(); - } - return _state.Accounts[options.UserId]; + state.Accounts[options.UserId].VolatileData = new Account.AccountVolatileData(); + return state.Accounts[options.UserId]; } return null; @@ -1321,8 +1321,7 @@ namespace Bit.Core.Services { _state.Accounts[userId].Tokens.AccessToken = null; _state.Accounts[userId].Tokens.RefreshToken = null; - _state.Accounts[userId].VolatileData.Key = null; - _state.Accounts[userId].VolatileData.BiometricLocked = null; + _state.Accounts[userId].VolatileData = null; } } if (userInitiated && _state?.ActiveUserId == userId) @@ -1366,7 +1365,6 @@ namespace Bit.Core.Services await SetOrgKeysEncryptedAsync(null, userId); await SetPrivateKeyEncryptedAsync(null, userId); await SetLastActiveTimeAsync(null, userId); - await SetLastFileCacheClearAsync(null, userId); await SetPreviousPageInfoAsync(null, userId); await SetInvalidUnlockAttemptsAsync(null, userId); await SetLocalDataAsync(null, userId);