mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 07:05:35 +03:00
[AC-1045] vault timeout action policy (#2415)
* [EC-1045] lock action if policy and show message * [EC-1045] add text for policy message * [EC-1045] add consts to policy service * [EC-1045] missed a const * [AC-1045] fix build * [AC-1045] fix bug where UI wasn't updating after sync * [AC-1045] change FirstOrDefault to First to avoid nulls * [AC-1045] refactor get vault timeout functions * [AC-1045] don't filter action options unecessarily * [AC-1045] refactor build alert logic for readability * [AC-1045] use policy to filter timeout options instead of current timeout * [AC-1045] update timeout during sync instead of getter - remove encrypted from state since it's not encrypted - if policies return a timeout policy, check and update vault timeout * [AC-1045] default to custom if we can't find vault timeout option * [AC-1045] revert Encrypted Policies rename
This commit is contained in:
parent
cc75cebdb8
commit
a72f267558
9 changed files with 144 additions and 76 deletions
|
@ -7,10 +7,7 @@ using Bit.App.Pages.Accounts;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Models;
|
|
||||||
using Bit.Core.Models.Domain;
|
using Bit.Core.Models.Domain;
|
||||||
using Bit.Core.Models.Response;
|
|
||||||
using Bit.Core.Models.View;
|
|
||||||
using Bit.Core.Services;
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Xamarin.CommunityToolkit.ObjectModel;
|
using Xamarin.CommunityToolkit.ObjectModel;
|
||||||
|
@ -51,7 +48,7 @@ namespace Bit.App.Pages
|
||||||
private bool _reportLoggingEnabled;
|
private bool _reportLoggingEnabled;
|
||||||
private bool _approvePasswordlessLoginRequests;
|
private bool _approvePasswordlessLoginRequests;
|
||||||
private bool _shouldConnectToWatch;
|
private bool _shouldConnectToWatch;
|
||||||
private List<KeyValuePair<string, int?>> _vaultTimeouts =
|
private readonly static List<KeyValuePair<string, int?>> VaultTimeoutOptions =
|
||||||
new List<KeyValuePair<string, int?>>
|
new List<KeyValuePair<string, int?>>
|
||||||
{
|
{
|
||||||
new KeyValuePair<string, int?>(AppResources.Immediately, 0),
|
new KeyValuePair<string, int?>(AppResources.Immediately, 0),
|
||||||
|
@ -65,7 +62,7 @@ namespace Bit.App.Pages
|
||||||
new KeyValuePair<string, int?>(AppResources.Never, null),
|
new KeyValuePair<string, int?>(AppResources.Never, null),
|
||||||
new KeyValuePair<string, int?>(AppResources.Custom, CustomVaultTimeoutValue),
|
new KeyValuePair<string, int?>(AppResources.Custom, CustomVaultTimeoutValue),
|
||||||
};
|
};
|
||||||
private List<KeyValuePair<string, VaultTimeoutAction>> _vaultTimeoutActions =
|
private readonly static List<KeyValuePair<string, VaultTimeoutAction>> VaultTimeoutActionOptions =
|
||||||
new List<KeyValuePair<string, VaultTimeoutAction>>
|
new List<KeyValuePair<string, VaultTimeoutAction>>
|
||||||
{
|
{
|
||||||
new KeyValuePair<string, VaultTimeoutAction>(AppResources.Lock, VaultTimeoutAction.Lock),
|
new KeyValuePair<string, VaultTimeoutAction>(AppResources.Lock, VaultTimeoutAction.Lock),
|
||||||
|
@ -74,6 +71,8 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
private Policy _vaultTimeoutPolicy;
|
private Policy _vaultTimeoutPolicy;
|
||||||
private int? _vaultTimeout;
|
private int? _vaultTimeout;
|
||||||
|
private List<KeyValuePair<string, int?>> _vaultTimeoutOptions = VaultTimeoutOptions;
|
||||||
|
private List<KeyValuePair<string, VaultTimeoutAction>> _vaultTimeoutActionOptions = VaultTimeoutActionOptions;
|
||||||
|
|
||||||
public SettingsPageViewModel()
|
public SettingsPageViewModel()
|
||||||
{
|
{
|
||||||
|
@ -117,20 +116,28 @@ namespace Bit.App.Pages
|
||||||
_localizeService.GetLocaleShortTime(lastSync.Value));
|
_localizeService.GetLocaleShortTime(lastSync.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_vaultTimeoutPolicy = null;
|
||||||
|
_vaultTimeoutOptions = VaultTimeoutOptions;
|
||||||
|
_vaultTimeoutActionOptions = VaultTimeoutActionOptions;
|
||||||
|
|
||||||
|
_vaultTimeout = await _vaultTimeoutService.GetVaultTimeout();
|
||||||
|
_vaultTimeoutDisplayValue = _vaultTimeoutOptions.FirstOrDefault(o => o.Value == _vaultTimeout).Key;
|
||||||
|
_vaultTimeoutDisplayValue ??= _vaultTimeoutOptions.Where(o => o.Value == CustomVaultTimeoutValue).First().Key;
|
||||||
|
|
||||||
|
var action = await _vaultTimeoutService.GetVaultTimeoutAction() ?? VaultTimeoutAction.Lock;
|
||||||
|
_vaultTimeoutActionDisplayValue = _vaultTimeoutActionOptions.FirstOrDefault(o => o.Value == action).Key;
|
||||||
|
|
||||||
if (await _policyService.PolicyAppliesToUser(PolicyType.MaximumVaultTimeout))
|
if (await _policyService.PolicyAppliesToUser(PolicyType.MaximumVaultTimeout))
|
||||||
{
|
{
|
||||||
|
// if we have a vault timeout policy, we need to filter the timeout options
|
||||||
_vaultTimeoutPolicy = (await _policyService.GetAll(PolicyType.MaximumVaultTimeout)).First();
|
_vaultTimeoutPolicy = (await _policyService.GetAll(PolicyType.MaximumVaultTimeout)).First();
|
||||||
var minutes = _policyService.GetPolicyInt(_vaultTimeoutPolicy, "minutes").GetValueOrDefault();
|
var policyMinutes = _policyService.GetPolicyInt(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_MINUTES);
|
||||||
_vaultTimeouts = _vaultTimeouts.Where(t =>
|
_vaultTimeoutOptions = _vaultTimeoutOptions.Where(t =>
|
||||||
t.Value <= minutes &&
|
t.Value <= policyMinutes &&
|
||||||
(t.Value > 0 || t.Value == CustomVaultTimeoutValue) &&
|
(t.Value > 0 || t.Value == CustomVaultTimeoutValue) &&
|
||||||
t.Value != null).ToList();
|
t.Value != null).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
_vaultTimeout = await _vaultTimeoutService.GetVaultTimeout();
|
|
||||||
_vaultTimeoutDisplayValue = _vaultTimeouts.FirstOrDefault(o => o.Value == _vaultTimeout).Key;
|
|
||||||
var action = await _stateService.GetVaultTimeoutActionAsync() ?? VaultTimeoutAction.Lock;
|
|
||||||
_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();
|
||||||
|
@ -266,7 +273,7 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
var oldTimeout = _vaultTimeout;
|
var oldTimeout = _vaultTimeout;
|
||||||
|
|
||||||
var options = _vaultTimeouts.Select(
|
var options = _vaultTimeoutOptions.Select(
|
||||||
o => o.Key == _vaultTimeoutDisplayValue ? $"✓ {o.Key}" : o.Key).ToArray();
|
o => o.Key == _vaultTimeoutDisplayValue ? $"✓ {o.Key}" : o.Key).ToArray();
|
||||||
if (promptOptions)
|
if (promptOptions)
|
||||||
{
|
{
|
||||||
|
@ -277,7 +284,7 @@ namespace Bit.App.Pages
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var cleanSelection = selection.Replace("✓ ", string.Empty);
|
var cleanSelection = selection.Replace("✓ ", string.Empty);
|
||||||
var selectionOption = _vaultTimeouts.FirstOrDefault(o => o.Key == cleanSelection);
|
var selectionOption = _vaultTimeoutOptions.FirstOrDefault(o => o.Key == cleanSelection);
|
||||||
|
|
||||||
// Check if the selected Timeout action is "Never" and if it's different from the previous selected value
|
// Check if the selected Timeout action is "Never" and if it's different from the previous selected value
|
||||||
if (selectionOption.Value == null && selectionOption.Value != oldTimeout)
|
if (selectionOption.Value == null && selectionOption.Value != oldTimeout)
|
||||||
|
@ -295,13 +302,13 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
if (_vaultTimeoutPolicy != null)
|
if (_vaultTimeoutPolicy != null)
|
||||||
{
|
{
|
||||||
var maximumTimeout = _policyService.GetPolicyInt(_vaultTimeoutPolicy, "minutes");
|
var maximumTimeout = _policyService.GetPolicyInt(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_MINUTES);
|
||||||
|
|
||||||
if (newTimeout > maximumTimeout)
|
if (newTimeout > maximumTimeout)
|
||||||
{
|
{
|
||||||
await _platformUtilsService.ShowDialogAsync(AppResources.VaultTimeoutToLarge, AppResources.Warning);
|
await _platformUtilsService.ShowDialogAsync(AppResources.VaultTimeoutToLarge, AppResources.Warning);
|
||||||
var timeout = await _vaultTimeoutService.GetVaultTimeout();
|
var timeout = await _vaultTimeoutService.GetVaultTimeout();
|
||||||
_vaultTimeoutDisplayValue = _vaultTimeouts.FirstOrDefault(o => o.Value == timeout).Key ??
|
_vaultTimeoutDisplayValue = _vaultTimeoutOptions.FirstOrDefault(o => o.Value == timeout).Key ??
|
||||||
AppResources.Custom;
|
AppResources.Custom;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -374,7 +381,13 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public async Task VaultTimeoutActionAsync()
|
public async Task VaultTimeoutActionAsync()
|
||||||
{
|
{
|
||||||
var options = _vaultTimeoutActions.Select(o =>
|
if (_vaultTimeoutPolicy != null &&
|
||||||
|
!string.IsNullOrEmpty(_policyService.GetPolicyString(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_ACTION)))
|
||||||
|
{
|
||||||
|
// do nothing if we have a policy set
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var options = _vaultTimeoutActionOptions.Select(o =>
|
||||||
o.Key == _vaultTimeoutActionDisplayValue ? $"✓ {o.Key}" : o.Key).ToArray();
|
o.Key == _vaultTimeoutActionDisplayValue ? $"✓ {o.Key}" : o.Key).ToArray();
|
||||||
var selection = await Page.DisplayActionSheet(AppResources.VaultTimeoutAction,
|
var selection = await Page.DisplayActionSheet(AppResources.VaultTimeoutAction,
|
||||||
AppResources.Cancel, null, options);
|
AppResources.Cancel, null, options);
|
||||||
|
@ -393,7 +406,7 @@ namespace Bit.App.Pages
|
||||||
cleanSelection = AppResources.Lock;
|
cleanSelection = AppResources.Lock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var selectionOption = _vaultTimeoutActions.FirstOrDefault(o => o.Key == cleanSelection);
|
var selectionOption = _vaultTimeoutActionOptions.FirstOrDefault(o => o.Key == cleanSelection);
|
||||||
var changed = _vaultTimeoutActionDisplayValue != selectionOption.Key;
|
var changed = _vaultTimeoutActionDisplayValue != selectionOption.Key;
|
||||||
_vaultTimeoutActionDisplayValue = selectionOption.Key;
|
_vaultTimeoutActionDisplayValue = selectionOption.Key;
|
||||||
await _vaultTimeoutService.SetVaultTimeoutOptionsAsync(_vaultTimeout,
|
await _vaultTimeoutService.SetVaultTimeoutOptionsAsync(_vaultTimeout,
|
||||||
|
@ -597,14 +610,36 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
if (_vaultTimeoutPolicy != null)
|
if (_vaultTimeoutPolicy != null)
|
||||||
{
|
{
|
||||||
var maximumTimeout = _policyService.GetPolicyInt(_vaultTimeoutPolicy, "minutes").GetValueOrDefault();
|
var policyMinutes = _policyService.GetPolicyInt(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_MINUTES);
|
||||||
securityItems.Insert(0, new SettingsPageListItem
|
var policyAction = _policyService.GetPolicyString(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_ACTION);
|
||||||
|
|
||||||
|
if (policyMinutes.HasValue || !string.IsNullOrWhiteSpace(policyAction))
|
||||||
{
|
{
|
||||||
Name = string.Format(AppResources.VaultTimeoutPolicyInEffect,
|
string policyAlert;
|
||||||
Math.Floor((float)maximumTimeout / 60),
|
if (policyMinutes.HasValue && string.IsNullOrWhiteSpace(policyAction))
|
||||||
maximumTimeout % 60),
|
{
|
||||||
UseFrame = true,
|
policyAlert = string.Format(AppResources.VaultTimeoutPolicyInEffect,
|
||||||
});
|
Math.Floor((float)policyMinutes / 60),
|
||||||
|
policyMinutes % 60);
|
||||||
|
}
|
||||||
|
else if (!policyMinutes.HasValue && !string.IsNullOrWhiteSpace(policyAction))
|
||||||
|
{
|
||||||
|
policyAlert = string.Format(AppResources.VaultTimeoutActionPolicyInEffect,
|
||||||
|
policyAction == PolicyService.TIMEOUT_POLICY_ACTION_LOCK ? AppResources.Lock : AppResources.LogOut);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
policyAlert = string.Format(AppResources.VaultTimeoutPolicyWithActionInEffect,
|
||||||
|
Math.Floor((float)policyMinutes / 60),
|
||||||
|
policyMinutes % 60,
|
||||||
|
policyAction == PolicyService.TIMEOUT_POLICY_ACTION_LOCK ? AppResources.Lock : AppResources.LogOut);
|
||||||
|
}
|
||||||
|
securityItems.Insert(0, new SettingsPageListItem
|
||||||
|
{
|
||||||
|
Name = policyAlert,
|
||||||
|
UseFrame = true,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (Device.RuntimePlatform == Device.Android)
|
if (Device.RuntimePlatform == Device.Android)
|
||||||
{
|
{
|
||||||
|
@ -792,12 +827,12 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
private VaultTimeoutAction GetVaultTimeoutActionFromKey(string key)
|
private VaultTimeoutAction GetVaultTimeoutActionFromKey(string key)
|
||||||
{
|
{
|
||||||
return _vaultTimeoutActions.FirstOrDefault(o => o.Key == key).Value;
|
return _vaultTimeoutActionOptions.FirstOrDefault(o => o.Key == key).Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int? GetVaultTimeoutFromKey(string key)
|
private int? GetVaultTimeoutFromKey(string key)
|
||||||
{
|
{
|
||||||
return _vaultTimeouts.FirstOrDefault(o => o.Key == key).Value;
|
return _vaultTimeoutOptions.FirstOrDefault(o => o.Key == key).Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string CreateSelectableOption(string option, bool selected) => selected ? $"✓ {option}" : option;
|
private string CreateSelectableOption(string option, bool selected) => selected ? $"✓ {option}" : option;
|
||||||
|
|
20
src/App/Resources/AppResources.Designer.cs
generated
20
src/App/Resources/AppResources.Designer.cs
generated
|
@ -6677,6 +6677,15 @@ namespace Bit.App.Resources {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Your organization policies have set your vault timeout action to {0}..
|
||||||
|
/// </summary>
|
||||||
|
public static string VaultTimeoutActionPolicyInEffect {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("VaultTimeoutActionPolicyInEffect", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?.
|
/// Looks up a localized string similar to Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -6687,7 +6696,7 @@ namespace Bit.App.Resources {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is {0} hour(s) and {1} minute(s).
|
/// Looks up a localized string similar to Your organization policies have set your maximum allowed vault timeout to {0} hour(s) and {1} minute(s)..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string VaultTimeoutPolicyInEffect {
|
public static string VaultTimeoutPolicyInEffect {
|
||||||
get {
|
get {
|
||||||
|
@ -6695,6 +6704,15 @@ namespace Bit.App.Resources {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is {0} hour(s) and {1} minute(s). Your vault timeout action is set to {2}..
|
||||||
|
/// </summary>
|
||||||
|
public static string VaultTimeoutPolicyWithActionInEffect {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("VaultTimeoutPolicyWithActionInEffect", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Your vault timeout exceeds the restrictions set by your organization..
|
/// Looks up a localized string similar to Your vault timeout exceeds the restrictions set by your organization..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -2141,7 +2141,13 @@ Scanning will happen automatically.</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>
|
<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">
|
<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>
|
<value>Your organization policies have set your maximum allowed vault timeout to {0} hour(s) and {1} minute(s).</value>
|
||||||
|
</data>
|
||||||
|
<data name="VaultTimeoutPolicyWithActionInEffect" xml:space="preserve">
|
||||||
|
<value>Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is {0} hour(s) and {1} minute(s). Your vault timeout action is set to {2}.</value>
|
||||||
|
</data>
|
||||||
|
<data name="VaultTimeoutActionPolicyInEffect" xml:space="preserve">
|
||||||
|
<value>Your organization policies have set your vault timeout action to {0}.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="VaultTimeoutToLarge" xml:space="preserve">
|
<data name="VaultTimeoutToLarge" xml:space="preserve">
|
||||||
<value>Your vault timeout exceeds the restrictions set by your organization.</value>
|
<value>Your vault timeout exceeds the restrictions set by your organization.</value>
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace Bit.Core.Abstractions
|
||||||
string orgId);
|
string orgId);
|
||||||
Task<bool> PolicyAppliesToUser(PolicyType policyType, Func<Policy, bool> policyFilter = null, string userId = null);
|
Task<bool> PolicyAppliesToUser(PolicyType policyType, Func<Policy, bool> policyFilter = null, string userId = null);
|
||||||
int? GetPolicyInt(Policy policy, string key);
|
int? GetPolicyInt(Policy policy, string key);
|
||||||
|
string GetPolicyString(Policy policy, string key);
|
||||||
Task<bool> ShouldShowVaultFilterAsync();
|
Task<bool> ShouldShowVaultFilterAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,5 +22,6 @@ namespace Bit.Core.Abstractions
|
||||||
Task LogOutAsync(bool userInitiated = true, string userId = null);
|
Task LogOutAsync(bool userInitiated = true, string userId = null);
|
||||||
Task SetVaultTimeoutOptionsAsync(int? timeout, VaultTimeoutAction? action);
|
Task SetVaultTimeoutOptionsAsync(int? timeout, VaultTimeoutAction? action);
|
||||||
Task<int?> GetVaultTimeout(string userId = null);
|
Task<int?> GetVaultTimeout(string userId = null);
|
||||||
|
Task<VaultTimeoutAction?> GetVaultTimeoutAction(string userId = null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,11 @@ namespace Bit.Core.Services
|
||||||
|
|
||||||
private IEnumerable<Policy> _policyCache;
|
private IEnumerable<Policy> _policyCache;
|
||||||
|
|
||||||
|
public const string TIMEOUT_POLICY_MINUTES = "minutes";
|
||||||
|
public const string TIMEOUT_POLICY_ACTION = "action";
|
||||||
|
public const string TIMEOUT_POLICY_ACTION_LOCK = "lock";
|
||||||
|
public const string TIMEOUT_POLICY_ACTION_LOGOUT = "logOut";
|
||||||
|
|
||||||
public PolicyService(
|
public PolicyService(
|
||||||
IStateService stateService,
|
IStateService stateService,
|
||||||
IOrganizationService organizationService)
|
IOrganizationService organizationService)
|
||||||
|
@ -56,6 +61,12 @@ namespace Bit.Core.Services
|
||||||
{
|
{
|
||||||
await _stateService.SetEncryptedPoliciesAsync(policies, userId);
|
await _stateService.SetEncryptedPoliciesAsync(policies, userId);
|
||||||
_policyCache = null;
|
_policyCache = null;
|
||||||
|
|
||||||
|
var vaultTimeoutPolicy = policies.FirstOrDefault(p => p.Value.Type == PolicyType.MaximumVaultTimeout);
|
||||||
|
if (!vaultTimeoutPolicy.Equals(default))
|
||||||
|
{
|
||||||
|
await UpdateVaultTimeoutFromPolicyAsync(new Policy(vaultTimeoutPolicy.Value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ClearAsync(string userId)
|
public async Task ClearAsync(string userId)
|
||||||
|
@ -64,6 +75,35 @@ namespace Bit.Core.Services
|
||||||
_policyCache = null;
|
_policyCache = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task UpdateVaultTimeoutFromPolicyAsync(Policy policy, string userId = null)
|
||||||
|
{
|
||||||
|
var policyTimeout = GetPolicyInt(policy, PolicyService.TIMEOUT_POLICY_MINUTES);
|
||||||
|
if (policyTimeout != null)
|
||||||
|
{
|
||||||
|
var vaultTimeout = await _stateService.GetVaultTimeoutAsync(userId);
|
||||||
|
var timeout = vaultTimeout.HasValue ? Math.Min(vaultTimeout.Value, policyTimeout.Value) : policyTimeout.Value;
|
||||||
|
if (timeout < 0)
|
||||||
|
{
|
||||||
|
timeout = policyTimeout.Value;
|
||||||
|
}
|
||||||
|
if (vaultTimeout != timeout)
|
||||||
|
{
|
||||||
|
await _stateService.SetVaultTimeoutAsync(timeout, userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var policyAction = GetPolicyString(policy, PolicyService.TIMEOUT_POLICY_ACTION);
|
||||||
|
if (!string.IsNullOrEmpty(policyAction))
|
||||||
|
{
|
||||||
|
var vaultTimeoutAction = await _stateService.GetVaultTimeoutActionAsync(userId);
|
||||||
|
var action = policyAction == PolicyService.TIMEOUT_POLICY_ACTION_LOCK ? VaultTimeoutAction.Lock : VaultTimeoutAction.Logout;
|
||||||
|
if (vaultTimeoutAction != action)
|
||||||
|
{
|
||||||
|
await _stateService.SetVaultTimeoutActionAsync(action, userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<MasterPasswordPolicyOptions> GetMasterPasswordPolicyOptions(
|
public async Task<MasterPasswordPolicyOptions> GetMasterPasswordPolicyOptions(
|
||||||
IEnumerable<Policy> policies = null, string userId = null)
|
IEnumerable<Policy> policies = null, string userId = null)
|
||||||
{
|
{
|
||||||
|
@ -247,6 +287,10 @@ namespace Bit.Core.Services
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetPolicyString(Policy policy, string key) =>
|
||||||
|
policy.Data.TryGetValue(key, out var val) ? val as string : null;
|
||||||
|
|
||||||
|
|
||||||
public async Task<bool> ShouldShowVaultFilterAsync()
|
public async Task<bool> ShouldShowVaultFilterAsync()
|
||||||
{
|
{
|
||||||
var personalOwnershipPolicyApplies = await PolicyAppliesToUser(PolicyType.PersonalOwnership);
|
var personalOwnershipPolicyApplies = await PolicyAppliesToUser(PolicyType.PersonalOwnership);
|
||||||
|
@ -272,17 +316,6 @@ namespace Bit.Core.Services
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetPolicyString(Policy policy, string key)
|
|
||||||
{
|
|
||||||
if (policy.Data.ContainsKey(key))
|
|
||||||
{
|
|
||||||
var value = policy.Data[key];
|
|
||||||
if (value != null)
|
|
||||||
{
|
|
||||||
return (string)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ namespace Bit.Core.Services
|
||||||
await SyncCollectionsAsync(response.Collections);
|
await SyncCollectionsAsync(response.Collections);
|
||||||
await SyncCiphersAsync(userId, response.Ciphers);
|
await SyncCiphersAsync(userId, response.Ciphers);
|
||||||
await SyncSettingsAsync(userId, response.Domains);
|
await SyncSettingsAsync(userId, response.Domains);
|
||||||
await SyncPoliciesAsync(response.Policies);
|
await SyncPoliciesAsync(userId, response.Policies);
|
||||||
await SyncSendsAsync(userId, response.Sends);
|
await SyncSendsAsync(userId, response.Sends);
|
||||||
await SetLastSyncAsync(now);
|
await SetLastSyncAsync(now);
|
||||||
_watchDeviceService.Value.SyncDataToWatchAsync().FireAndForget();
|
_watchDeviceService.Value.SyncDataToWatchAsync().FireAndForget();
|
||||||
|
@ -378,11 +378,11 @@ namespace Bit.Core.Services
|
||||||
await _settingsService.SetEquivalentDomainsAsync(eqDomains);
|
await _settingsService.SetEquivalentDomainsAsync(eqDomains);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SyncPoliciesAsync(List<PolicyResponse> response)
|
private async Task SyncPoliciesAsync(string userId, List<PolicyResponse> response)
|
||||||
{
|
{
|
||||||
var policies = response?.ToDictionary(p => p.Id, p => new PolicyData(p)) ??
|
var policies = response?.ToDictionary(p => p.Id, p => new PolicyData(p)) ??
|
||||||
new Dictionary<string, PolicyData>();
|
new Dictionary<string, PolicyData>();
|
||||||
await _policyService.Replace(policies);
|
await _policyService.Replace(policies, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SyncSendsAsync(string userId, List<SendResponse> response)
|
private async Task SyncSendsAsync(string userId, List<SendResponse> response)
|
||||||
|
|
|
@ -17,7 +17,6 @@ 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 IKeyConnectorService _keyConnectorService;
|
private readonly IKeyConnectorService _keyConnectorService;
|
||||||
private readonly Func<Tuple<string, bool>, Task> _lockedCallback;
|
private readonly Func<Tuple<string, bool>, Task> _lockedCallback;
|
||||||
private readonly Func<Tuple<string, bool, bool>, Task> _loggedOutCallback;
|
private readonly Func<Tuple<string, bool, bool>, Task> _loggedOutCallback;
|
||||||
|
@ -32,7 +31,6 @@ namespace Bit.Core.Services
|
||||||
ISearchService searchService,
|
ISearchService searchService,
|
||||||
IMessagingService messagingService,
|
IMessagingService messagingService,
|
||||||
ITokenService tokenService,
|
ITokenService tokenService,
|
||||||
IPolicyService policyService,
|
|
||||||
IKeyConnectorService keyConnectorService,
|
IKeyConnectorService keyConnectorService,
|
||||||
Func<Tuple<string, bool>, Task> lockedCallback,
|
Func<Tuple<string, bool>, Task> lockedCallback,
|
||||||
Func<Tuple<string, bool, bool>, Task> loggedOutCallback)
|
Func<Tuple<string, bool, bool>, Task> loggedOutCallback)
|
||||||
|
@ -46,7 +44,6 @@ namespace Bit.Core.Services
|
||||||
_searchService = searchService;
|
_searchService = searchService;
|
||||||
_messagingService = messagingService;
|
_messagingService = messagingService;
|
||||||
_tokenService = tokenService;
|
_tokenService = tokenService;
|
||||||
_policyService = policyService;
|
|
||||||
_keyConnectorService = keyConnectorService;
|
_keyConnectorService = keyConnectorService;
|
||||||
_lockedCallback = lockedCallback;
|
_lockedCallback = lockedCallback;
|
||||||
_loggedOutCallback = loggedOutCallback;
|
_loggedOutCallback = loggedOutCallback;
|
||||||
|
@ -241,35 +238,12 @@ namespace Bit.Core.Services
|
||||||
|
|
||||||
public async Task<int?> GetVaultTimeout(string userId = null)
|
public async Task<int?> GetVaultTimeout(string userId = null)
|
||||||
{
|
{
|
||||||
var vaultTimeout = await _stateService.GetVaultTimeoutAsync(userId);
|
return await _stateService.GetVaultTimeoutAsync(userId);
|
||||||
|
}
|
||||||
|
|
||||||
if (await _policyService.PolicyAppliesToUser(PolicyType.MaximumVaultTimeout, null, userId))
|
public async Task<VaultTimeoutAction?> GetVaultTimeoutAction(string userId = null)
|
||||||
{
|
{
|
||||||
var policy = (await _policyService.GetAll(PolicyType.MaximumVaultTimeout, userId)).First();
|
return await _stateService.GetVaultTimeoutActionAsync(userId);
|
||||||
// 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 = vaultTimeout.HasValue ? Math.Min(vaultTimeout.Value, policyTimeout.Value) : 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 _stateService.SetVaultTimeoutAsync(timeout, userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vaultTimeout;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace Bit.Core.Utilities
|
||||||
organizationService);
|
organizationService);
|
||||||
var vaultTimeoutService = new VaultTimeoutService(cryptoService, stateService, platformUtilsService,
|
var vaultTimeoutService = new VaultTimeoutService(cryptoService, stateService, platformUtilsService,
|
||||||
folderService, cipherService, collectionService, searchService, messagingService, tokenService,
|
folderService, cipherService, collectionService, searchService, messagingService, tokenService,
|
||||||
policyService, keyConnectorService,
|
keyConnectorService,
|
||||||
(extras) =>
|
(extras) =>
|
||||||
{
|
{
|
||||||
messagingService.Send("locked", extras);
|
messagingService.Send("locked", extras);
|
||||||
|
|
Loading…
Reference in a new issue