mirror of
https://github.com/bitwarden/android.git
synced 2024-12-25 18:38:27 +03:00
[SG-386] iOS Update user state when coming from background (#1952)
* SG-386 Updated active user when coming from background to the iOS app and the extension had switched users * Added iOSExtensionActiveUserIdKey to preference keys * Reorder iOS preference keys
This commit is contained in:
parent
c53a85cd50
commit
3aef86bd34
11 changed files with 79 additions and 27 deletions
|
@ -130,7 +130,7 @@ namespace Bit.Droid
|
||||||
var secureStorageService = new SecureStorageService();
|
var secureStorageService = new SecureStorageService();
|
||||||
var cryptoPrimitiveService = new CryptoPrimitiveService();
|
var cryptoPrimitiveService = new CryptoPrimitiveService();
|
||||||
var mobileStorageService = new MobileStorageService(preferencesStorage, liteDbStorage);
|
var mobileStorageService = new MobileStorageService(preferencesStorage, liteDbStorage);
|
||||||
var stateService = new StateService(mobileStorageService, secureStorageService);
|
var stateService = new StateService(mobileStorageService, secureStorageService, messagingService);
|
||||||
var stateMigrationService =
|
var stateMigrationService =
|
||||||
new StateMigrationService(liteDbStorage, preferencesStorage, secureStorageService);
|
new StateMigrationService(liteDbStorage, preferencesStorage, secureStorageService);
|
||||||
var clipboardService = new ClipboardService(stateService);
|
var clipboardService = new ClipboardService(stateService);
|
||||||
|
|
|
@ -202,6 +202,7 @@ namespace Bit.App
|
||||||
|
|
||||||
private async Task ResumedAsync()
|
private async Task ResumedAsync()
|
||||||
{
|
{
|
||||||
|
await _stateService.CheckExtensionActiveUserAndSwitchIfNeededAsync();
|
||||||
await _vaultTimeoutService.CheckVaultTimeoutAsync();
|
await _vaultTimeoutService.CheckVaultTimeoutAsync();
|
||||||
_messagingService.Send("startEventTimer");
|
_messagingService.Send("startEventTimer");
|
||||||
await UpdateThemeAsync();
|
await UpdateThemeAsync();
|
||||||
|
|
|
@ -45,23 +45,28 @@ namespace Bit.App.Controls
|
||||||
|
|
||||||
public ICommand LongPressAccountCommand { get; }
|
public ICommand LongPressAccountCommand { get; }
|
||||||
|
|
||||||
|
public bool FromIOSExtension { get; set; }
|
||||||
|
|
||||||
private async Task SelectAccountAsync(AccountViewCellViewModel item)
|
private async Task SelectAccountAsync(AccountViewCellViewModel item)
|
||||||
{
|
{
|
||||||
if (item.AccountView.IsAccount)
|
if (!item.AccountView.IsAccount)
|
||||||
{
|
{
|
||||||
|
_messagingService.Send(AccountsManagerMessageCommands.ADD_ACCOUNT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!item.AccountView.IsActive)
|
if (!item.AccountView.IsActive)
|
||||||
{
|
{
|
||||||
await _stateService.SetActiveUserAsync(item.AccountView.UserId);
|
await _stateService.SetActiveUserAsync(item.AccountView.UserId);
|
||||||
_messagingService.Send("switchedAccount");
|
_messagingService.Send(AccountsManagerMessageCommands.SWITCHED_ACCOUNT);
|
||||||
|
if (FromIOSExtension)
|
||||||
|
{
|
||||||
|
await _stateService.SaveExtensionActiveUserIdToStorageAsync(item.AccountView.UserId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (AllowActiveAccountSelection)
|
else if (AllowActiveAccountSelection)
|
||||||
{
|
{
|
||||||
_messagingService.Send("switchedAccount");
|
_messagingService.Send(AccountsManagerMessageCommands.SWITCHED_ACCOUNT);
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_messagingService.Send("addAccount");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace Bit.App.Services
|
||||||
Constants.LastBuildKey,
|
Constants.LastBuildKey,
|
||||||
Constants.ClearCiphersCacheKey,
|
Constants.ClearCiphersCacheKey,
|
||||||
Constants.BiometricIntegrityKey,
|
Constants.BiometricIntegrityKey,
|
||||||
|
Constants.iOSExtensionActiveUserIdKey,
|
||||||
Constants.iOSAutoFillClearCiphersCacheKey,
|
Constants.iOSAutoFillClearCiphersCacheKey,
|
||||||
Constants.iOSAutoFillBiometricIntegrityKey,
|
Constants.iOSAutoFillBiometricIntegrityKey,
|
||||||
Constants.iOSExtensionClearCiphersCacheKey,
|
Constants.iOSExtensionClearCiphersCacheKey,
|
||||||
|
@ -32,7 +33,7 @@ namespace Bit.App.Services
|
||||||
Constants.iOSShareExtensionClearCiphersCacheKey,
|
Constants.iOSShareExtensionClearCiphersCacheKey,
|
||||||
Constants.iOSShareExtensionBiometricIntegrityKey,
|
Constants.iOSShareExtensionBiometricIntegrityKey,
|
||||||
Constants.RememberedEmailKey,
|
Constants.RememberedEmailKey,
|
||||||
Constants.RememberedOrgIdentifierKey,
|
Constants.RememberedOrgIdentifierKey
|
||||||
};
|
};
|
||||||
|
|
||||||
public MobileStorageService(
|
public MobileStorageService(
|
||||||
|
|
|
@ -6,21 +6,11 @@ using Bit.App.Resources;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Models.Domain;
|
using Bit.Core.Models.Domain;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Utilities.AccountManagement
|
namespace Bit.App.Utilities.AccountManagement
|
||||||
{
|
{
|
||||||
public static class AccountsManagerMessageCommands
|
|
||||||
{
|
|
||||||
public const string LOCKED = "locked";
|
|
||||||
public const string LOCK_VAULT = "lockVault";
|
|
||||||
public const string LOGOUT = "logout";
|
|
||||||
public const string LOGGED_OUT = "loggedOut";
|
|
||||||
public const string ADD_ACCOUNT = "addAccount";
|
|
||||||
public const string ACCOUNT_ADDED = "accountAdded";
|
|
||||||
public const string SWITCHED_ACCOUNT = "switchedAccount";
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AccountsManager : IAccountsManager
|
public class AccountsManager : IAccountsManager
|
||||||
{
|
{
|
||||||
private readonly IBroadcasterService _broadcasterService;
|
private readonly IBroadcasterService _broadcasterService;
|
||||||
|
@ -209,7 +199,7 @@ namespace Bit.App.Utilities.AccountManagement
|
||||||
private async Task SwitchedAccountAsync()
|
private async Task SwitchedAccountAsync()
|
||||||
{
|
{
|
||||||
await AppHelpers.OnAccountSwitchAsync();
|
await AppHelpers.OnAccountSwitchAsync();
|
||||||
Device.BeginInvokeOnMainThread(async () =>
|
await Device.InvokeOnMainThreadAsync(async () =>
|
||||||
{
|
{
|
||||||
if (await _vaultTimeoutService.ShouldTimeoutAsync())
|
if (await _vaultTimeoutService.ShouldTimeoutAsync())
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace Bit.Core.Abstractions
|
||||||
Task<string> GetActiveUserIdAsync();
|
Task<string> GetActiveUserIdAsync();
|
||||||
Task<bool> IsActiveAccountAsync(string userId = null);
|
Task<bool> IsActiveAccountAsync(string userId = null);
|
||||||
Task SetActiveUserAsync(string userId);
|
Task SetActiveUserAsync(string userId);
|
||||||
|
Task CheckExtensionActiveUserAndSwitchIfNeededAsync();
|
||||||
Task<bool> IsAuthenticatedAsync(string userId = null);
|
Task<bool> IsAuthenticatedAsync(string userId = null);
|
||||||
Task<string> GetUserIdAsync(string email);
|
Task<string> GetUserIdAsync(string email);
|
||||||
Task RefreshAccountViewsAsync(bool allowAddAccountRow);
|
Task RefreshAccountViewsAsync(bool allowAddAccountRow);
|
||||||
|
@ -145,5 +146,6 @@ namespace Bit.Core.Abstractions
|
||||||
Task SetRefreshTokenAsync(string value, bool skipTokenStorage, string userId = null);
|
Task SetRefreshTokenAsync(string value, bool skipTokenStorage, string userId = null);
|
||||||
Task<string> GetTwoFactorTokenAsync(string email = null);
|
Task<string> GetTwoFactorTokenAsync(string email = null);
|
||||||
Task SetTwoFactorTokenAsync(string value, string email = null);
|
Task SetTwoFactorTokenAsync(string value, string email = null);
|
||||||
|
Task SaveExtensionActiveUserIdToStorageAsync(string userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
public static string iOSExtensionBiometricIntegrityKey = "iOSExtensionBiometricIntegrityState";
|
public static string iOSExtensionBiometricIntegrityKey = "iOSExtensionBiometricIntegrityState";
|
||||||
public static string iOSShareExtensionClearCiphersCacheKey = "iOSShareExtensionClearCiphersCache";
|
public static string iOSShareExtensionClearCiphersCacheKey = "iOSShareExtensionClearCiphersCache";
|
||||||
public static string iOSShareExtensionBiometricIntegrityKey = "iOSShareExtensionBiometricIntegrityState";
|
public static string iOSShareExtensionBiometricIntegrityKey = "iOSShareExtensionBiometricIntegrityState";
|
||||||
|
public static string iOSExtensionActiveUserIdKey = "iOSExtensionActiveUserId";
|
||||||
public static string EventCollectionKey = "eventCollection";
|
public static string EventCollectionKey = "eventCollection";
|
||||||
public static string RememberedEmailKey = "rememberedEmail";
|
public static string RememberedEmailKey = "rememberedEmail";
|
||||||
public static string RememberedOrgIdentifierKey = "rememberedOrgIdentifier";
|
public static string RememberedOrgIdentifierKey = "rememberedOrgIdentifier";
|
||||||
|
|
|
@ -15,16 +15,20 @@ namespace Bit.Core.Services
|
||||||
{
|
{
|
||||||
private readonly IStorageService _storageService;
|
private readonly IStorageService _storageService;
|
||||||
private readonly IStorageService _secureStorageService;
|
private readonly IStorageService _secureStorageService;
|
||||||
|
private readonly IMessagingService _messagingService;
|
||||||
|
|
||||||
private State _state;
|
private State _state;
|
||||||
private bool _migrationChecked;
|
private bool _migrationChecked;
|
||||||
|
|
||||||
public List<AccountView> AccountViews { get; set; }
|
public List<AccountView> AccountViews { get; set; }
|
||||||
|
|
||||||
public StateService(IStorageService storageService, IStorageService secureStorageService)
|
public StateService(IStorageService storageService,
|
||||||
|
IStorageService secureStorageService,
|
||||||
|
IMessagingService messagingService)
|
||||||
{
|
{
|
||||||
_storageService = storageService;
|
_storageService = storageService;
|
||||||
_secureStorageService = secureStorageService;
|
_secureStorageService = secureStorageService;
|
||||||
|
_messagingService = messagingService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetActiveUserIdAsync()
|
public async Task<string> GetActiveUserIdAsync()
|
||||||
|
@ -67,6 +71,28 @@ namespace Bit.Core.Services
|
||||||
await SetPreAuthEnvironmentUrlsAsync(await GetEnvironmentUrlsAsync());
|
await SetPreAuthEnvironmentUrlsAsync(await GetEnvironmentUrlsAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task CheckExtensionActiveUserAndSwitchIfNeededAsync()
|
||||||
|
{
|
||||||
|
var extensionUserId = await GetExtensionActiveUserIdFromStorageAsync();
|
||||||
|
if (string.IsNullOrEmpty(extensionUserId))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_state?.ActiveUserId == extensionUserId)
|
||||||
|
{
|
||||||
|
// Clear the value in case the user changes the active user from the app
|
||||||
|
// so if that happens and the user sends the app to background and comes back
|
||||||
|
// the user is not changed again.
|
||||||
|
await SaveExtensionActiveUserIdToStorageAsync(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await SetActiveUserAsync(extensionUserId);
|
||||||
|
await SaveExtensionActiveUserIdToStorageAsync(null);
|
||||||
|
_messagingService.Send(AccountsManagerMessageCommands.SWITCHED_ACCOUNT);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<bool> IsAuthenticatedAsync(string userId = null)
|
public async Task<bool> IsAuthenticatedAsync(string userId = null)
|
||||||
{
|
{
|
||||||
return await GetAccessTokenAsync(userId) != null;
|
return await GetAccessTokenAsync(userId) != null;
|
||||||
|
@ -1510,6 +1536,16 @@ namespace Bit.Core.Services
|
||||||
await _storageService.SaveAsync(Constants.StateKey, state);
|
await _storageService.SaveAsync(Constants.StateKey, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<string> GetExtensionActiveUserIdFromStorageAsync()
|
||||||
|
{
|
||||||
|
return await _storageService.GetAsync<string>(Constants.iOSExtensionActiveUserIdKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SaveExtensionActiveUserIdToStorageAsync(string userId)
|
||||||
|
{
|
||||||
|
await _storageService.SaveAsync(Constants.iOSExtensionActiveUserIdKey, userId);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task CheckStateAsync()
|
private async Task CheckStateAsync()
|
||||||
{
|
{
|
||||||
if (!_migrationChecked)
|
if (!_migrationChecked)
|
||||||
|
|
13
src/Core/Utilities/AccountsManagerMessageCommands.cs
Normal file
13
src/Core/Utilities/AccountsManagerMessageCommands.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
namespace Bit.Core.Utilities
|
||||||
|
{
|
||||||
|
public static class AccountsManagerMessageCommands
|
||||||
|
{
|
||||||
|
public const string LOCKED = "locked";
|
||||||
|
public const string LOCK_VAULT = "lockVault";
|
||||||
|
public const string LOGOUT = "logout";
|
||||||
|
public const string LOGGED_OUT = "loggedOut";
|
||||||
|
public const string ADD_ACCOUNT = "addAccount";
|
||||||
|
public const string ACCOUNT_ADDED = "accountAdded";
|
||||||
|
public const string SWITCHED_ACCOUNT = "switchedAccount";
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,7 +35,10 @@ namespace Bit.iOS.Core.Utilities
|
||||||
LongPressAccountEnabled = false
|
LongPressAccountEnabled = false
|
||||||
};
|
};
|
||||||
|
|
||||||
var vm = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger);
|
var vm = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger)
|
||||||
|
{
|
||||||
|
FromIOSExtension = true
|
||||||
|
};
|
||||||
overlay.BindingContext = vm;
|
overlay.BindingContext = vm;
|
||||||
|
|
||||||
var renderer = Platform.CreateRenderer(overlay.Content);
|
var renderer = Platform.CreateRenderer(overlay.Content);
|
||||||
|
|
|
@ -59,7 +59,7 @@ namespace Bit.iOS.Core.Utilities
|
||||||
() => ServiceContainer.Resolve<IAppIdService>("appIdService").GetAppIdAsync());
|
() => ServiceContainer.Resolve<IAppIdService>("appIdService").GetAppIdAsync());
|
||||||
var cryptoPrimitiveService = new CryptoPrimitiveService();
|
var cryptoPrimitiveService = new CryptoPrimitiveService();
|
||||||
var mobileStorageService = new MobileStorageService(preferencesStorage, liteDbStorage);
|
var mobileStorageService = new MobileStorageService(preferencesStorage, liteDbStorage);
|
||||||
var stateService = new StateService(mobileStorageService, secureStorageService);
|
var stateService = new StateService(mobileStorageService, secureStorageService, messagingService);
|
||||||
var stateMigrationService =
|
var stateMigrationService =
|
||||||
new StateMigrationService(liteDbStorage, preferencesStorage, secureStorageService);
|
new StateMigrationService(liteDbStorage, preferencesStorage, secureStorageService);
|
||||||
var deviceActionService = new DeviceActionService(stateService, messagingService);
|
var deviceActionService = new DeviceActionService(stateService, messagingService);
|
||||||
|
|
Loading…
Reference in a new issue