1
0
mirror of https://github.com/bitwarden/mobile synced 2026-01-06 10:34:07 +00:00

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
16 changed files with 5504 additions and 3526 deletions

View File

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

View File

@@ -18,5 +18,7 @@ namespace Bit.Core.Abstractions
MasterPasswordPolicyOptions enforcedPolicyOptions);
Tuple<ResetPasswordPolicyOptions, bool> GetResetPasswordPolicyOptions(IEnumerable<Policy> policies,
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 LogOutAsync();
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
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
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 canManagePolicies => IsAdmin || Permissions.ManagePolicies;
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);
}
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))
{

View File

@@ -1,7 +1,9 @@
using Bit.Core.Abstractions;
using Bit.Core.Models.Domain;
using System;
using System.Linq;
using System.Threading.Tasks;
using Bit.Core.Enums;
namespace Bit.Core.Services
{
@@ -17,6 +19,7 @@ namespace Bit.Core.Services
private readonly ISearchService _searchService;
private readonly IMessagingService _messagingService;
private readonly ITokenService _tokenService;
private readonly IPolicyService _policyService;
private readonly Action<bool> _lockedCallback;
private readonly Func<bool, Task> _loggedOutCallback;
@@ -31,6 +34,7 @@ namespace Bit.Core.Services
ISearchService searchService,
IMessagingService messagingService,
ITokenService tokenService,
IPolicyService policyService,
Action<bool> lockedCallback,
Func<bool, Task> loggedOutCallback)
{
@@ -44,6 +48,7 @@ namespace Bit.Core.Services
_searchService = searchService;
_messagingService = messagingService;
_tokenService = tokenService;
_policyService = policyService;
_lockedCallback = lockedCallback;
_loggedOutCallback = loggedOutCallback;
}
@@ -80,13 +85,8 @@ namespace Bit.Core.Services
{
return;
}
// This only returns null
var vaultTimeoutMinutes = _platformUtilsService.LockTimeout();
if (vaultTimeoutMinutes == null)
{
vaultTimeoutMinutes = await _storageService.GetAsync<int?>(Constants.VaultTimeoutKey);
}
if (vaultTimeoutMinutes.GetValueOrDefault(-1) < 0)
var vaultTimeoutMinutes = await GetVaultTimeout();
if (vaultTimeoutMinutes < 0)
{
return;
}
@@ -177,5 +177,34 @@ namespace Bit.Core.Services
PinProtectedKey = null;
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,
i18nService, cryptoFunctionService);
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,
null, (expired) =>
policyService, null, (expired) =>
{
messagingService.Send("logout", expired);
return Task.FromResult(0);
});
var policyService = new PolicyService(storageService, userService);
var syncService = new SyncService(userService, apiService, settingsService, folderService,
cipherService, cryptoService, collectionService, storageService, messagingService, policyService, sendService,
(bool expired) =>