1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-18 09:13:15 +00:00
This commit is contained in:
Matt Portune
2022-01-17 21:58:04 -05:00
parent 120fb70039
commit 65739489a7
43 changed files with 893 additions and 1068 deletions

View File

@@ -80,11 +80,12 @@ namespace Bit.App
} }
else if (message.Command == "logout") else if (message.Command == "logout")
{ {
var extras = message.Data as Tuple<bool?, string>; var extras = message.Data as Tuple<string, bool, bool>;
var expired = extras?.Item1; var userId = extras?.Item1;
var userId = extras?.Item2; var userInitiated = extras?.Item2;
var expired = extras?.Item3;
Device.BeginInvokeOnMainThread(async () => Device.BeginInvokeOnMainThread(async () =>
await LogOutAsync(expired.GetValueOrDefault(), userId)); await LogOutAsync(userId, userInitiated, expired));
} }
else if (message.Command == "loggedOut") else if (message.Command == "loggedOut")
{ {
@@ -111,7 +112,7 @@ namespace Bit.App
} }
else if (message.Command == "switchedAccount") else if (message.Command == "switchedAccount")
{ {
await SwitchedAccount(); await SwitchedAccountAsync();
} }
else if (message.Command == "migrated") else if (message.Command == "migrated")
{ {
@@ -241,13 +242,13 @@ namespace Bit.App
new System.Globalization.UmAlQuraCalendar(); new System.Globalization.UmAlQuraCalendar();
} }
private async Task LogOutAsync(bool expired, string userId) private async Task LogOutAsync(string userId, bool? userInitiated, bool? expired)
{ {
await AppHelpers.LogOutAsync(userId); await AppHelpers.LogOutAsync(userId, userInitiated.GetValueOrDefault(true));
await SetMainPageAsync();
_authService.LogOut(() => _authService.LogOut(() =>
{ {
Current.MainPage = new NavigationPage(new HomePage(Options)); if (expired.GetValueOrDefault())
if (expired)
{ {
_platformUtilsService.ShowToast("warning", null, AppResources.LoginExpired); _platformUtilsService.ShowToast("warning", null, AppResources.LoginExpired);
} }
@@ -258,14 +259,14 @@ namespace Bit.App
{ {
Device.BeginInvokeOnMainThread(async () => Device.BeginInvokeOnMainThread(async () =>
{ {
Options.ShowAccountSwitcher = true;
Current.MainPage = new NavigationPage(new HomePage(Options)); Current.MainPage = new NavigationPage(new HomePage(Options));
}); });
} }
private async Task SwitchedAccount() private async Task SwitchedAccountAsync()
{ {
await AppHelpers.ClearServiceCache(); await AppHelpers.OnAccountSwitchAsync();
UpdateTheme();
Device.BeginInvokeOnMainThread(async () => Device.BeginInvokeOnMainThread(async () =>
{ {
await SetMainPageAsync(); await SetMainPageAsync();
@@ -274,10 +275,7 @@ namespace Bit.App
private async Task SetMainPageAsync() private async Task SetMainPageAsync()
{ {
if (await _stateService.HasMultipleAccountsAsync()) await _stateService.RefreshAccountViews();
{
Options.ShowAccountSwitcher = true;
}
var authed = await _stateService.IsAuthenticatedAsync(); var authed = await _stateService.IsAuthenticatedAsync();
if (authed) if (authed)
{ {

View File

@@ -45,13 +45,13 @@
<Label <Label
Grid.Column="0" Grid.Column="0"
Grid.Row="0" Grid.Row="0"
Text="{Binding Account.Email}" Text="{Binding AccountView.Email}"
StyleClass="list-title" StyleClass="list-title"
LineBreakMode="TailTruncation" /> LineBreakMode="TailTruncation" />
<Label <Label
Grid.Column="0" Grid.Column="0"
Grid.Row="1" Grid.Row="1"
Text="{Binding Account.Hostname}" Text="{Binding AccountView.Hostname}"
StyleClass="list-sub" StyleClass="list-sub"
LineBreakMode="TailTruncation" /> LineBreakMode="TailTruncation" />
</Grid> </Grid>

View File

@@ -5,27 +5,27 @@ namespace Bit.App.Controls
{ {
public class AccountViewCellViewModel : ExtendedViewModel public class AccountViewCellViewModel : ExtendedViewModel
{ {
private AccountView _account; private AccountView _accountView;
public AccountViewCellViewModel(AccountView accountView) public AccountViewCellViewModel(AccountView accountView)
{ {
Account = accountView; AccountView = accountView;
} }
public AccountView Account public AccountView AccountView
{ {
get => _account; get => _accountView;
set => SetProperty(ref _account, value); set => SetProperty(ref _accountView, value);
} }
public bool IsAccount public bool IsAccount
{ {
get => Account.IsAccount; get => AccountView.IsAccount;
} }
public string AuthStatusText public string AuthStatusText
{ {
get => Account.AuthStatus.ToString(); get => AccountView.AuthStatus.ToString();
} }
} }
} }

View File

@@ -100,7 +100,8 @@ namespace Bit.App.Controls
for (var i = 0; i < 3; i++) for (var i = 0; i < 3; i++)
{ {
var value = (hash >> (i * 8)) & 0xff; var value = (hash >> (i * 8)) & 0xff;
color += Convert.ToString(value, 16); var base16 = "00" + Convert.ToString(value, 16);
color += base16.Substring(base16.Length - 2);
} }
if (Device.RuntimePlatform == Device.iOS) if (Device.RuntimePlatform == Device.iOS)
{ {

View File

@@ -21,7 +21,6 @@ namespace Bit.App.Models
public string SaveCardCode { get; set; } public string SaveCardCode { get; set; }
public bool IosExtension { get; set; } public bool IosExtension { get; set; }
public Tuple<SendType, string, byte[], string> CreateSend { get; set; } public Tuple<SendType, string, byte[], string> CreateSend { get; set; }
public bool ShowAccountSwitcher { get; set; }
public void SetAllFrom(AppOptions o) public void SetAllFrom(AppOptions o)
{ {
@@ -45,7 +44,6 @@ namespace Bit.App.Models
SaveCardCode = o.SaveCardCode; SaveCardCode = o.SaveCardCode;
IosExtension = o.IosExtension; IosExtension = o.IosExtension;
CreateSend = o.CreateSend; CreateSend = o.CreateSend;
ShowAccountSwitcher = o.ShowAccountSwitcher;
} }
} }
} }

View File

@@ -88,7 +88,7 @@
xct:ShadowEffect.Radius="10" xct:ShadowEffect.Radius="10"
xct:ShadowEffect.OffsetY="3"> xct:ShadowEffect.OffsetY="3">
<ListView <ListView
ItemsSource="{Binding Accounts}" ItemsSource="{Binding AccountViews}"
ItemSelected="AccountRow_Selected" ItemSelected="AccountRow_Selected"
VerticalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
RowHeight="60"> RowHeight="60">

View File

@@ -14,6 +14,8 @@ namespace Bit.App.Pages
private readonly AppOptions _appOptions; private readonly AppOptions _appOptions;
private IBroadcasterService _broadcasterService; private IBroadcasterService _broadcasterService;
private bool _appeared;
public HomePage(AppOptions appOptions = null) public HomePage(AppOptions appOptions = null)
{ {
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService"); _broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
@@ -31,10 +33,6 @@ namespace Bit.App.Pages
{ {
ToolbarItems.Add(_closeItem); ToolbarItems.Add(_closeItem);
} }
if (_appOptions?.ShowAccountSwitcher ?? false)
{
ToolbarItems.Add(_accountAvatar);
}
} }
public async Task DismissRegisterPageAndLogInAsync(string email) public async Task DismissRegisterPageAndLogInAsync(string email)
@@ -46,12 +44,6 @@ namespace Bit.App.Pages
protected override async void OnAppearing() protected override async void OnAppearing()
{ {
base.OnAppearing(); base.OnAppearing();
_mainContent.Content = _mainLayout;
if (_appOptions?.ShowAccountSwitcher ?? false)
{
_appOptions.ShowAccountSwitcher = false;
_vm.AvatarImageSource = await GetAvatarImageSourceAsync();
}
_broadcasterService.Subscribe(nameof(HomePage), async (message) => _broadcasterService.Subscribe(nameof(HomePage), async (message) =>
{ {
if (message.Command == "updatedTheme") if (message.Command == "updatedTheme")
@@ -62,6 +54,17 @@ namespace Bit.App.Pages
}); });
} }
}); });
if (_appeared)
{
return;
}
_appeared = true;
_mainContent.Content = _mainLayout;
if (await HasMultipleAccountsAsync())
{
ToolbarItems.Add(_accountAvatar);
_vm.AvatarImageSource = await GetAvatarImageSourceAsync(false);
}
} }
protected override void OnDisappearing() protected override void OnDisappearing()

View File

@@ -17,9 +17,9 @@ namespace Bit.App.Pages
PageTitle = AppResources.Bitwarden; PageTitle = AppResources.Bitwarden;
} }
public ExtendedObservableCollection<AccountView> Accounts public ExtendedObservableCollection<AccountView> AccountViews
{ {
get => _stateService.Accounts; get => _stateService.AccountViews;
} }
public Action StartLoginAction { get; set; } public Action StartLoginAction { get; set; }

View File

@@ -178,7 +178,7 @@
xct:ShadowEffect.Radius="10" xct:ShadowEffect.Radius="10"
xct:ShadowEffect.OffsetY="3"> xct:ShadowEffect.OffsetY="3">
<ListView <ListView
ItemsSource="{Binding Accounts}" ItemsSource="{Binding AccountViews}"
ItemSelected="AccountRow_Selected" ItemSelected="AccountRow_Selected"
VerticalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
RowHeight="60"> RowHeight="60">

View File

@@ -27,10 +27,6 @@ namespace Bit.App.Pages
MasterPasswordEntry = _masterPassword; MasterPasswordEntry = _masterPassword;
PinEntry = _pin; PinEntry = _pin;
if (_appOptions?.ShowAccountSwitcher ?? false)
{
ToolbarItems.Add(_accountAvatar);
}
if (Device.RuntimePlatform == Device.iOS) if (Device.RuntimePlatform == Device.iOS)
{ {
ToolbarItems.Add(_moreItem); ToolbarItems.Add(_moreItem);
@@ -66,9 +62,9 @@ namespace Bit.App.Pages
} }
_appeared = true; _appeared = true;
_mainContent.Content = _mainLayout; _mainContent.Content = _mainLayout;
if (_appOptions?.ShowAccountSwitcher ?? false) if (await HasMultipleAccountsAsync())
{ {
_appOptions.ShowAccountSwitcher = false; ToolbarItems.Add(_accountAvatar);
_vm.AvatarImageSource = await GetAvatarImageSourceAsync(); _vm.AvatarImageSource = await GetAvatarImageSourceAsync();
} }
await _vm.InitAsync(); await _vm.InitAsync();

View File

@@ -113,9 +113,9 @@ namespace Bit.App.Pages
set => SetProperty(ref _lockedVerifyText, value); set => SetProperty(ref _lockedVerifyText, value);
} }
public ExtendedObservableCollection<AccountView> Accounts public ExtendedObservableCollection<AccountView> AccountViews
{ {
get => _stateService.Accounts; get => _stateService.AccountViews;
} }
public Command SubmitCommand { get; } public Command SubmitCommand { get; }

View File

@@ -130,7 +130,7 @@
xct:ShadowEffect.Radius="10" xct:ShadowEffect.Radius="10"
xct:ShadowEffect.OffsetY="3"> xct:ShadowEffect.OffsetY="3">
<ListView <ListView
ItemsSource="{Binding Accounts}" ItemsSource="{Binding AccountViews}"
ItemSelected="AccountRow_Selected" ItemSelected="AccountRow_Selected"
VerticalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
RowHeight="60"> RowHeight="60">

View File

@@ -12,6 +12,7 @@ namespace Bit.App.Pages
private readonly LoginPageViewModel _vm; private readonly LoginPageViewModel _vm;
private readonly AppOptions _appOptions; private readonly AppOptions _appOptions;
private bool _appeared;
private bool _inputFocused; private bool _inputFocused;
public LoginPage(string email = null, AppOptions appOptions = null) public LoginPage(string email = null, AppOptions appOptions = null)
@@ -34,11 +35,6 @@ namespace Bit.App.Pages
{ {
ToolbarItems.RemoveAt(0); ToolbarItems.RemoveAt(0);
} }
if (_appOptions?.ShowAccountSwitcher ?? false)
{
ToolbarItems.Add(_accountAvatar);
ToolbarItems.Remove(_closeItem);
}
_email.ReturnType = ReturnType.Next; _email.ReturnType = ReturnType.Next;
_email.ReturnCommand = new Command(() => _masterPassword.Focus()); _email.ReturnCommand = new Command(() => _masterPassword.Focus());
@@ -58,18 +54,24 @@ namespace Bit.App.Pages
protected override async void OnAppearing() protected override async void OnAppearing()
{ {
base.OnAppearing(); base.OnAppearing();
_mainContent.Content = _mainLayout;
if (_appOptions?.ShowAccountSwitcher ?? false)
{
_appOptions.ShowAccountSwitcher = false;
_vm.AvatarImageSource = await GetAvatarImageSourceAsync();
}
await _vm.InitAsync(); await _vm.InitAsync();
if (!_inputFocused) if (!_inputFocused)
{ {
RequestFocus(string.IsNullOrWhiteSpace(_vm.Email) ? _email : _masterPassword); RequestFocus(string.IsNullOrWhiteSpace(_vm.Email) ? _email : _masterPassword);
_inputFocused = true; _inputFocused = true;
} }
if (_appeared)
{
return;
}
_appeared = true;
_mainContent.Content = _mainLayout;
if (await HasMultipleAccountsAsync())
{
ToolbarItems.Add(_accountAvatar);
ToolbarItems.Remove(_closeItem);
_vm.AvatarImageSource = await GetAvatarImageSourceAsync();
}
} }
private async void LogIn_Clicked(object sender, EventArgs e) private async void LogIn_Clicked(object sender, EventArgs e)

View File

@@ -62,9 +62,9 @@ namespace Bit.App.Pages
set => SetProperty(ref _masterPassword, value); set => SetProperty(ref _masterPassword, value);
} }
public ExtendedObservableCollection<AccountView> Accounts public ExtendedObservableCollection<AccountView> AccountViews
{ {
get => _stateService.Accounts; get => _stateService.AccountViews;
} }
public Command LogInCommand { get; } public Command LogInCommand { get; }

View File

@@ -38,6 +38,11 @@ namespace Bit.App.Pages
await SaveActivity(); await SaveActivity();
} }
public async Task<bool> HasMultipleAccountsAsync()
{
return await _stateService.HasMultipleAccountsAsync();
}
public bool DoOnce(Action action = null, int milliseconds = 1000) public bool DoOnce(Action action = null, int milliseconds = 1000)
{ {
if (LastPageAction.HasValue && (DateTime.UtcNow - LastPageAction.Value).TotalMilliseconds < milliseconds) if (LastPageAction.HasValue && (DateTime.UtcNow - LastPageAction.Value).TotalMilliseconds < milliseconds)
@@ -108,9 +113,9 @@ namespace Bit.App.Pages
}); });
} }
protected async Task<AvatarImageSource> GetAvatarImageSourceAsync() protected async Task<AvatarImageSource> GetAvatarImageSourceAsync(bool useCurrentActiveAccount = true)
{ {
return new AvatarImageSource(await _stateService.GetEmailAsync()); return new AvatarImageSource(useCurrentActiveAccount ? await _stateService.GetEmailAsync() : null);
} }
protected async Task ShowAccountListAsync(bool isVisible, View listView, View overlay, View fab = null) protected async Task ShowAccountListAsync(bool isVisible, View listView, View overlay, View fab = null)
@@ -120,6 +125,9 @@ namespace Bit.App.Pages
// Not all animations are awaited. This is intentional to allow multiple simultaneous animations. // Not all animations are awaited. This is intentional to allow multiple simultaneous animations.
if (isVisible) if (isVisible)
{ {
// Update account views to reflect current state
await _stateService.RefreshAccountViews();
// start listView in default (off-screen) position // start listView in default (off-screen) position
await listView.TranslateTo(0, listView.Height * -1, 0); await listView.TranslateTo(0, listView.Height * -1, 0);
@@ -173,13 +181,13 @@ namespace Bit.App.Pages
await Task.Delay(100); await Task.Delay(100);
await ShowAccountListAsync(false, listView, overlay, fab); await ShowAccountListAsync(false, listView, overlay, fab);
if (item.Account.IsAccount) if (item.AccountView.IsAccount)
{ {
if (item.Account.AuthStatus != AuthenticationStatus.Active) if (item.AccountView.AuthStatus != AuthenticationStatus.Active)
{ {
await _stateService.SetActiveUserAsync(item.Account.UserId); await _stateService.SetActiveUserAsync(item.AccountView.UserId);
_messagingService.Send("switchedAccount");
} }
_messagingService.Send("switchedAccount");
} }
else else
{ {

View File

@@ -180,7 +180,7 @@
xct:ShadowEffect.Radius="10" xct:ShadowEffect.Radius="10"
xct:ShadowEffect.OffsetY="3"> xct:ShadowEffect.OffsetY="3">
<ListView <ListView
ItemsSource="{Binding Accounts}" ItemsSource="{Binding AccountViews}"
ItemSelected="AccountRow_Selected" ItemSelected="AccountRow_Selected"
VerticalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
RowHeight="60"> RowHeight="60">

View File

@@ -133,13 +133,13 @@ namespace Bit.App.Pages
get => _websiteIconsEnabled; get => _websiteIconsEnabled;
set => SetProperty(ref _websiteIconsEnabled, value); set => SetProperty(ref _websiteIconsEnabled, value);
} }
public ExtendedObservableCollection<AccountView> Accounts public ExtendedObservableCollection<AccountView> AccountViews
{ {
get get
{ {
// create a separate collection that includes the "add new" row // create a separate collection that includes the "add new" row
var accounts = new ExtendedObservableCollection<AccountView>(); var accounts = new ExtendedObservableCollection<AccountView>();
accounts.AddRange(_stateService.Accounts); accounts.AddRange(_stateService.AccountViews);
accounts.Add(new AccountView()); accounts.Add(new AccountView());
return accounts; return accounts;
} }

View File

@@ -447,7 +447,7 @@ namespace Bit.App.Utilities
return Convert.ToBase64String(Encoding.UTF8.GetBytes(multiByteEscaped)); return Convert.ToBase64String(Encoding.UTF8.GetBytes(multiByteEscaped));
} }
public static async Task LogOutAsync(string userId) public static async Task LogOutAsync(string userId, bool userInitiated = false)
{ {
var syncService = ServiceContainer.Resolve<ISyncService>("syncService"); var syncService = ServiceContainer.Resolve<ISyncService>("syncService");
var tokenService = ServiceContainer.Resolve<ITokenService>("tokenService"); var tokenService = ServiceContainer.Resolve<ITokenService>("tokenService");
@@ -469,24 +469,30 @@ namespace Bit.App.Utilities
} }
await Task.WhenAll( await Task.WhenAll(
syncService.SetLastSyncAsync(DateTime.MinValue),
tokenService.ClearTokenAsync(userId),
cryptoService.ClearKeysAsync(userId),
stateService.CleanAsync(userId),
settingsService.ClearAsync(userId),
cipherService.ClearAsync(userId), cipherService.ClearAsync(userId),
folderService.ClearAsync(userId), folderService.ClearAsync(userId),
collectionService.ClearAsync(userId), collectionService.ClearAsync(userId),
passwordGenerationService.ClearAsync(userId), passwordGenerationService.ClearAsync(userId),
vaultTimeoutService.ClearAsync(userId),
deviceActionService.ClearCacheAsync()); deviceActionService.ClearCacheAsync());
if (userInitiated)
{
await Task.WhenAll(
syncService.SetLastSyncAsync(DateTime.MinValue),
tokenService.ClearTokenAsync(userId),
cryptoService.ClearKeysAsync(userId),
settingsService.ClearAsync(userId),
vaultTimeoutService.ClearAsync(userId),
stateService.ClearAsync(userId));
}
stateService.BiometricLocked = true; stateService.BiometricLocked = true;
searchService.ClearIndex(); searchService.ClearIndex();
} }
public static async Task ClearServiceCache() public static async Task OnAccountSwitchAsync()
{ {
var environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
var tokenService = ServiceContainer.Resolve<ITokenService>("tokenService"); var tokenService = ServiceContainer.Resolve<ITokenService>("tokenService");
var cryptoService = ServiceContainer.Resolve<ICryptoService>("cryptoService");
var cipherService = ServiceContainer.Resolve<ICipherService>("cipherService"); var cipherService = ServiceContainer.Resolve<ICipherService>("cipherService");
var folderService = ServiceContainer.Resolve<IFolderService>("folderService"); var folderService = ServiceContainer.Resolve<IFolderService>("folderService");
var collectionService = ServiceContainer.Resolve<ICollectionService>("collectionService"); var collectionService = ServiceContainer.Resolve<ICollectionService>("collectionService");
@@ -495,10 +501,13 @@ namespace Bit.App.Utilities
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService"); var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
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());
tokenService.ClearCache(); tokenService.ClearCache();
cryptoService.ClearCache();
folderService.ClearCache(); folderService.ClearCache();
collectionService.ClearCache(); collectionService.ClearCache();
passwordGenerationService.ClearCache(); passwordGenerationService.ClearCache();

View File

@@ -16,6 +16,7 @@ namespace Bit.Core.Abstractions
Task ClearKeysAsync(string userId = null); Task ClearKeysAsync(string userId = null);
Task ClearOrgKeysAsync(bool memoryOnly = false, string userId = null); Task ClearOrgKeysAsync(bool memoryOnly = false, string userId = null);
Task ClearPinProtectedKeyAsync(string userId = null); Task ClearPinProtectedKeyAsync(string userId = null);
void ClearCache();
Task<byte[]> DecryptFromBytesAsync(byte[] encBytes, SymmetricCryptoKey key); Task<byte[]> DecryptFromBytesAsync(byte[] encBytes, SymmetricCryptoKey key);
Task<byte[]> DecryptToBytesAsync(EncString encString, SymmetricCryptoKey key = null); Task<byte[]> DecryptToBytesAsync(EncString encString, SymmetricCryptoKey key = null);
Task<string> DecryptToUtf8Async(EncString encString, SymmetricCryptoKey key = null); Task<string> DecryptToUtf8Async(EncString encString, SymmetricCryptoKey key = null);

View File

@@ -12,162 +12,152 @@ namespace Bit.Core.Abstractions
public interface IStateService public interface IStateService
{ {
bool BiometricLocked { get; set; } bool BiometricLocked { get; set; }
ExtendedObservableCollection<AccountView> Accounts { get; set; } ExtendedObservableCollection<AccountView> AccountViews { get; set; }
Task<string> GetActiveUserIdAsync(StorageOptions options = null); Task<List<string>> GetUserIdsAsync();
Task<string> GetActiveUserIdAsync();
Task SetActiveUserAsync(string userId); Task SetActiveUserAsync(string userId);
Task<bool> IsAuthenticatedAsync(StorageOptions options = null); Task<bool> IsAuthenticatedAsync(string userId = null);
Task<bool> HasMultipleAccountsAsync(); Task<bool> HasMultipleAccountsAsync();
Task RefreshAccountViews();
Task AddAccountAsync(Account account); Task AddAccountAsync(Account account);
// Task SetInformationAsync(string userId, string email, KdfType kdf, int? kdfIterations); Task ClearAsync(string userId);
Task CleanAsync(string userId);
Task<EnvironmentUrlData> GetPreAuthEnvironmentUrlsAsync(); Task<EnvironmentUrlData> GetPreAuthEnvironmentUrlsAsync();
Task SetPreAuthEnvironmentUrlsAsync(EnvironmentUrlData value); Task SetPreAuthEnvironmentUrlsAsync(EnvironmentUrlData value);
Task<EnvironmentUrlData> GetEnvironmentUrlsAsync(StorageOptions options = null); Task<EnvironmentUrlData> GetEnvironmentUrlsAsync(string userId = null);
Task SetEnvironmentUrlsAsync(EnvironmentUrlData value, StorageOptions options = null); Task<bool?> GetBiometricUnlockAsync(string userId = null);
Task<bool?> GetBiometricUnlockAsync(StorageOptions options = null); Task SetBiometricUnlockAsync(bool? value, string userId = null);
Task SetBiometricUnlockAsync(bool? value, StorageOptions options = null); Task<bool> CanAccessPremiumAsync(string userId = null);
Task<bool> CanAccessPremiumAsync(StorageOptions options = null); Task<string> GetProtectedPinAsync(string userId = null);
Task<string> GetProtectedPinAsync(StorageOptions options = null); Task SetProtectedPinAsync(string value, string userId = null);
Task SetProtectedPinAsync(string value, StorageOptions options = null); Task<string> GetPinProtectedAsync(string userId = null);
Task<string> GetPinProtectedAsync(StorageOptions options = null); Task SetPinProtectedAsync(string value, string userId = null);
Task SetPinProtectedAsync(string value, StorageOptions options = null); Task<EncString> GetPinProtectedCachedAsync(string userId = null);
Task<EncString> GetPinProtectedCachedAsync(StorageOptions options = null); Task SetPinProtectedCachedAsync(EncString value, string userId = null);
Task SetPinProtectedCachedAsync(EncString value, StorageOptions options = null); Task<KdfType?> GetKdfTypeAsync(string userId = null);
Task<KdfType?> GetKdfTypeAsync(StorageOptions options = null); Task SetKdfTypeAsync(KdfType? value, string userId = null);
Task SetKdfTypeAsync(KdfType? value, StorageOptions options = null); Task<int?> GetKdfIterationsAsync(string userId = null);
Task<int?> GetKdfIterationsAsync(StorageOptions options = null); Task SetKdfIterationsAsync(int? value, string userId = null);
Task SetKdfIterationsAsync(int? value, StorageOptions options = null); Task<string> GetKeyEncryptedAsync(string userId = null);
Task<string> GetKeyEncryptedAsync(StorageOptions options = null); Task SetKeyEncryptedAsync(string value, string userId = null);
Task SetKeyEncryptedAsync(string value, StorageOptions options = null); Task<SymmetricCryptoKey> GetKeyDecryptedAsync(string userId = null);
Task<SymmetricCryptoKey> GetKeyDecryptedAsync(StorageOptions options = null); Task SetKeyDecryptedAsync(SymmetricCryptoKey value, string userId = null);
Task SetKeyDecryptedAsync(SymmetricCryptoKey value, StorageOptions options = null); Task<string> GetKeyHashAsync(string userId = null);
Task<string> GetKeyHashAsync(StorageOptions options = null); Task SetKeyHashAsync(string value, string userId = null);
Task SetKeyHashAsync(string value, StorageOptions options = null); Task<string> GetEncKeyEncryptedAsync(string userId = null);
Task<string> GetKeyHashCachedAsync(StorageOptions options = null); Task SetEncKeyEncryptedAsync(string value, string userId = null);
Task SetKeyHashCachedAsync(string value, StorageOptions options = null); Task<Dictionary<string, string>> GetOrgKeysEncryptedAsync(string userId = null);
Task<string> GetEncKeyEncryptedAsync(StorageOptions options = null); Task SetOrgKeysEncryptedAsync(Dictionary<string, string> value, string userId = null);
Task SetEncKeyEncryptedAsync(string value, StorageOptions options = null); Task<string> GetPrivateKeyEncryptedAsync(string userId = null);
Task<SymmetricCryptoKey> GetEncKeyDecryptedAsync(StorageOptions options = null); Task SetPrivateKeyEncryptedAsync(string value, string userId = null);
Task SetEncKeyDecryptedAsync(SymmetricCryptoKey value, StorageOptions options = null); Task<List<string>> GetAutofillBlacklistedUrisAsync(string userId = null);
Task<Dictionary<string, string>> GetOrgKeysEncryptedAsync(StorageOptions options = null); Task SetAutofillBlacklistedUrisAsync(List<string> value, string userId = null);
Task SetOrgKeysEncryptedAsync(Dictionary<string, string> value, StorageOptions options = null); Task<bool?> GetAutofillTileAddedAsync(string userId = null);
Task<Dictionary<string, SymmetricCryptoKey>> GetOrgKeysDecryptedAsync(StorageOptions options = null); Task SetAutofillTileAddedAsync(bool? value, string userId = null);
Task SetOrgKeysDecryptedAsync(Dictionary<string, SymmetricCryptoKey> value, StorageOptions options = null); Task<string> GetEmailAsync(string userId = null);
Task<byte[]> GetPublicKeyAsync(StorageOptions options = null); // Task SetEmailAsync(string value, string userId = null);
Task SetPublicKeyAsync(byte[] value, StorageOptions options = null); Task<long?> GetLastActiveTimeAsync(string userId = null);
Task<string> GetPrivateKeyEncryptedAsync(StorageOptions options = null); Task SetLastActiveTimeAsync(long? value, string userId = null);
Task SetPrivateKeyEncryptedAsync(string value, StorageOptions options = null); Task<int?> GetVaultTimeoutAsync(string userId = null);
Task<byte[]> GetPrivateKeyDecryptedAsync(StorageOptions options = null); Task SetVaultTimeoutAsync(int? value, string userId = null);
Task SetPrivateKeyDecryptedAsync(byte[] value, StorageOptions options = null); Task<string> GetVaultTimeoutActionAsync(string userId = null);
Task<List<string>> GetAutofillBlacklistedUrisAsync(StorageOptions options = null); Task SetVaultTimeoutActionAsync(string value, string userId = null);
Task SetAutofillBlacklistedUrisAsync(List<string> value, StorageOptions options = null); Task<DateTime?> GetLastFileCacheClearAsync(string userId = null);
Task<bool?> GetAutofillTileAddedAsync(StorageOptions options = null); Task SetLastFileCacheClearAsync(DateTime? value, string userId = null);
Task SetAutofillTileAddedAsync(bool? value, StorageOptions options = null); Task<PreviousPageInfo> GetPreviousPageInfoAsync(string userId = null);
Task<string> GetEmailAsync(StorageOptions options = null); Task SetPreviousPageInfoAsync(PreviousPageInfo value, string userId = null);
// Task SetEmailAsync(string value, StorageOptions options = null); Task<int> GetInvalidUnlockAttemptsAsync(string userId = null);
Task<long?> GetLastActiveTimeAsync(StorageOptions options = null); Task SetInvalidUnlockAttemptsAsync(int? value, string userId = null);
Task SetLastActiveTimeAsync(long? value, StorageOptions options = null); Task<string> GetLastBuildAsync(string userId = null);
Task<int?> GetVaultTimeoutAsync(StorageOptions options = null); Task SetLastBuildAsync(string value, string userId = null);
Task SetVaultTimeoutAsync(int? value, StorageOptions options = null); Task<bool?> GetDisableFaviconAsync(string userId = null);
Task<string> GetVaultTimeoutActionAsync(StorageOptions options = null); Task SetDisableFaviconAsync(bool? value, string userId = null);
Task SetVaultTimeoutActionAsync(string value, StorageOptions options = null); Task<bool?> GetDisableAutoTotpCopyAsync(string userId = null);
Task<DateTime?> GetLastFileCacheClearAsync(StorageOptions options = null); Task SetDisableAutoTotpCopyAsync(bool? value, string userId = null);
Task SetLastFileCacheClearAsync(DateTime? value, StorageOptions options = null); Task<bool?> GetInlineAutofillEnabledAsync(string userId = null);
Task<PreviousPageInfo> GetPreviousPageInfoAsync(StorageOptions options = null); Task SetInlineAutofillEnabledAsync(bool? value, string userId = null);
Task SetPreviousPageInfoAsync(PreviousPageInfo value, StorageOptions options = null); Task<bool?> GetAutofillDisableSavePromptAsync(string userId = null);
Task<int> GetInvalidUnlockAttemptsAsync(StorageOptions options = null); Task SetAutofillDisableSavePromptAsync(bool? value, string userId = null);
Task SetInvalidUnlockAttemptsAsync(int? value, StorageOptions options = null); Task<Dictionary<string, Dictionary<string, object>>> GetLocalDataAsync(string userId = null);
Task<string> GetLastBuildAsync(StorageOptions options = null); Task SetLocalDataAsync(Dictionary<string, Dictionary<string, object>> value, string userId = null);
Task SetLastBuildAsync(string value, StorageOptions options = null); Task<Dictionary<string, CipherData>> GetEncryptedCiphersAsync(string userId = null);
Task<bool?> GetDisableFaviconAsync(StorageOptions options = null); Task SetEncryptedCiphersAsync(Dictionary<string, CipherData> value, string userId = null);
Task SetDisableFaviconAsync(bool? value, StorageOptions options = null); Task<int?> GetDefaultUriMatchAsync(string userId = null);
Task<bool?> GetDisableAutoTotpCopyAsync(StorageOptions options = null); Task SetDefaultUriMatchAsync(int? value, string userId = null);
Task SetDisableAutoTotpCopyAsync(bool? value, StorageOptions options = null); Task<HashSet<string>> GetNeverDomainsAsync(string userId = null);
Task<bool?> GetInlineAutofillEnabledAsync(StorageOptions options = null); Task SetNeverDomainsAsync(HashSet<string> value, string userId = null);
Task SetInlineAutofillEnabledAsync(bool? value, StorageOptions options = null); Task<int?> GetClearClipboardAsync(string userId = null);
Task<bool?> GetAutofillDisableSavePromptAsync(StorageOptions options = null); Task SetClearClipboardAsync(int? value, string userId = null);
Task SetAutofillDisableSavePromptAsync(bool? value, StorageOptions options = null); Task<Dictionary<string, CollectionData>> GetEncryptedCollectionsAsync(string userId = null);
Task<Dictionary<string, Dictionary<string, object>>> GetLocalDataAsync(StorageOptions options = null); Task SetEncryptedCollectionsAsync(Dictionary<string, CollectionData> value, string userId = null);
Task SetLocalDataAsync(Dictionary<string, Dictionary<string, object>> value, StorageOptions options = null); Task<bool> GetPasswordRepromptAutofillAsync(string userId = null);
Task<Dictionary<string, CipherData>> GetEncryptedCiphersAsync(StorageOptions options = null); Task SetPasswordRepromptAutofillAsync(bool? value, string userId = null);
Task SetEncryptedCiphersAsync(Dictionary<string, CipherData> value, StorageOptions options = null); Task<bool> GetPasswordVerifiedAutofillAsync(string userId = null);
Task<int?> GetDefaultUriMatchAsync(StorageOptions options = null); Task SetPasswordVerifiedAutofillAsync(bool? value, string userId = null);
Task SetDefaultUriMatchAsync(int? value, StorageOptions options = null); Task<DateTime?> GetLastSyncAsync(string userId = null);
Task<HashSet<string>> GetNeverDomainsAsync(StorageOptions options = null); Task SetLastSyncAsync(DateTime? value, string userId = null);
Task SetNeverDomainsAsync(HashSet<string> value, StorageOptions options = null); Task<string> GetSecurityStampAsync(string userId = null);
Task<int?> GetClearClipboardAsync(StorageOptions options = null); Task SetSecurityStampAsync(string value, string userId = null);
Task SetClearClipboardAsync(int? value, StorageOptions options = null); Task<bool> GetEmailVerifiedAsync(string userId = null);
Task<Dictionary<string, CollectionData>> GetEncryptedCollectionsAsync(StorageOptions options = null); Task SetEmailVerifiedAsync(bool? value, string userId = null);
Task SetEncryptedCollectionsAsync(Dictionary<string, CollectionData> value, StorageOptions options = null); Task<bool> GetForcePasswordReset(string userId = null);
Task<bool> GetPasswordRepromptAutofillAsync(StorageOptions options = null); Task SetForcePasswordResetAsync(bool? value, string userId = null);
Task SetPasswordRepromptAutofillAsync(bool? value, StorageOptions options = null); Task<bool> GetSyncOnRefreshAsync(string userId = null);
Task<bool> GetPasswordVerifiedAutofillAsync(StorageOptions options = null); Task SetSyncOnRefreshAsync(bool? value, string userId = null);
Task SetPasswordVerifiedAutofillAsync(bool? value, StorageOptions options = null); Task<string> GetRememberedEmailAsync(string userId = null);
Task<DateTime?> GetLastSyncAsync(StorageOptions options = null); Task SetRememberedEmailAsync(string value, string userId = null);
Task SetLastSyncAsync(DateTime? value, StorageOptions options = null); Task<bool?> GetRememberEmailAsync(string userId = null);
Task<string> GetSecurityStampAsync(StorageOptions options = null); Task SetRememberEmailAsync(bool? value, string userId = null);
Task SetSecurityStampAsync(string value, StorageOptions options = null); Task<string> GetRememberedOrgIdentifierAsync(string userId = null);
Task<bool> GetEmailVerifiedAsync(StorageOptions options = null); Task SetRememberedOrgIdentifierAsync(string value, string userId = null);
Task SetEmailVerifiedAsync(bool? value, StorageOptions options = null); Task<bool?> GetRememberOrgIdentifierAsync(string userId = null);
Task<bool> GetForcePasswordReset(StorageOptions options = null); Task SetRememberOrgIdentifierAsync(bool? value, string userId = null);
Task SetForcePasswordResetAsync(bool? value, StorageOptions options = null); Task<string> GetThemeAsync(string userId = null);
Task<bool> GetSyncOnRefreshAsync(StorageOptions options = null); Task SetThemeAsync(string value, string userId = null);
Task SetSyncOnRefreshAsync(bool? value, StorageOptions options = null); Task<bool?> GetAddSitePromptShownAsync(string userId = null);
Task<string> GetRememberedEmailAsync(StorageOptions options = null); Task SetAddSitePromptShownAsync(bool? value, string userId = null);
Task SetRememberedEmailAsync(string value, StorageOptions options = null); Task<bool?> GetMigratedFromV1Async(string userId = null);
Task<bool?> GetRememberEmailAsync(StorageOptions options = null); Task SetMigratedFromV1Async(bool? value, string userId = null);
Task SetRememberEmailAsync(bool? value, StorageOptions options = null); Task<bool?> GetMigratedFromV1AutofillPromptShownAsync(string userId = null);
Task<string> GetRememberedOrgIdentifierAsync(StorageOptions options = null); Task SetMigratedFromV1AutofillPromptShownAsync(bool? value, string userId = null);
Task SetRememberedOrgIdentifierAsync(string value, StorageOptions options = null); Task<bool?> GetTriedV1ResyncAsync(string userId = null);
Task<bool?> GetRememberOrgIdentifierAsync(StorageOptions options = null); Task SetTriedV1ResyncAsync(bool? value, string userId = null);
Task SetRememberOrgIdentifierAsync(bool? value, StorageOptions options = null); Task<bool?> GetPushInitialPromptShownAsync(string userId = null);
Task<string> GetThemeAsync(StorageOptions options = null); Task SetPushInitialPromptShownAsync(bool? value, string userId = null);
Task SetThemeAsync(string value, StorageOptions options = null); Task<DateTime?> GetPushLastRegistrationDateAsync(string userId = null);
Task<bool?> GetAddSitePromptShownAsync(StorageOptions options = null); Task SetPushLastRegistrationDateAsync(DateTime? value, string userId = null);
Task SetAddSitePromptShownAsync(bool? value, StorageOptions options = null); Task<string> GetPushCurrentTokenAsync(string userId = null);
Task<bool?> GetMigratedFromV1Async(StorageOptions options = null); Task SetPushCurrentTokenAsync(string value, string userId = null);
Task SetMigratedFromV1Async(bool? value, StorageOptions options = null); Task<List<EventData>> GetEventCollectionAsync(string userId = null);
Task<bool?> GetMigratedFromV1AutofillPromptShownAsync(StorageOptions options = null); Task SetEventCollectionAsync(List<EventData> value, string userId = null);
Task SetMigratedFromV1AutofillPromptShownAsync(bool? value, StorageOptions options = null); Task<Dictionary<string, FolderData>> GetEncryptedFoldersAsync(string userId = null);
Task<bool?> GetTriedV1ResyncAsync(StorageOptions options = null); Task SetEncryptedFoldersAsync(Dictionary<string, FolderData> value, string userId = null);
Task SetTriedV1ResyncAsync(bool? value, StorageOptions options = null); Task<Dictionary<string, PolicyData>> GetEncryptedPoliciesAsync(string userId = null);
Task<bool?> GetPushInitialPromptShownAsync(StorageOptions options = null); Task SetEncryptedPoliciesAsync(Dictionary<string, PolicyData> value, string userId = null);
Task SetPushInitialPromptShownAsync(bool? value, StorageOptions options = null); Task<string> GetPushRegisteredTokenAsync(string userId = null);
Task<DateTime?> GetPushLastRegistrationDateAsync(StorageOptions options = null); Task SetPushRegisteredTokenAsync(string value, string userId = null);
Task SetPushLastRegistrationDateAsync(DateTime? value, StorageOptions options = null); Task<bool?> GetAppExtensionStartedAsync(string userId = null);
Task<string> GetPushCurrentTokenAsync(StorageOptions options = null); Task SetAppExtensionStartedAsync(bool? value, string userId = null);
Task SetPushCurrentTokenAsync(string value, StorageOptions options = null); Task<bool?> GetAppExtensionActivatedAsync(string userId = null);
Task<List<EventData>> GetEventCollectionAsync(StorageOptions options = null); Task SetAppExtensionActivatedAsync(bool? value, string userId = null);
Task SetEventCollectionAsync(List<EventData> value, StorageOptions options = null); Task<string> GetAppIdAsync(string userId = null);
Task<Dictionary<string, FolderData>> GetEncryptedFoldersAsync(StorageOptions options = null); Task SetAppIdAsync(string value, string userId = null);
Task SetEncryptedFoldersAsync(Dictionary<string, FolderData> value, StorageOptions options = null); Task<bool> GetUsesKeyConnectorAsync(string userId = null);
Task<Dictionary<string, PolicyData>> GetEncryptedPoliciesAsync(StorageOptions options = null); Task SetUsesKeyConnectorAsync(bool? value, string userId = null);
Task SetEncryptedPoliciesAsync(Dictionary<string, PolicyData> value, StorageOptions options = null); Task<Dictionary<string, OrganizationData>> GetOrganizationsAsync(string userId = null);
Task<string> GetPushRegisteredTokenAsync(StorageOptions options = null); Task SetOrganizationsAsync(Dictionary<string, OrganizationData> organizations, string userId = null);
Task SetPushRegisteredTokenAsync(string value, StorageOptions options = null); Task<PasswordGenerationOptions> GetPasswordGenerationOptionsAsync(string userId = null);
Task<bool?> GetAppExtensionStartedAsync(StorageOptions options = null); Task SetPasswordGenerationOptionsAsync(PasswordGenerationOptions value, string userId = null);
Task SetAppExtensionStartedAsync(bool? value, StorageOptions options = null); Task<List<GeneratedPasswordHistory>> GetEncryptedPasswordGenerationHistory(string userId = null);
Task<bool?> GetAppExtensionActivatedAsync(StorageOptions options = null); Task SetEncryptedPasswordGenerationHistoryAsync(List<GeneratedPasswordHistory> value, string userId = null);
Task SetAppExtensionActivatedAsync(bool? value, StorageOptions options = null); Task<Dictionary<string, SendData>> GetEncryptedSendsAsync(string userId = null);
Task<string> GetAppIdAsync(StorageOptions options = null); Task SetEncryptedSendsAsync(Dictionary<string, SendData> value, string userId = null);
Task SetAppIdAsync(string value, StorageOptions options = null); Task<Dictionary<string, object>> GetSettingsAsync(string userId = null);
Task<bool> GetUsesKeyConnectorAsync(StorageOptions options = null); Task SetSettingsAsync(Dictionary<string, object> value, string userId = null);
Task SetUsesKeyConnectorAsync(bool? value, StorageOptions options = null); Task<string> GetAccessTokenAsync(string userId = null);
Task<Dictionary<string, OrganizationData>> GetOrganizationsAsync(StorageOptions options = null); Task SetAccessTokenAsync(string value, string userId = null);
Task SetOrganizationsAsync(Dictionary<string, OrganizationData> organizations, StorageOptions options = null); Task<string> GetRefreshTokenAsync(string userId = null);
Task<PasswordGenerationOptions> GetPasswordGenerationOptionsAsync(StorageOptions options = null); Task SetRefreshTokenAsync(string value, string userId = null);
Task SetPasswordGenerationOptionsAsync(PasswordGenerationOptions value, StorageOptions options = null); Task<string> GetTwoFactorTokenAsync(string email = null);
Task<List<GeneratedPasswordHistory>> GetEncryptedPasswordGenerationHistory(StorageOptions options = null); Task SetTwoFactorTokenAsync(string value, string email = null);
Task SetEncryptedPasswordGenerationHistoryAsync(List<GeneratedPasswordHistory> value, StorageOptions options = null);
Task<Dictionary<string, SendData>> GetEncryptedSendsAsync(StorageOptions options = null);
Task SetEncryptedSendsAsync(Dictionary<string, SendData> value, StorageOptions options = null);
Task<Dictionary<string, object>> GetSettingsAsync(StorageOptions options = null);
Task SetSettingsAsync(Dictionary<string, object> value, StorageOptions options = null);
Task<string> GetAccessTokenAsync(StorageOptions options = null);
Task SetAccessTokenAsync(string value, StorageOptions options = null);
Task<string> GetRefreshTokenAsync(StorageOptions options = null);
Task SetRefreshTokenAsync(string value, StorageOptions options = null);
Task<string> GetTwoFactorTokenAsync(StorageOptions options = null);
Task SetTwoFactorTokenAsync(string value, StorageOptions options = null);
} }
} }

View File

@@ -1,31 +0,0 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
using Bit.Core.Models.Domain;
namespace Bit.Core.Abstractions
{
public interface IUserService
{
Task<bool> CanAccessPremiumAsync();
Task ClearAsync();
Task ClearOrganizationsAsync(string userId);
Task<List<Organization>> GetAllOrganizationAsync();
Task<string> GetEmailAsync();
Task<KdfType?> GetKdfAsync();
Task<int?> GetKdfIterationsAsync();
Task<Organization> GetOrganizationAsync(string id);
Task<Organization> GetOrganizationByIdentifierAsync(string identifier);
Task<string> GetSecurityStampAsync();
Task<bool> GetEmailVerifiedAsync();
Task<bool> GetForcePasswordReset();
Task<string> GetUserIdAsync();
Task<bool> IsAuthenticatedAsync();
Task ReplaceOrganizationsAsync(Dictionary<string, OrganizationData> organizations);
Task SetInformationAsync(string userId, string email, KdfType kdf, int? kdfIterations);
Task SetSecurityStampAsync(string stamp);
Task SetEmailVerifiedAsync(bool emailVerified);
Task SetForcePasswordReset(bool forcePasswordReset);
}
}

View File

@@ -11,7 +11,7 @@ namespace Bit.Core.Abstractions
Task<Tuple<bool, bool>> IsPinLockSetAsync(); Task<Tuple<bool, bool>> IsPinLockSetAsync();
Task<bool> IsBiometricLockSetAsync(); Task<bool> IsBiometricLockSetAsync();
Task LockAsync(bool allowSoftLock = false, bool userInitiated = false, string userId = null); Task LockAsync(bool allowSoftLock = false, bool userInitiated = false, string userId = null);
Task LogOutAsync(string userId = null); Task LogOutAsync(bool userInitiated = true, string userId = null);
Task SetVaultTimeoutOptionsAsync(int? timeout, string action); Task SetVaultTimeoutOptionsAsync(int? timeout, string action);
Task<int?> GetVaultTimeout(string userId = null); Task<int?> GetVaultTimeout(string userId = null);
} }

View File

@@ -64,8 +64,6 @@
public static string PassGenOptionsKey(string userId) => $"passwordGenerationOptions_{userId}"; public static string PassGenOptionsKey(string userId) => $"passwordGenerationOptions_{userId}";
public static string PassGenHistoryKey(string userId) => $"generatedPasswordHistory_{userId}"; public static string PassGenHistoryKey(string userId) => $"generatedPasswordHistory_{userId}";
public static string TwoFactorTokenKey(string email) => $"twoFactorToken_{email}"; public static string TwoFactorTokenKey(string email) => $"twoFactorToken_{email}";
public static string VaultTimeoutKey(string userId) => $"vaultTimeout_{userId}";
public static string VaultTimeoutActionKey(string userId) => $"vaultTimeoutAction_{userId}";
public static string LastActiveTimeKey(string userId) => $"lastActiveTime_{userId}"; public static string LastActiveTimeKey(string userId) => $"lastActiveTime_{userId}";
public static string InvalidUnlockAttemptsKey(string userId) => $"invalidUnlockAttempts_{userId}"; public static string InvalidUnlockAttemptsKey(string userId) => $"invalidUnlockAttempts_{userId}";
public static string InlineAutofillEnabledKey(string userId) => $"inlineAutofillEnabled_{userId}"; public static string InlineAutofillEnabledKey(string userId) => $"inlineAutofillEnabled_{userId}";
@@ -83,8 +81,6 @@
public static string SettingsKey(string userId) => $"settings_{userId}"; public static string SettingsKey(string userId) => $"settings_{userId}";
public static string UsesKeyConnectorKey(string userId) => $"usesKeyConnector_{userId}"; public static string UsesKeyConnectorKey(string userId) => $"usesKeyConnector_{userId}";
public static string ProtectedPinKey(string userId) => $"protectedPin_{userId}"; public static string ProtectedPinKey(string userId) => $"protectedPin_{userId}";
public static string SecurityStampKey(string userId) => $"securityStamp_{userId}";
public static string EmailVerifiedKey(string userId) => $"emailVerified_{userId}";
public static string ForcePasswordResetKey(string userId) => $"forcePasswordReset_{userId}"; public static string ForcePasswordResetKey(string userId) => $"forcePasswordReset_{userId}";
public static string LastSyncKey(string userId) => $"lastSync_{userId}"; public static string LastSyncKey(string userId) => $"lastSync_{userId}";
public static string BiometricUnlockKey(string userId) => $"biometricUnlock_{userId}"; public static string BiometricUnlockKey(string userId) => $"biometricUnlock_{userId}";

View File

@@ -1,11 +1,11 @@
using System.Collections.Generic; using Bit.Core.Enums;
using Bit.Core.Enums;
using Bit.Core.Models.Data; using Bit.Core.Models.Data;
namespace Bit.Core.Models.Domain namespace Bit.Core.Models.Domain
{ {
public class Account : Domain public class Account : Domain
{ {
public AuthenticationStatus? AuthStatus;
public AccountProfile Profile; public AccountProfile Profile;
public AccountTokens Tokens; public AccountTokens Tokens;
public AccountSettings Settings; public AccountSettings Settings;
@@ -24,6 +24,7 @@ namespace Bit.Core.Models.Domain
public Account(Account account) public Account(Account account)
{ {
// Copy constructor excludes Keys (for storage) // Copy constructor excludes Keys (for storage)
AuthStatus = account.AuthStatus;
Profile = new AccountProfile(account.Profile); Profile = new AccountProfile(account.Profile);
Tokens = new AccountTokens(account.Tokens); Tokens = new AccountTokens(account.Tokens);
Settings = new AccountSettings(account.Settings); Settings = new AccountSettings(account.Settings);
@@ -42,18 +43,20 @@ namespace Bit.Core.Models.Domain
UserId = copy.UserId; UserId = copy.UserId;
Email = copy.Email; Email = copy.Email;
AuthStatus = copy.AuthStatus; Stamp = copy.Stamp;
HasPremiumPersonally = copy.HasPremiumPersonally;
KdfType = copy.KdfType; KdfType = copy.KdfType;
KdfIterations = copy.KdfIterations; KdfIterations = copy.KdfIterations;
EmailVerified = copy.EmailVerified;
HasPremiumPersonally = copy.HasPremiumPersonally;
} }
public string UserId; public string UserId;
public string Email; public string Email;
public AuthenticationStatus? AuthStatus; public string Stamp;
public bool? HasPremiumPersonally;
public KdfType? KdfType; public KdfType? KdfType;
public int? KdfIterations; public int? KdfIterations;
public bool? EmailVerified;
public bool? HasPremiumPersonally;
} }
public class AccountTokens public class AccountTokens
@@ -88,21 +91,19 @@ namespace Bit.Core.Models.Domain
EnvironmentUrls = copy.EnvironmentUrls; EnvironmentUrls = copy.EnvironmentUrls;
PinProtected = copy.PinProtected; PinProtected = copy.PinProtected;
VaultTimeout = copy.VaultTimeout;
VaultTimeoutAction = copy.VaultTimeoutAction;
} }
public EnvironmentUrlData EnvironmentUrls; public EnvironmentUrlData EnvironmentUrls;
public EncString PinProtected; public EncString PinProtected;
public int? VaultTimeout;
public string VaultTimeoutAction;
} }
public class AccountKeys public class AccountKeys
{ {
public SymmetricCryptoKey Key; public SymmetricCryptoKey Key;
public string KeyHash;
public SymmetricCryptoKey EncKey;
public Dictionary<string, SymmetricCryptoKey>
OrganizationKeys = new Dictionary<string, SymmetricCryptoKey>();
public byte[] PrivateKey;
public byte[] PublicKey;
} }
} }
} }

View File

@@ -15,17 +15,16 @@ namespace Bit.Core.Models.View
return; return;
} }
IsAccount = true; IsAccount = true;
AuthStatus = a.AuthStatus;
UserId = a.Profile.UserId; UserId = a.Profile?.UserId;
Email = a.Profile.Email; Email = a.Profile?.Email;
Hostname = a.Settings.EnvironmentUrls.Base; Hostname = a.Settings?.EnvironmentUrls?.Base;
AuthStatus = a.Profile.AuthStatus;
} }
public bool IsAccount { get; set; } public bool IsAccount { get; set; }
public AuthenticationStatus? AuthStatus { get; set; }
public string UserId { get; set; } public string UserId { get; set; }
public string Email { get; set; } public string Email { get; set; }
public string Hostname { get; set; } public string Hostname { get; set; }
public AuthenticationStatus? AuthStatus { get; set; }
} }
} }

View File

@@ -24,12 +24,12 @@ namespace Bit.Core.Services
private readonly HttpClient _httpClient = new HttpClient(); private readonly HttpClient _httpClient = new HttpClient();
private readonly ITokenService _tokenService; private readonly ITokenService _tokenService;
private readonly IPlatformUtilsService _platformUtilsService; private readonly IPlatformUtilsService _platformUtilsService;
private readonly Func<bool, Task> _logoutCallbackAsync; private readonly Func<Tuple<string, bool, bool>, Task> _logoutCallbackAsync;
public ApiService( public ApiService(
ITokenService tokenService, ITokenService tokenService,
IPlatformUtilsService platformUtilsService, IPlatformUtilsService platformUtilsService,
Func<bool, Task> logoutCallbackAsync, Func<Tuple<string, bool, bool>, Task> logoutCallbackAsync,
string customUserAgent = null) string customUserAgent = null)
{ {
_tokenService = tokenService; _tokenService = tokenService;
@@ -698,7 +698,7 @@ namespace Bit.Core.Services
if (authed && ((tokenError && response.StatusCode == HttpStatusCode.BadRequest) || if (authed && ((tokenError && response.StatusCode == HttpStatusCode.BadRequest) ||
response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.Forbidden)) response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.Forbidden))
{ {
await _logoutCallbackAsync(true); await _logoutCallbackAsync(new Tuple<string, bool, bool>(null, false, true));
return null; return null;
} }
try try

View File

@@ -359,9 +359,9 @@ namespace Bit.Core.Services
{ {
UserId = _tokenService.GetUserId(), UserId = _tokenService.GetUserId(),
Email = _tokenService.GetEmail(), Email = _tokenService.GetEmail(),
HasPremiumPersonally = _tokenService.GetPremium(),
KdfType = tokenResponse.Kdf, KdfType = tokenResponse.Kdf,
KdfIterations = tokenResponse.KdfIterations, KdfIterations = tokenResponse.KdfIterations,
HasPremiumPersonally = _tokenService.GetPremium(),
}, },
new Account.AccountTokens() new Account.AccountTokens()
{ {

View File

@@ -639,7 +639,7 @@ namespace Bit.Core.Services
public async Task ClearAsync(string userId) public async Task ClearAsync(string userId)
{ {
await _stateService.SetEncryptedCiphersAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetEncryptedCiphersAsync(null, userId);
await ClearCacheAsync(); await ClearCacheAsync();
} }

View File

@@ -181,7 +181,7 @@ namespace Bit.Core.Services
public async Task ClearAsync(string userId) public async Task ClearAsync(string userId)
{ {
await _stateService.SetEncryptedCollectionsAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetEncryptedCollectionsAsync(null, userId);
_decryptedCollectionCache = null; _decryptedCollectionCache = null;
} }

View File

@@ -17,7 +17,12 @@ namespace Bit.Core.Services
private readonly IStateService _stateService; private readonly IStateService _stateService;
private readonly ICryptoFunctionService _cryptoFunctionService; private readonly ICryptoFunctionService _cryptoFunctionService;
private SymmetricCryptoKey _encKey;
private SymmetricCryptoKey _legacyEtmKey; private SymmetricCryptoKey _legacyEtmKey;
private string _keyHash;
private byte[] _publicKey;
private byte[] _privateKey;
private Dictionary<string, SymmetricCryptoKey> _orgKeys;
private Task<SymmetricCryptoKey> _getEncKeysTask; private Task<SymmetricCryptoKey> _getEncKeysTask;
private Task<Dictionary<string, SymmetricCryptoKey>> _getOrgKeysTask; private Task<Dictionary<string, SymmetricCryptoKey>> _getOrgKeysTask;
@@ -44,7 +49,7 @@ namespace Bit.Core.Services
public async Task SetKeyHashAsync(string keyHash) public async Task SetKeyHashAsync(string keyHash)
{ {
await _stateService.SetKeyHashCachedAsync(keyHash); _keyHash = keyHash;
await _stateService.SetKeyHashAsync(keyHash); await _stateService.SetKeyHashAsync(keyHash);
} }
@@ -55,7 +60,7 @@ namespace Bit.Core.Services
return; return;
} }
await _stateService.SetEncKeyEncryptedAsync(encKey); await _stateService.SetEncKeyEncryptedAsync(encKey);
await _stateService.SetEncKeyDecryptedAsync(null); _encKey = null;
} }
public async Task SetEncPrivateKeyAsync(string encPrivateKey) public async Task SetEncPrivateKeyAsync(string encPrivateKey)
@@ -65,13 +70,13 @@ namespace Bit.Core.Services
return; return;
} }
await _stateService.SetPrivateKeyEncryptedAsync(encPrivateKey); await _stateService.SetPrivateKeyEncryptedAsync(encPrivateKey);
await _stateService.SetPrivateKeyDecryptedAsync(null); _privateKey = null;
} }
public async Task SetOrgKeysAsync(IEnumerable<ProfileOrganizationResponse> orgs) public async Task SetOrgKeysAsync(IEnumerable<ProfileOrganizationResponse> orgs)
{ {
var orgKeys = orgs.ToDictionary(org => org.Id, org => org.Key); var orgKeys = orgs.ToDictionary(org => org.Id, org => org.Key);
await _stateService.SetOrgKeysDecryptedAsync(null); _orgKeys = null;
await _stateService.SetOrgKeysEncryptedAsync(orgKeys); await _stateService.SetOrgKeysEncryptedAsync(orgKeys);
} }
@@ -93,25 +98,23 @@ namespace Bit.Core.Services
public async Task<string> GetKeyHashAsync() public async Task<string> GetKeyHashAsync()
{ {
var inMemoryKeyHash = await _stateService.GetKeyHashCachedAsync(); if (_keyHash != null)
if (inMemoryKeyHash != null)
{ {
return inMemoryKeyHash; return _keyHash;
} }
var keyHash = await _stateService.GetKeyHashAsync(); var keyHash = await _stateService.GetKeyHashAsync();
if (keyHash != null) if (keyHash != null)
{ {
await _stateService.SetKeyHashCachedAsync(keyHash); _keyHash = keyHash;
} }
return keyHash; return _keyHash;
} }
public Task<SymmetricCryptoKey> GetEncKeyAsync(SymmetricCryptoKey key = null) public Task<SymmetricCryptoKey> GetEncKeyAsync(SymmetricCryptoKey key = null)
{ {
var inMemoryKey = _stateService.GetEncKeyDecryptedAsync().GetAwaiter().GetResult(); if (_encKey != null)
if (inMemoryKey != null)
{ {
return Task.FromResult(inMemoryKey); return Task.FromResult(_encKey);
} }
if (_getEncKeysTask != null && !_getEncKeysTask.IsCompleted && !_getEncKeysTask.IsFaulted) if (_getEncKeysTask != null && !_getEncKeysTask.IsCompleted && !_getEncKeysTask.IsFaulted)
{ {
@@ -156,9 +159,8 @@ namespace Bit.Core.Services
{ {
return null; return null;
} }
var newEncKey = new SymmetricCryptoKey(decEncKey); _encKey = new SymmetricCryptoKey(decEncKey);
await _stateService.SetEncKeyDecryptedAsync(newEncKey); return _encKey;
return newEncKey;
} }
finally finally
{ {
@@ -171,36 +173,32 @@ namespace Bit.Core.Services
public async Task<byte[]> GetPublicKeyAsync() public async Task<byte[]> GetPublicKeyAsync()
{ {
var inMemoryKey = await _stateService.GetPublicKeyAsync(); if (_publicKey != null)
if (inMemoryKey != null)
{ {
return inMemoryKey; return _publicKey;
} }
var privateKey = await GetPrivateKeyAsync(); var privateKey = await GetPrivateKeyAsync();
if (privateKey == null) if (privateKey == null)
{ {
return null; return null;
} }
inMemoryKey = await _cryptoFunctionService.RsaExtractPublicKeyAsync(privateKey); _publicKey = await _cryptoFunctionService.RsaExtractPublicKeyAsync(privateKey);
await _stateService.SetPublicKeyAsync(inMemoryKey); return _publicKey;
return inMemoryKey;
} }
public async Task<byte[]> GetPrivateKeyAsync() public async Task<byte[]> GetPrivateKeyAsync()
{ {
var inMemoryKey = await _stateService.GetPrivateKeyDecryptedAsync(); if (_privateKey != null)
if (inMemoryKey != null)
{ {
return inMemoryKey; return _privateKey;
} }
var encPrivateKey = await _stateService.GetPrivateKeyEncryptedAsync(); var encPrivateKey = await _stateService.GetPrivateKeyEncryptedAsync();
if (encPrivateKey == null) if (encPrivateKey == null)
{ {
return null; return null;
} }
inMemoryKey = await DecryptToBytesAsync(new EncString(encPrivateKey), null); _privateKey = await DecryptToBytesAsync(new EncString(encPrivateKey), null);
await _stateService.SetPrivateKeyDecryptedAsync(inMemoryKey); return _privateKey;
return inMemoryKey;
} }
public async Task<List<string>> GetFingerprintAsync(string userId, byte[] publicKey = null) public async Task<List<string>> GetFingerprintAsync(string userId, byte[] publicKey = null)
@@ -220,10 +218,9 @@ namespace Bit.Core.Services
public Task<Dictionary<string, SymmetricCryptoKey>> GetOrgKeysAsync() public Task<Dictionary<string, SymmetricCryptoKey>> GetOrgKeysAsync()
{ {
var inMemoryKeys = _stateService.GetOrgKeysDecryptedAsync(); if (_orgKeys != null && _orgKeys.Count > 0)
if (inMemoryKeys != null && inMemoryKeys.Result.Count > 0)
{ {
return inMemoryKeys; return Task.FromResult(_orgKeys);
} }
if (_getOrgKeysTask != null && !_getOrgKeysTask.IsCompleted && !_getOrgKeysTask.IsFaulted) if (_getOrgKeysTask != null && !_getOrgKeysTask.IsCompleted && !_getOrgKeysTask.IsFaulted)
{ {
@@ -249,9 +246,9 @@ namespace Bit.Core.Services
if (setKey) if (setKey)
{ {
await _stateService.SetOrgKeysDecryptedAsync(orgKeys); _orgKeys = orgKeys;
} }
return orgKeys; return _orgKeys;
} }
finally finally
{ {
@@ -312,48 +309,57 @@ namespace Bit.Core.Services
public async Task ClearKeyAsync(string userId = null) public async Task ClearKeyAsync(string userId = null)
{ {
await _stateService.SetKeyDecryptedAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetKeyDecryptedAsync(null, userId);
_legacyEtmKey = null; _legacyEtmKey = null;
await _stateService.SetKeyEncryptedAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetKeyEncryptedAsync(null, userId);
} }
public async Task ClearKeyHashAsync(string userId = null) public async Task ClearKeyHashAsync(string userId = null)
{ {
await _stateService.SetKeyHashCachedAsync(null, new StorageOptions { UserId = userId }); _keyHash = null;
await _stateService.SetKeyHashAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetKeyHashAsync(null, userId);
} }
public async Task ClearEncKeyAsync(bool memoryOnly = false, string userId = null) public async Task ClearEncKeyAsync(bool memoryOnly = false, string userId = null)
{ {
await _stateService.SetEncKeyDecryptedAsync(null, new StorageOptions { UserId = userId }); _encKey = null;
if (!memoryOnly) if (!memoryOnly)
{ {
await _stateService.SetEncKeyEncryptedAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetEncKeyEncryptedAsync(null, userId);
} }
} }
public async Task ClearKeyPairAsync(bool memoryOnly = false, string userId = null) public async Task ClearKeyPairAsync(bool memoryOnly = false, string userId = null)
{ {
await _stateService.SetPublicKeyAsync(null, new StorageOptions { UserId = userId }); _publicKey = _privateKey = null;
await _stateService.SetPrivateKeyDecryptedAsync(null, new StorageOptions { UserId = userId });
if (!memoryOnly) if (!memoryOnly)
{ {
await _stateService.SetPrivateKeyEncryptedAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetPrivateKeyEncryptedAsync(null, userId);
} }
} }
public async Task ClearOrgKeysAsync(bool memoryOnly = false, string userId = null) public async Task ClearOrgKeysAsync(bool memoryOnly = false, string userId = null)
{ {
await _stateService.SetOrgKeysDecryptedAsync(null, new StorageOptions { UserId = userId }); _orgKeys = null;
if (!memoryOnly) if (!memoryOnly)
{ {
await _stateService.SetOrgKeysEncryptedAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetOrgKeysEncryptedAsync(null, userId);
} }
} }
public async Task ClearPinProtectedKeyAsync(string userId = null) public async Task ClearPinProtectedKeyAsync(string userId = null)
{ {
await _stateService.SetPinProtectedAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetPinProtectedAsync(null, userId);
}
public void ClearCache()
{
_encKey = null;
_legacyEtmKey = null;
_keyHash = null;
_publicKey = null;
_privateKey = null;
_orgKeys = null;
} }
public async Task ClearKeysAsync(string userId = null) public async Task ClearKeysAsync(string userId = null)

View File

@@ -192,7 +192,7 @@ namespace Bit.Core.Services
public async Task ClearAsync(string userId) public async Task ClearAsync(string userId)
{ {
await _stateService.SetEncryptedFoldersAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetEncryptedFoldersAsync(null, userId);
_decryptedFolderCache = null; _decryptedFolderCache = null;
} }

View File

@@ -38,7 +38,7 @@ namespace Bit.Core.Services
public async Task<List<Organization>> GetAllAsync(string userId = null) public async Task<List<Organization>> GetAllAsync(string userId = null)
{ {
var organizations = await _stateService.GetOrganizationsAsync(new StorageOptions { UserId = userId }); var organizations = await _stateService.GetOrganizationsAsync(userId);
return organizations?.Select(o => new Organization(o.Value)).ToList() ?? new List<Organization>(); return organizations?.Select(o => new Organization(o.Value)).ToList() ?? new List<Organization>();
} }
@@ -49,7 +49,7 @@ namespace Bit.Core.Services
public async Task ClearAllAsync(string userId) public async Task ClearAllAsync(string userId)
{ {
await _stateService.SetOrganizationsAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetOrganizationsAsync(null, userId);
} }
} }
} }

View File

@@ -483,8 +483,7 @@ namespace Bit.Core.Services
public async Task ClearAsync(string userId = null) public async Task ClearAsync(string userId = null)
{ {
_history = new List<GeneratedPasswordHistory>(); _history = new List<GeneratedPasswordHistory>();
await _stateService.SetEncryptedPasswordGenerationHistoryAsync(null, await _stateService.SetEncryptedPasswordGenerationHistoryAsync(null, userId);
new StorageOptions { UserId = userId });
} }
public Result PasswordStrength(string password, List<string> userInputs = null) public Result PasswordStrength(string password, List<string> userInputs = null)

View File

@@ -60,7 +60,7 @@ namespace Bit.Core.Services
public async Task Clear(string userId) public async Task Clear(string userId)
{ {
await _stateService.SetEncryptedPoliciesAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetEncryptedPoliciesAsync(null, userId);
_policyCache = null; _policyCache = null;
} }

View File

@@ -45,7 +45,7 @@ namespace Bit.Core.Services
public async Task ClearAsync(string userId) public async Task ClearAsync(string userId)
{ {
await _stateService.SetEncryptedSendsAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetEncryptedSendsAsync(null, userId);
ClearCache(); ClearCache();
} }

View File

@@ -2,7 +2,6 @@
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.Core.Models.Domain;
namespace Bit.Core.Services namespace Bit.Core.Services
{ {
@@ -44,7 +43,7 @@ namespace Bit.Core.Services
public async Task ClearAsync(string userId) public async Task ClearAsync(string userId)
{ {
await _stateService.SetSettingsAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetSettingsAsync(null, userId);
ClearCache(); ClearCache();
} }

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,7 @@ namespace Bit.Core.Services
private readonly IPolicyService _policyService; private readonly IPolicyService _policyService;
private readonly ISendService _sendService; private readonly ISendService _sendService;
private readonly IKeyConnectorService _keyConnectorService; private readonly IKeyConnectorService _keyConnectorService;
private readonly Func<bool, Task> _logoutCallbackAsync; private readonly Func<Tuple<string, bool, bool>, Task> _logoutCallbackAsync;
public SyncService( public SyncService(
IStateService stateService, IStateService stateService,
@@ -39,7 +39,7 @@ namespace Bit.Core.Services
IPolicyService policyService, IPolicyService policyService,
ISendService sendService, ISendService sendService,
IKeyConnectorService keyConnectorService, IKeyConnectorService keyConnectorService,
Func<bool, Task> logoutCallbackAsync) Func<Tuple<string, bool, bool>, Task> logoutCallbackAsync)
{ {
_stateService = stateService; _stateService = stateService;
_apiService = apiService; _apiService = apiService;
@@ -316,7 +316,7 @@ namespace Bit.Core.Services
{ {
if (_logoutCallbackAsync != null) if (_logoutCallbackAsync != null)
{ {
await _logoutCallbackAsync(true); await _logoutCallbackAsync(new Tuple<string, bool, bool>(response.Id, false, true));
} }
return; return;
} }

View File

@@ -5,7 +5,6 @@ using System;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Linq; using System.Linq;
using Bit.Core.Models.Domain;
namespace Bit.Core.Services namespace Bit.Core.Services
{ {
@@ -94,25 +93,25 @@ namespace Bit.Core.Services
public async Task SetTwoFactorTokenAsync(string token, string email) public async Task SetTwoFactorTokenAsync(string token, string email)
{ {
await _stateService.SetTwoFactorTokenAsync(token, new StorageOptions { Email = email }); await _stateService.SetTwoFactorTokenAsync(token, email);
} }
public async Task<string> GetTwoFactorTokenAsync(string email) public async Task<string> GetTwoFactorTokenAsync(string email)
{ {
return await _stateService.GetTwoFactorTokenAsync(new StorageOptions { Email = email }); return await _stateService.GetTwoFactorTokenAsync(email);
} }
public async Task ClearTwoFactorTokenAsync(string email) public async Task ClearTwoFactorTokenAsync(string email)
{ {
await _stateService.SetTwoFactorTokenAsync(null, new StorageOptions { Email = email }); await _stateService.SetTwoFactorTokenAsync(null, email);
} }
public async Task ClearTokenAsync(string userId = null) public async Task ClearTokenAsync(string userId = null)
{ {
ClearCache(); ClearCache();
await Task.WhenAll( await Task.WhenAll(
_stateService.SetAccessTokenAsync(null, new StorageOptions { UserId = userId }), _stateService.SetAccessTokenAsync(null, userId),
_stateService.SetRefreshTokenAsync(null, new StorageOptions { UserId = userId })); _stateService.SetRefreshTokenAsync(null, userId));
} }
public void ClearCache() public void ClearCache()

View File

@@ -1,221 +0,0 @@
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
using Bit.Core.Models.Domain;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Bit.Core.Services
{
public class UserService : IUserService
{
private string _userId;
private string _email;
private string _stamp;
private KdfType? _kdf;
private int? _kdfIterations;
private bool? _emailVerified;
private bool? _forcePasswordReset;
private const string Keys_UserId = "userId";
private const string Keys_UserEmail = "userEmail";
private const string Keys_Stamp = "securityStamp";
private const string Keys_Kdf = "kdf";
private const string Keys_KdfIterations = "kdfIterations";
private const string Keys_OrganizationsFormat = "organizations_{0}";
private const string Keys_EmailVerified = "emailVerified";
private const string Keys_ForcePasswordReset = "forcePasswordReset";
private readonly IStorageService _storageService;
private readonly ITokenService _tokenService;
public UserService(IStorageService storageService, ITokenService tokenService)
{
_storageService = storageService;
_tokenService = tokenService;
}
public async Task SetInformationAsync(string userId, string email, KdfType kdf, int? kdfIterations)
{
_email = email;
_userId = userId;
_kdf = kdf;
_kdfIterations = kdfIterations;
await Task.WhenAll(
_storageService.SaveAsync(Keys_UserEmail, email),
_storageService.SaveAsync(Keys_UserId, userId),
_storageService.SaveAsync(Keys_Kdf, (int)kdf),
_storageService.SaveAsync(Keys_KdfIterations, kdfIterations));
}
public async Task SetSecurityStampAsync(string stamp)
{
_stamp = stamp;
await _storageService.SaveAsync(Keys_Stamp, stamp);
}
public async Task SetEmailVerifiedAsync(bool emailVerified)
{
_emailVerified = emailVerified;
await _storageService.SaveAsync(Keys_EmailVerified, emailVerified);
}
public async Task SetForcePasswordReset(bool forcePasswordReset)
{
_forcePasswordReset = forcePasswordReset;
await _storageService.SaveAsync(Keys_ForcePasswordReset, forcePasswordReset);
}
public async Task<string> GetUserIdAsync()
{
if (_userId == null)
{
_userId = await _storageService.GetAsync<string>(Keys_UserId);
}
return _userId;
}
public async Task<string> GetEmailAsync()
{
if (_email == null)
{
_email = await _storageService.GetAsync<string>(Keys_UserEmail);
}
return _email;
}
public async Task<string> GetSecurityStampAsync()
{
if (_stamp == null)
{
_stamp = await _storageService.GetAsync<string>(Keys_Stamp);
}
return _stamp;
}
public async Task<bool> GetEmailVerifiedAsync()
{
if (_emailVerified == null)
{
_emailVerified = await _storageService.GetAsync<bool>(Keys_EmailVerified);
}
return _emailVerified.GetValueOrDefault();
}
public async Task<KdfType?> GetKdfAsync()
{
if (_kdf == null)
{
_kdf = (KdfType?)(await _storageService.GetAsync<int?>(Keys_Kdf));
}
return _kdf;
}
public async Task<int?> GetKdfIterationsAsync()
{
if (_kdfIterations == null)
{
_kdfIterations = await _storageService.GetAsync<int?>(Keys_KdfIterations);
}
return _kdfIterations;
}
public async Task<bool> GetForcePasswordReset()
{
if (_forcePasswordReset == null)
{
_forcePasswordReset = await _storageService.GetAsync<bool>(Keys_ForcePasswordReset);
}
return _forcePasswordReset.GetValueOrDefault();
}
public async Task ClearAsync()
{
var userId = await GetUserIdAsync();
await Task.WhenAll(
_storageService.RemoveAsync(Keys_UserId),
_storageService.RemoveAsync(Keys_UserEmail),
_storageService.RemoveAsync(Keys_Stamp),
_storageService.RemoveAsync(Keys_Kdf),
_storageService.RemoveAsync(Keys_KdfIterations),
_storageService.RemoveAsync(Keys_ForcePasswordReset),
ClearOrganizationsAsync(userId));
_userId = _email = _stamp = null;
_kdf = null;
_kdfIterations = null;
}
public async Task<bool> IsAuthenticatedAsync()
{
var token = await _tokenService.GetTokenAsync();
if (token == null)
{
return false;
}
var userId = await GetUserIdAsync();
return userId != null;
}
public async Task<bool> CanAccessPremiumAsync()
{
var authed = await IsAuthenticatedAsync();
if (!authed)
{
return false;
}
var tokenPremium = _tokenService.GetPremium();
if (tokenPremium)
{
return true;
}
var orgs = await GetAllOrganizationAsync();
return orgs?.Any(o => o.UsersGetPremium && o.Enabled) ?? false;
}
public async Task<Organization> GetOrganizationAsync(string id)
{
var userId = await GetUserIdAsync();
var organizations = await _storageService.GetAsync<Dictionary<string, OrganizationData>>(
string.Format(Keys_OrganizationsFormat, userId));
if (organizations == null || !organizations.ContainsKey(id))
{
return null;
}
return new Organization(organizations[id]);
}
public async Task<Organization> GetOrganizationByIdentifierAsync(string identifier)
{
var userId = await GetUserIdAsync();
var organizations = await GetAllOrganizationAsync();
if (organizations == null || organizations.Count == 0)
{
return null;
}
return organizations.FirstOrDefault(o => o.Identifier == identifier);
}
public async Task<List<Organization>> GetAllOrganizationAsync()
{
var userId = await GetUserIdAsync();
var organizations = await _storageService.GetAsync<Dictionary<string, OrganizationData>>(
string.Format(Keys_OrganizationsFormat, userId));
return organizations?.Select(o => new Organization(o.Value)).ToList() ?? new List<Organization>();
}
public async Task ReplaceOrganizationsAsync(Dictionary<string, OrganizationData> organizations)
{
var userId = await GetUserIdAsync();
await _storageService.SaveAsync(string.Format(Keys_OrganizationsFormat, userId), organizations);
}
public async Task ClearOrganizationsAsync(string userId)
{
await _storageService.RemoveAsync(string.Format(Keys_OrganizationsFormat, userId));
}
}
}

View File

@@ -1,5 +1,4 @@
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Models.Domain;
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -21,7 +20,7 @@ namespace Bit.Core.Services
private readonly IPolicyService _policyService; private readonly IPolicyService _policyService;
private readonly IKeyConnectorService _keyConnectorService; private readonly IKeyConnectorService _keyConnectorService;
private readonly Action<bool> _lockedCallback; private readonly Action<bool> _lockedCallback;
private readonly Func<Tuple<bool, string>, Task> _loggedOutCallback; private readonly Func<Tuple<string, bool, bool>, Task> _loggedOutCallback;
public VaultTimeoutService( public VaultTimeoutService(
ICryptoService cryptoService, ICryptoService cryptoService,
@@ -36,7 +35,7 @@ namespace Bit.Core.Services
IPolicyService policyService, IPolicyService policyService,
IKeyConnectorService keyConnectorService, IKeyConnectorService keyConnectorService,
Action<bool> lockedCallback, Action<bool> lockedCallback,
Func<Tuple<bool, string>, Task> loggedOutCallback) Func<Tuple<string, bool, bool>, Task> loggedOutCallback)
{ {
_cryptoService = cryptoService; _cryptoService = cryptoService;
_stateService = stateService; _stateService = stateService;
@@ -74,18 +73,18 @@ namespace Bit.Core.Services
return; return;
} }
foreach (var account in _stateService.Accounts) foreach (var userId in await _stateService.GetUserIdsAsync())
{ {
if (account.UserId != null && await ShouldLockAsync(account.UserId)) if (userId != null && await ShouldLockAsync(userId))
{ {
await ExecuteTimeoutActionAsync(account.UserId); await ExecuteTimeoutActionAsync(userId);
} }
} }
} }
private async Task<bool> ShouldLockAsync(string userId) private async Task<bool> ShouldLockAsync(string userId)
{ {
var authed = await _stateService.IsAuthenticatedAsync(new StorageOptions { UserId = userId }); var authed = await _stateService.IsAuthenticatedAsync(userId);
if (!authed) if (!authed)
{ {
return false; return false;
@@ -99,7 +98,7 @@ namespace Bit.Core.Services
{ {
return false; return false;
} }
var lastActiveTime = await _stateService.GetLastActiveTimeAsync(new StorageOptions { UserId = userId }); var lastActiveTime = await _stateService.GetLastActiveTimeAsync(userId);
if (lastActiveTime == null) if (lastActiveTime == null)
{ {
return false; return false;
@@ -111,10 +110,10 @@ namespace Bit.Core.Services
private async Task ExecuteTimeoutActionAsync(string userId) private async Task ExecuteTimeoutActionAsync(string userId)
{ {
var action = await _stateService.GetVaultTimeoutActionAsync(new StorageOptions { UserId = userId }); var action = await _stateService.GetVaultTimeoutActionAsync(userId);
if (action == "logOut") if (action == "logOut")
{ {
await LogOutAsync(userId); await LogOutAsync(false, userId);
} }
else else
{ {
@@ -124,7 +123,7 @@ namespace Bit.Core.Services
public async Task LockAsync(bool allowSoftLock = false, bool userInitiated = false, string userId = null) public async Task LockAsync(bool allowSoftLock = false, bool userInitiated = false, string userId = null)
{ {
var authed = await _stateService.IsAuthenticatedAsync(new StorageOptions { UserId = userId }); var authed = await _stateService.IsAuthenticatedAsync(userId);
if (!authed) if (!authed)
{ {
return; return;
@@ -136,7 +135,7 @@ namespace Bit.Core.Services
if (!pinLock && !await IsBiometricLockSetAsync()) if (!pinLock && !await IsBiometricLockSetAsync())
{ {
await LogOutAsync(); await LogOutAsync(userInitiated, userId);
return; return;
} }
} }
@@ -172,11 +171,11 @@ namespace Bit.Core.Services
_lockedCallback?.Invoke(userInitiated); _lockedCallback?.Invoke(userInitiated);
} }
public async Task LogOutAsync(string userId = null) public async Task LogOutAsync(bool userInitiated = true, string userId = null)
{ {
if(_loggedOutCallback != null) if(_loggedOutCallback != null)
{ {
await _loggedOutCallback.Invoke(new Tuple<bool, string>(false, userId)); await _loggedOutCallback.Invoke(new Tuple<string, bool, bool>(userId, userInitiated, false));
} }
} }
@@ -203,8 +202,8 @@ namespace Bit.Core.Services
public async Task ClearAsync(string userId = null) public async Task ClearAsync(string userId = null)
{ {
await _stateService.SetPinProtectedAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetPinProtectedAsync(null, userId);
await _stateService.SetProtectedPinAsync(null, new StorageOptions { UserId = userId }); await _stateService.SetProtectedPinAsync(null, userId);
} }
public async Task<int?> GetVaultTimeout(string userId = null) { public async Task<int?> GetVaultTimeout(string userId = null) {

View File

@@ -30,9 +30,9 @@ namespace Bit.Core.Utilities
SearchService searchService = null; SearchService searchService = null;
var tokenService = new TokenService(stateService); var tokenService = new TokenService(stateService);
var apiService = new ApiService(tokenService, platformUtilsService, (bool expired) => var apiService = new ApiService(tokenService, platformUtilsService, (extras) =>
{ {
messagingService.Send("logout", expired); messagingService.Send("logout", extras);
return Task.FromResult(0); return Task.FromResult(0);
}, customUserAgent); }, customUserAgent);
var appIdService = new AppIdService(stateService); var appIdService = new AppIdService(stateService);
@@ -59,9 +59,9 @@ namespace Bit.Core.Utilities
}); });
var syncService = new SyncService(stateService, apiService, settingsService, folderService, cipherService, var syncService = new SyncService(stateService, apiService, settingsService, folderService, cipherService,
cryptoService, collectionService, organizationService, messagingService, policyService, sendService, cryptoService, collectionService, organizationService, messagingService, policyService, sendService,
keyConnectorService, (bool expired) => keyConnectorService, (extras) =>
{ {
messagingService.Send("logout", expired); messagingService.Send("logout", extras);
return Task.FromResult(0); return Task.FromResult(0);
}); });
var passwordGenerationService = new PasswordGenerationService(cryptoService, stateService, var passwordGenerationService = new PasswordGenerationService(cryptoService, stateService,

View File

@@ -145,7 +145,8 @@ namespace Bit.iOS
{ {
if (_deviceActionService.SystemMajorVersion() >= 12) if (_deviceActionService.SystemMajorVersion() >= 12)
{ {
await ASCredentialIdentityStore.SharedStore?.RemoveAllCredentialIdentitiesAsync(); // TODO make account-specific
// await ASCredentialIdentityStore.SharedStore?.RemoveAllCredentialIdentitiesAsync();
} }
} }
else if ((message.Command == "softDeletedCipher" || message.Command == "restoredCipher") else if ((message.Command == "softDeletedCipher" || message.Command == "restoredCipher")