fixed issues with logging out inactive accounts (#1836)

This commit is contained in:
Matt Portune 2022-03-10 09:02:01 -05:00 committed by GitHub
parent ad7c656868
commit 5008e1daa8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 52 deletions

View file

@ -502,41 +502,25 @@ namespace Bit.App.Utilities
public static async Task LogOutAsync(string userId, bool userInitiated = false) public static async Task LogOutAsync(string userId, bool userInitiated = false)
{ {
var tokenService = ServiceContainer.Resolve<ITokenService>("tokenService");
var cryptoService = ServiceContainer.Resolve<ICryptoService>("cryptoService");
var settingsService = ServiceContainer.Resolve<ISettingsService>("settingsService");
var cipherService = ServiceContainer.Resolve<ICipherService>("cipherService");
var folderService = ServiceContainer.Resolve<IFolderService>("folderService");
var collectionService = ServiceContainer.Resolve<ICollectionService>("collectionService");
var passwordGenerationService = ServiceContainer.Resolve<IPasswordGenerationService>(
"passwordGenerationService");
var vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
var stateService = ServiceContainer.Resolve<IStateService>("stateService"); var stateService = ServiceContainer.Resolve<IStateService>("stateService");
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService"); var vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
var policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
var searchService = ServiceContainer.Resolve<ISearchService>("searchService");
var isActiveAccount = await stateService.IsActiveAccountAsync(userId); var isActiveAccount = await stateService.IsActiveAccountAsync(userId);
var isAccountRemoval = await vaultTimeoutService.IsLoggedOutByTimeoutAsync(userId) ||
await vaultTimeoutService.ShouldLogOutByTimeoutAsync(userId);
if (userId == null) if (userId == null)
{ {
userId = await stateService.GetActiveUserIdAsync(); userId = await stateService.GetActiveUserIdAsync();
} }
await Task.WhenAll( await stateService.LogoutAccountAsync(userId, userInitiated);
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));
searchService.ClearIndex(); if (isActiveAccount)
{
await ClearServiceCacheAsync();
}
if (!userInitiated) if (!userInitiated)
{ {
@ -558,8 +542,7 @@ namespace Bit.App.Utilities
if (!isActiveAccount) if (!isActiveAccount)
{ {
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"); var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
if (await vaultTimeoutService.IsLoggedOutByTimeoutAsync(userId) || if (isAccountRemoval)
await vaultTimeoutService.ShouldLogOutByTimeoutAsync())
{ {
platformUtilsService.ShowToast("info", null, AppResources.AccountRemovedSuccessfully); platformUtilsService.ShowToast("info", null, AppResources.AccountRemovedSuccessfully);
return; return;
@ -571,6 +554,12 @@ namespace Bit.App.Utilities
public static async Task OnAccountSwitchAsync() public static async Task OnAccountSwitchAsync()
{ {
var environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService"); var environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
await environmentService.SetUrlsFromStorageAsync();
await ClearServiceCacheAsync();
}
public static async Task ClearServiceCacheAsync()
{
var tokenService = ServiceContainer.Resolve<ITokenService>("tokenService"); var tokenService = ServiceContainer.Resolve<ITokenService>("tokenService");
var cryptoService = ServiceContainer.Resolve<ICryptoService>("cryptoService"); var cryptoService = ServiceContainer.Resolve<ICryptoService>("cryptoService");
var settingsService = ServiceContainer.Resolve<ISettingsService>("settingsService"); var settingsService = ServiceContainer.Resolve<ISettingsService>("settingsService");
@ -584,8 +573,6 @@ namespace Bit.App.Utilities
var policyService = ServiceContainer.Resolve<IPolicyService>("policyService"); var policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
var searchService = ServiceContainer.Resolve<ISearchService>("searchService"); var searchService = ServiceContainer.Resolve<ISearchService>("searchService");
await environmentService.SetUrlsFromStorageAsync();
await Task.WhenAll( await Task.WhenAll(
cipherService.ClearCacheAsync(), cipherService.ClearCacheAsync(),
deviceActionService.ClearCacheAsync()); deviceActionService.ClearCacheAsync());

View file

@ -63,8 +63,8 @@ namespace Bit.Core.Abstractions
Task SetVaultTimeoutAsync(int? value, string userId = null); Task SetVaultTimeoutAsync(int? value, string userId = null);
Task<VaultTimeoutAction?> GetVaultTimeoutActionAsync(string userId = null); Task<VaultTimeoutAction?> GetVaultTimeoutActionAsync(string userId = null);
Task SetVaultTimeoutActionAsync(VaultTimeoutAction? value, string userId = null); Task SetVaultTimeoutActionAsync(VaultTimeoutAction? value, string userId = null);
Task<DateTime?> GetLastFileCacheClearAsync(string userId = null); Task<DateTime?> GetLastFileCacheClearAsync();
Task SetLastFileCacheClearAsync(DateTime? value, string userId = null); Task SetLastFileCacheClearAsync(DateTime? value);
Task<PreviousPageInfo> GetPreviousPageInfoAsync(string userId = null); Task<PreviousPageInfo> GetPreviousPageInfoAsync(string userId = null);
Task SetPreviousPageInfoAsync(PreviousPageInfo value, string userId = null); Task SetPreviousPageInfoAsync(PreviousPageInfo value, string userId = null);
Task<int> GetInvalidUnlockAttemptsAsync(string userId = null); Task<int> GetInvalidUnlockAttemptsAsync(string userId = null);

View file

@ -48,7 +48,6 @@ namespace Bit.Core.Services
{ {
return true; return true;
} }
await CheckStateAsync();
return userId == await GetActiveUserIdAsync(); return userId == await GetActiveUserIdAsync();
} }
@ -160,8 +159,9 @@ namespace Bit.Core.Services
await CheckStateAsync(); await CheckStateAsync();
await RemoveAccountAsync(userId, userInitiated); await RemoveAccountAsync(userId, userInitiated);
// If user initiated logout (not vault timeout) find the next user to make active, if any // If user initiated logout (not vault timeout) and ActiveUserId is null after account removal, find the
if (userInitiated && _state?.Accounts != null) // next user to make active, if any
if (userInitiated && _state?.ActiveUserId == null && _state?.Accounts != null)
{ {
foreach (var account in _state.Accounts) foreach (var account in _state.Accounts)
{ {
@ -534,20 +534,18 @@ namespace Bit.Core.Services
await SaveAccountAsync(account, reconciledOptions); await SaveAccountAsync(account, reconciledOptions);
} }
public async Task<DateTime?> GetLastFileCacheClearAsync(string userId = null) public async Task<DateTime?> GetLastFileCacheClearAsync()
{ {
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId }, var options = await GetDefaultStorageOptionsAsync();
await GetDefaultStorageOptionsAsync());
var key = Constants.LastFileCacheClearKey; var key = Constants.LastFileCacheClearKey;
return await GetValueAsync<DateTime?>(key, reconciledOptions); return await GetValueAsync<DateTime?>(key, options);
} }
public async Task SetLastFileCacheClearAsync(DateTime? value, string userId = null) public async Task SetLastFileCacheClearAsync(DateTime? value)
{ {
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId }, var options = await GetDefaultStorageOptionsAsync();
await GetDefaultStorageOptionsAsync());
var key = Constants.LastFileCacheClearKey; var key = Constants.LastFileCacheClearKey;
await SetValueAsync(key, value, reconciledOptions); await SetValueAsync(key, value, options);
} }
public async Task<PreviousPageInfo> GetPreviousPageInfoAsync(string userId = null) public async Task<PreviousPageInfo> GetPreviousPageInfoAsync(string userId = null)
@ -1204,6 +1202,11 @@ namespace Bit.Core.Services
private async Task SetValueGloballyAsync<T>(Func<string, string> keyPrefix, T value, StorageOptions options) private async Task SetValueGloballyAsync<T>(Func<string, string> keyPrefix, T value, StorageOptions options)
{ {
if (value == null)
{
// don't remove values globally
return;
}
await CheckStateAsync(); await CheckStateAsync();
if (_state?.Accounts == null) if (_state?.Accounts == null)
{ {
@ -1246,14 +1249,11 @@ namespace Bit.Core.Services
} }
// Storage // Storage
_state = await GetStateFromStorageAsync(); var state = await GetStateFromStorageAsync();
if (_state?.Accounts?.ContainsKey(options.UserId) ?? false) 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; return null;
@ -1321,8 +1321,7 @@ namespace Bit.Core.Services
{ {
_state.Accounts[userId].Tokens.AccessToken = null; _state.Accounts[userId].Tokens.AccessToken = null;
_state.Accounts[userId].Tokens.RefreshToken = null; _state.Accounts[userId].Tokens.RefreshToken = null;
_state.Accounts[userId].VolatileData.Key = null; _state.Accounts[userId].VolatileData = null;
_state.Accounts[userId].VolatileData.BiometricLocked = null;
} }
} }
if (userInitiated && _state?.ActiveUserId == userId) if (userInitiated && _state?.ActiveUserId == userId)
@ -1366,7 +1365,6 @@ namespace Bit.Core.Services
await SetOrgKeysEncryptedAsync(null, userId); await SetOrgKeysEncryptedAsync(null, userId);
await SetPrivateKeyEncryptedAsync(null, userId); await SetPrivateKeyEncryptedAsync(null, userId);
await SetLastActiveTimeAsync(null, userId); await SetLastActiveTimeAsync(null, userId);
await SetLastFileCacheClearAsync(null, userId);
await SetPreviousPageInfoAsync(null, userId); await SetPreviousPageInfoAsync(null, userId);
await SetInvalidUnlockAttemptsAsync(null, userId); await SetInvalidUnlockAttemptsAsync(null, userId);
await SetLocalDataAsync(null, userId); await SetLocalDataAsync(null, userId);