mirror of
https://github.com/bitwarden/mobile
synced 2025-12-18 01:03:24 +00:00
wip
This commit is contained in:
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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}";
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
Reference in New Issue
Block a user