Vault Timeout Policy (#1530)

This commit is contained in:
Oscar Hinton 2021-09-23 15:42:38 +02:00 committed by GitHub
parent d3c1b58c2a
commit 6023374fbe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 5504 additions and 3526 deletions

View file

@ -309,12 +309,7 @@ namespace Bit.App
{ {
return; return;
} }
// Will only ever be null - look to remove this in the future var vaultTimeout = await _storageService.GetAsync<int?>(Constants.VaultTimeoutKey);
var vaultTimeout = _platformUtilsService.LockTimeout();
if (vaultTimeout == null)
{
vaultTimeout = await _storageService.GetAsync<int?>(Constants.VaultTimeoutKey);
}
vaultTimeout = vaultTimeout.GetValueOrDefault(-1); vaultTimeout = vaultTimeout.GetValueOrDefault(-1);
if (vaultTimeout == 0) if (vaultTimeout == 0)
{ {

View file

@ -21,18 +21,38 @@
x:DataType="pages:SettingsPageListItem"> x:DataType="pages:SettingsPageListItem">
<controls:ExtendedStackLayout Orientation="Horizontal" <controls:ExtendedStackLayout Orientation="Horizontal"
StyleClass="list-row, list-row-platform"> StyleClass="list-row, list-row-platform">
<Label Text="{Binding Name, Mode=OneWay}" <Frame
LineBreakMode="TailTruncation" IsVisible="{Binding UseFrame}"
Padding="10"
HasShadow="False"
BackgroundColor="Transparent"
BorderColor="Accent">
<Label
Text="{Binding Name, Mode=OneWay}"
StyleClass="text-muted, text-sm, text-bold"
HorizontalTextAlignment="Center" />
</Frame>
<Label IsVisible="{Binding UseFrame, Converter={StaticResource inverseBool}}"
Text="{Binding Name, Mode=OneWay}"
LineBreakMode="{Binding LineBreakMode}"
HorizontalOptions="StartAndExpand" HorizontalOptions="StartAndExpand"
VerticalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"
StyleClass="list-title"/> StyleClass="list-title"/>
<Label Text="{Binding SubLabel, Mode=OneWay}" <Label Text="{Binding SubLabel, Mode=OneWay}"
IsVisible="{Binding SubLabel, Converter={StaticResource stringHasValue}}" IsVisible="{Binding ShowSubLabel}"
HorizontalOptions="End" HorizontalOptions="End"
HorizontalTextAlignment="End" HorizontalTextAlignment="End"
VerticalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"
TextColor="{Binding SubLabelColor}" TextColor="{Binding SubLabelColor}"
StyleClass="list-sub" /> StyleClass="list-sub" />
<TimePicker IsVisible="{Binding ShowTimeInput}"
Time="{Binding Time}" Format="HH:mm"
PropertyChanged="OnTimePickerPropertyChanged"
HorizontalOptions="End"
VerticalOptions="Center"
FontSize="Small"
TextColor="{Binding SubLabelColor}"
StyleClass="list-sub" Margin="-5" />
</controls:ExtendedStackLayout> </controls:ExtendedStackLayout>
</DataTemplate> </DataTemplate>

View file

@ -1,4 +1,5 @@
using Bit.App.Abstractions; using System.ComponentModel;
using Bit.App.Abstractions;
using Bit.App.Resources; using Bit.App.Resources;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using System.Linq; using System.Linq;
@ -43,6 +44,16 @@ namespace Bit.App.Pages
return base.OnBackButtonPressed(); return base.OnBackButtonPressed();
} }
async void OnTimePickerPropertyChanged(object sender, PropertyChangedEventArgs args)
{
var s = (TimePicker) sender;
var time = s.Time.TotalMinutes;
if (s.IsFocused && args.PropertyName == "Time")
{
await _vm.VaultTimeoutAsync(false, (int)time);
}
}
private async void RowSelected(object sender, SelectionChangedEventArgs e) private async void RowSelected(object sender, SelectionChangedEventArgs e)
{ {
((ExtendedCollectionView)sender).SelectedItem = null; ((ExtendedCollectionView)sender).SelectedItem = null;

View file

@ -1,4 +1,5 @@
using Bit.App.Resources; using System;
using Bit.App.Resources;
using Bit.App.Utilities; using Bit.App.Utilities;
using System.Collections.Generic; using System.Collections.Generic;
using Xamarin.Forms; using Xamarin.Forms;
@ -10,7 +11,12 @@ namespace Bit.App.Pages
public string Icon { get; set; } public string Icon { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string SubLabel { get; set; } public string SubLabel { get; set; }
public TimeSpan? Time { get; set; }
public bool UseFrame { get; set; }
public bool SubLabelTextEnabled => SubLabel == AppResources.Enabled; public bool SubLabelTextEnabled => SubLabel == AppResources.Enabled;
public string LineBreakMode => SubLabel == null ? "TailTruncation" : "";
public bool ShowSubLabel => SubLabel.Length != 0;
public bool ShowTimeInput => Time != null;
public Color SubLabelColor => SubLabelTextEnabled ? public Color SubLabelColor => SubLabelTextEnabled ?
ThemeManager.GetResourceColor("SuccessColor") : ThemeManager.GetResourceColor("SuccessColor") :
ThemeManager.GetResourceColor("MutedColor"); ThemeManager.GetResourceColor("MutedColor");

View file

@ -7,6 +7,8 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.Core.Enums;
using Bit.Core.Models.Domain;
using Xamarin.Forms; using Xamarin.Forms;
namespace Bit.App.Pages namespace Bit.App.Pages
@ -23,6 +25,9 @@ namespace Bit.App.Pages
private readonly IStorageService _storageService; private readonly IStorageService _storageService;
private readonly ISyncService _syncService; private readonly ISyncService _syncService;
private readonly IBiometricService _biometricService; private readonly IBiometricService _biometricService;
private readonly IPolicyService _policyService;
private const int CustomVaultTimeoutValue = -100;
private bool _supportsBiometric; private bool _supportsBiometric;
private bool _pin; private bool _pin;
@ -42,6 +47,7 @@ namespace Bit.App.Pages
new KeyValuePair<string, int?>(AppResources.FourHours, 240), new KeyValuePair<string, int?>(AppResources.FourHours, 240),
new KeyValuePair<string, int?>(AppResources.OnRestart, -1), new KeyValuePair<string, int?>(AppResources.OnRestart, -1),
new KeyValuePair<string, int?>(AppResources.Never, null), new KeyValuePair<string, int?>(AppResources.Never, null),
new KeyValuePair<string, int?>(AppResources.Custom, CustomVaultTimeoutValue),
}; };
private List<KeyValuePair<string, string>> _vaultTimeoutActions = private List<KeyValuePair<string, string>> _vaultTimeoutActions =
new List<KeyValuePair<string, string>> new List<KeyValuePair<string, string>>
@ -50,6 +56,9 @@ namespace Bit.App.Pages
new KeyValuePair<string, string>(AppResources.LogOut, "logOut"), new KeyValuePair<string, string>(AppResources.LogOut, "logOut"),
}; };
private Policy _vaultTimeoutPolicy;
private int _vaultTimeout;
public SettingsPageViewModel() public SettingsPageViewModel()
{ {
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"); _platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
@ -62,6 +71,7 @@ namespace Bit.App.Pages
_storageService = ServiceContainer.Resolve<IStorageService>("storageService"); _storageService = ServiceContainer.Resolve<IStorageService>("storageService");
_syncService = ServiceContainer.Resolve<ISyncService>("syncService"); _syncService = ServiceContainer.Resolve<ISyncService>("syncService");
_biometricService = ServiceContainer.Resolve<IBiometricService>("biometricService"); _biometricService = ServiceContainer.Resolve<IBiometricService>("biometricService");
_policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
GroupedItems = new ExtendedObservableCollection<SettingsPageListGroup>(); GroupedItems = new ExtendedObservableCollection<SettingsPageListGroup>();
PageTitle = AppResources.Settings; PageTitle = AppResources.Settings;
@ -79,13 +89,30 @@ namespace Bit.App.Pages
_lastSyncDate = string.Format("{0} {1}", lastSync.Value.ToShortDateString(), _lastSyncDate = string.Format("{0} {1}", lastSync.Value.ToShortDateString(),
lastSync.Value.ToShortTimeString()); lastSync.Value.ToShortTimeString());
} }
var timeout = await _storageService.GetAsync<int?>(Constants.VaultTimeoutKey);
_vaultTimeoutDisplayValue = _vaultTimeouts.FirstOrDefault(o => o.Value == timeout).Key; if (await _policyService.PolicyAppliesToUser(PolicyType.MaximumVaultTimeout))
{
_vaultTimeoutPolicy = (await _policyService.GetAll(PolicyType.MaximumVaultTimeout)).First();
var minutes = _policyService.GetPolicyInt(_vaultTimeoutPolicy, "minutes").GetValueOrDefault();
_vaultTimeouts = _vaultTimeouts.Where(t =>
t.Value <= minutes &&
(t.Value > 0 || t.Value == CustomVaultTimeoutValue) &&
t.Value != null).ToList();
}
_vaultTimeout = await _vaultTimeoutService.GetVaultTimeout();
_vaultTimeoutDisplayValue = _vaultTimeouts.FirstOrDefault(o => o.Value == _vaultTimeout).Key;
var action = await _storageService.GetAsync<string>(Constants.VaultTimeoutActionKey) ?? "lock"; var action = await _storageService.GetAsync<string>(Constants.VaultTimeoutActionKey) ?? "lock";
_vaultTimeoutActionDisplayValue = _vaultTimeoutActions.FirstOrDefault(o => o.Value == action).Key; _vaultTimeoutActionDisplayValue = _vaultTimeoutActions.FirstOrDefault(o => o.Value == action).Key;
var pinSet = await _vaultTimeoutService.IsPinLockSetAsync(); var pinSet = await _vaultTimeoutService.IsPinLockSetAsync();
_pin = pinSet.Item1 || pinSet.Item2; _pin = pinSet.Item1 || pinSet.Item2;
_biometric = await _vaultTimeoutService.IsBiometricLockSetAsync(); _biometric = await _vaultTimeoutService.IsBiometricLockSetAsync();
if (_vaultTimeoutDisplayValue == null)
{
_vaultTimeoutDisplayValue = AppResources.Custom;
}
BuildList(); BuildList();
} }
@ -193,22 +220,51 @@ namespace Bit.App.Pages
await _vaultTimeoutService.LockAsync(true, true); await _vaultTimeoutService.LockAsync(true, true);
} }
public async Task VaultTimeoutAsync() public async Task VaultTimeoutAsync(bool promptOptions = true, int newTimeout = 0)
{ {
var oldTimeout = _vaultTimeout;
var options = _vaultTimeouts.Select( var options = _vaultTimeouts.Select(
o => o.Key == _vaultTimeoutDisplayValue ? $"✓ {o.Key}" : o.Key).ToArray(); o => o.Key == _vaultTimeoutDisplayValue ? $"✓ {o.Key}" : o.Key).ToArray();
var selection = await Page.DisplayActionSheet(AppResources.VaultTimeout, if (promptOptions)
AppResources.Cancel, null, options);
if (selection == null || selection == AppResources.Cancel)
{ {
return; var selection = await Page.DisplayActionSheet(AppResources.VaultTimeout,
AppResources.Cancel, null, options);
if (selection == null || selection == AppResources.Cancel)
{
return;
}
var cleanSelection = selection.Replace("✓ ", string.Empty);
var selectionOption = _vaultTimeouts.FirstOrDefault(o => o.Key == cleanSelection);
_vaultTimeoutDisplayValue = selectionOption.Key;
newTimeout = selectionOption.Value.GetValueOrDefault();
} }
var cleanSelection = selection.Replace("✓ ", string.Empty);
var selectionOption = _vaultTimeouts.FirstOrDefault(o => o.Key == cleanSelection); if (_vaultTimeoutPolicy != null)
_vaultTimeoutDisplayValue = selectionOption.Key; {
await _vaultTimeoutService.SetVaultTimeoutOptionsAsync(selectionOption.Value, var maximumTimeout = _policyService.GetPolicyInt(_vaultTimeoutPolicy, "minutes");
if (newTimeout > maximumTimeout)
{
await _platformUtilsService.ShowDialogAsync(AppResources.VaultTimeoutToLarge, AppResources.Warning);
var timeout = await _vaultTimeoutService.GetVaultTimeout();
_vaultTimeoutDisplayValue = _vaultTimeouts.FirstOrDefault(o => o.Value == timeout).Key ??
AppResources.Custom;
return;
}
}
await _vaultTimeoutService.SetVaultTimeoutOptionsAsync(newTimeout,
GetVaultTimeoutActionFromKey(_vaultTimeoutActionDisplayValue)); GetVaultTimeoutActionFromKey(_vaultTimeoutActionDisplayValue));
BuildList();
if (newTimeout != CustomVaultTimeoutValue)
{
_vaultTimeout = newTimeout;
}
if (oldTimeout != newTimeout)
{
await Device.InvokeOnMainThreadAsync(BuildList);
}
} }
public async Task VaultTimeoutActionAsync() public async Task VaultTimeoutActionAsync()
@ -235,7 +291,7 @@ namespace Bit.App.Pages
var selectionOption = _vaultTimeoutActions.FirstOrDefault(o => o.Key == cleanSelection); var selectionOption = _vaultTimeoutActions.FirstOrDefault(o => o.Key == cleanSelection);
var changed = _vaultTimeoutActionDisplayValue != selectionOption.Key; var changed = _vaultTimeoutActionDisplayValue != selectionOption.Key;
_vaultTimeoutActionDisplayValue = selectionOption.Key; _vaultTimeoutActionDisplayValue = selectionOption.Key;
await _vaultTimeoutService.SetVaultTimeoutOptionsAsync(GetVaultTimeoutFromKey(_vaultTimeoutDisplayValue), await _vaultTimeoutService.SetVaultTimeoutOptionsAsync(_vaultTimeout,
selectionOption.Value); selectionOption.Value);
if (changed) if (changed)
{ {
@ -362,6 +418,25 @@ namespace Bit.App.Pages
new SettingsPageListItem { Name = AppResources.LockNow }, new SettingsPageListItem { Name = AppResources.LockNow },
new SettingsPageListItem { Name = AppResources.TwoStepLogin } new SettingsPageListItem { Name = AppResources.TwoStepLogin }
}; };
if (_vaultTimeoutDisplayValue == AppResources.Custom)
{
securityItems.Insert(1, new SettingsPageListItem
{
Name = AppResources.Custom,
Time = TimeSpan.FromMinutes(Math.Abs((double) _vaultTimeout)),
});
}
if (_vaultTimeoutPolicy != null)
{
var maximumTimeout = _policyService.GetPolicyInt(_vaultTimeoutPolicy, "minutes").GetValueOrDefault();
securityItems.Insert(0, new SettingsPageListItem
{
Name = string.Format(AppResources.VaultTimeoutPolicyInEffect,
Math.Floor((float) maximumTimeout / 60),
maximumTimeout % 60),
UseFrame = true,
});
}
if (_supportsBiometric || _biometric) if (_supportsBiometric || _biometric)
{ {
var biometricName = AppResources.Biometrics; var biometricName = AppResources.Biometrics;

File diff suppressed because it is too large Load diff

View file

@ -2034,4 +2034,10 @@
<data name="ResetPasswordAutoEnrollInviteWarning" xml:space="preserve"> <data name="ResetPasswordAutoEnrollInviteWarning" xml:space="preserve">
<value>This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password.</value> <value>This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password.</value>
</data> </data>
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
<value>Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is {0} hour(s) and {1} minute(s)</value>
</data>
<data name="VaultTimeoutToLarge" xml:space="preserve">
<value>Your vault timeout exceeds the restrictions set by your organization.</value>
</data>
</root> </root>

View file

@ -84,11 +84,6 @@ namespace Bit.App.Services
return false; return false;
} }
public int? LockTimeout()
{
return null;
}
public void LaunchUri(string uri, Dictionary<string, object> options = null) public void LaunchUri(string uri, Dictionary<string, object> options = null)
{ {
if ((uri.StartsWith("http://") || uri.StartsWith("https://")) && if ((uri.StartsWith("http://") || uri.StartsWith("https://")) &&

View file

@ -17,7 +17,6 @@ namespace Bit.Core.Abstractions
bool IsSelfHost(); bool IsSelfHost();
bool IsViewOpen(); bool IsViewOpen();
void LaunchUri(string uri, Dictionary<string, object> options = null); void LaunchUri(string uri, Dictionary<string, object> options = null);
int? LockTimeout();
Task<string> ReadFromClipboardAsync(Dictionary<string, object> options = null); Task<string> ReadFromClipboardAsync(Dictionary<string, object> options = null);
void SaveFile(); void SaveFile();
Task<bool> ShowDialogAsync(string text, string title = null, string confirmText = null, Task<bool> ShowDialogAsync(string text, string title = null, string confirmText = null,

View file

@ -18,5 +18,7 @@ namespace Bit.Core.Abstractions
MasterPasswordPolicyOptions enforcedPolicyOptions); MasterPasswordPolicyOptions enforcedPolicyOptions);
Tuple<ResetPasswordPolicyOptions, bool> GetResetPasswordPolicyOptions(IEnumerable<Policy> policies, Tuple<ResetPasswordPolicyOptions, bool> GetResetPasswordPolicyOptions(IEnumerable<Policy> policies,
string orgId); string orgId);
Task<bool> PolicyAppliesToUser(PolicyType policyType, Func<Policy, bool> policyFilter = null);
int? GetPolicyInt(Policy policy, string key);
} }
} }

View file

@ -17,5 +17,6 @@ namespace Bit.Core.Abstractions
Task LockAsync(bool allowSoftLock = false, bool userInitiated = false); Task LockAsync(bool allowSoftLock = false, bool userInitiated = false);
Task LogOutAsync(); Task LogOutAsync();
Task SetVaultTimeoutOptionsAsync(int? timeout, string action); Task SetVaultTimeoutOptionsAsync(int? timeout, string action);
Task<int> GetVaultTimeout();
} }
} }

View file

@ -11,5 +11,6 @@
DisableSend = 6, // Disables the ability to create and edit Sends DisableSend = 6, // Disables the ability to create and edit Sends
SendOptions = 7, // Sets restrictions or defaults for Bitwarden Sends SendOptions = 7, // Sets restrictions or defaults for Bitwarden Sends
ResetPassword = 8, // Allows orgs to use reset password : also can enable auto-enrollment during invite flow ResetPassword = 8, // Allows orgs to use reset password : also can enable auto-enrollment during invite flow
MaximumVaultTimeout = 9, // Sets the maximum allowed vault timeout
} }
} }

View file

@ -91,5 +91,6 @@ namespace Bit.Core.Models.Domain
public bool canManageGroups => IsAdmin || Permissions.ManageGroups; public bool canManageGroups => IsAdmin || Permissions.ManageGroups;
public bool canManagePolicies => IsAdmin || Permissions.ManagePolicies; public bool canManagePolicies => IsAdmin || Permissions.ManagePolicies;
public bool canManageUser => IsAdmin || Permissions.ManageUsers; public bool canManageUser => IsAdmin || Permissions.ManageUsers;
public bool IsExemptFromPolicies => canManagePolicies;
} }
} }

View file

@ -197,8 +197,33 @@ namespace Bit.Core.Services
return new Tuple<ResetPasswordPolicyOptions, bool>(resetPasswordPolicyOptions, policy != null); return new Tuple<ResetPasswordPolicyOptions, bool>(resetPasswordPolicyOptions, policy != null);
} }
private int? GetPolicyInt(Policy policy, string key) public async Task<bool> PolicyAppliesToUser(PolicyType policyType, Func<Policy, bool> policyFilter = null)
{
if (policyFilter == null) {
policyFilter = _ => true;
}
var policies = await GetAll(policyType);
var organizations = await _userService.GetAllOrganizationAsync();
var filteredPolicies = policies.Where(p =>
p.Enabled &&
p.Type == policyType &&
policyFilter(p))
.Select(p => p.OrganizationId);
var policySet = filteredPolicies.Distinct();
return organizations.Any(o =>
o.Enabled &&
o.Status >= OrganizationUserStatusType.Accepted &&
o.UsePolicies &&
!o.IsExemptFromPolicies &&
policySet.Distinct().Contains(o.Id));
}
public int? GetPolicyInt(Policy policy, string key)
{ {
if (policy.Data.ContainsKey(key)) if (policy.Data.ContainsKey(key))
{ {

View file

@ -1,7 +1,9 @@
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Models.Domain; using Bit.Core.Models.Domain;
using System; using System;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.Core.Enums;
namespace Bit.Core.Services namespace Bit.Core.Services
{ {
@ -17,6 +19,7 @@ namespace Bit.Core.Services
private readonly ISearchService _searchService; private readonly ISearchService _searchService;
private readonly IMessagingService _messagingService; private readonly IMessagingService _messagingService;
private readonly ITokenService _tokenService; private readonly ITokenService _tokenService;
private readonly IPolicyService _policyService;
private readonly Action<bool> _lockedCallback; private readonly Action<bool> _lockedCallback;
private readonly Func<bool, Task> _loggedOutCallback; private readonly Func<bool, Task> _loggedOutCallback;
@ -31,6 +34,7 @@ namespace Bit.Core.Services
ISearchService searchService, ISearchService searchService,
IMessagingService messagingService, IMessagingService messagingService,
ITokenService tokenService, ITokenService tokenService,
IPolicyService policyService,
Action<bool> lockedCallback, Action<bool> lockedCallback,
Func<bool, Task> loggedOutCallback) Func<bool, Task> loggedOutCallback)
{ {
@ -44,6 +48,7 @@ namespace Bit.Core.Services
_searchService = searchService; _searchService = searchService;
_messagingService = messagingService; _messagingService = messagingService;
_tokenService = tokenService; _tokenService = tokenService;
_policyService = policyService;
_lockedCallback = lockedCallback; _lockedCallback = lockedCallback;
_loggedOutCallback = loggedOutCallback; _loggedOutCallback = loggedOutCallback;
} }
@ -80,13 +85,8 @@ namespace Bit.Core.Services
{ {
return; return;
} }
// This only returns null var vaultTimeoutMinutes = await GetVaultTimeout();
var vaultTimeoutMinutes = _platformUtilsService.LockTimeout(); if (vaultTimeoutMinutes < 0)
if (vaultTimeoutMinutes == null)
{
vaultTimeoutMinutes = await _storageService.GetAsync<int?>(Constants.VaultTimeoutKey);
}
if (vaultTimeoutMinutes.GetValueOrDefault(-1) < 0)
{ {
return; return;
} }
@ -177,5 +177,34 @@ namespace Bit.Core.Services
PinProtectedKey = null; PinProtectedKey = null;
await _storageService.RemoveAsync(Constants.ProtectedPin); await _storageService.RemoveAsync(Constants.ProtectedPin);
} }
public async Task<int> GetVaultTimeout() {
var vaultTimeout = (await _storageService.GetAsync<int?>(Constants.VaultTimeoutKey)).GetValueOrDefault(-1);
if (await _policyService.PolicyAppliesToUser(PolicyType.MaximumVaultTimeout)) {
var policy = (await _policyService.GetAll(PolicyType.MaximumVaultTimeout)).First();
// Remove negative values, and ensure it's smaller than maximum allowed value according to policy
var policyTimeout = _policyService.GetPolicyInt(policy, "minutes");
if (!policyTimeout.HasValue)
{
return vaultTimeout;
}
var timeout = Math.Min(vaultTimeout, policyTimeout.Value);
if (timeout < 0) {
timeout = policyTimeout.Value;
}
// We really shouldn't need to set the value here, but multiple services relies on this value being correct.
if (vaultTimeout != timeout) {
await _storageService.SaveAsync(Constants.VaultTimeoutKey, timeout);
}
return timeout;
}
return vaultTimeout;
}
} }
} }

View file

@ -48,14 +48,14 @@ namespace Bit.Core.Utilities
var sendService = new SendService(cryptoService, userService, apiService, fileUploadService, storageService, var sendService = new SendService(cryptoService, userService, apiService, fileUploadService, storageService,
i18nService, cryptoFunctionService); i18nService, cryptoFunctionService);
searchService = new SearchService(cipherService, sendService); searchService = new SearchService(cipherService, sendService);
var vaultTimeoutService = new VaultTimeoutService(cryptoService, userService, platformUtilsService, var policyService = new PolicyService(storageService, userService);
var vaultTimeoutService = new VaultTimeoutService(cryptoService, userService, platformUtilsService,
storageService, folderService, cipherService, collectionService, searchService, messagingService, tokenService, storageService, folderService, cipherService, collectionService, searchService, messagingService, tokenService,
null, (expired) => policyService, null, (expired) =>
{ {
messagingService.Send("logout", expired); messagingService.Send("logout", expired);
return Task.FromResult(0); return Task.FromResult(0);
}); });
var policyService = new PolicyService(storageService, userService);
var syncService = new SyncService(userService, apiService, settingsService, folderService, var syncService = new SyncService(userService, apiService, settingsService, folderService,
cipherService, cryptoService, collectionService, storageService, messagingService, policyService, sendService, cipherService, cryptoService, collectionService, storageService, messagingService, policyService, sendService,
(bool expired) => (bool expired) =>