Beginning of policy support (#736)

* Model & service support for policies

* Formatting

* Changes to match existing service and model patterns
This commit is contained in:
Matt Portune 2020-02-21 10:23:38 -05:00 committed by GitHub
parent ec3660a86d
commit 387dc2f59c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 172 additions and 1 deletions

View File

@ -0,0 +1,16 @@
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 IPolicyService
{
void ClearCache();
Task<IEnumerable<Policy>> GetAll(PolicyType? type);
Task Replace(Dictionary<string, PolicyData> policies);
Task Clear(string userId);
}
}

View File

@ -0,0 +1,9 @@
namespace Bit.Core.Enums
{
public enum PolicyType : byte
{
TwoFactorAuthentication = 0,
MasterPassword = 1,
PasswordGenerator = 2
}
}

View File

@ -0,0 +1,26 @@
using System.Collections.Generic;
using Bit.Core.Enums;
using Bit.Core.Models.Response;
namespace Bit.Core.Models.Data
{
public class PolicyData : Data
{
public PolicyData() { }
public PolicyData(PolicyResponse response)
{
Id = response.Id;
OrganizationId = response.OrganizationId;
Type = response.Type;
Data = response.Data;
Enabled = response.Enabled;
}
public string Id { get; set; }
public string OrganizationId { get; set; }
public PolicyType Type { get; set; }
public Dictionary<string, object> Data { get; set; }
public bool Enabled { get; set; }
}
}

View File

@ -0,0 +1,26 @@
using System.Collections.Generic;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
namespace Bit.Core.Models.Domain
{
public class Policy : Domain
{
public Policy() { }
public Policy(PolicyData obj)
{
Id = obj.Id;
OrganizationId = obj.OrganizationId;
Type = obj.Type;
Data = obj.Data;
Enabled = obj.Enabled;
}
public string Id { get; set; }
public string OrganizationId { get; set; }
public PolicyType Type { get; set; }
public Dictionary<string, object> Data { get; set; }
public bool Enabled { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using System.Collections.Generic;
using Bit.Core.Enums;
namespace Bit.Core.Models.Response
{
public class PolicyResponse
{
public string Id { get; set; }
public string OrganizationId { get; set; }
public PolicyType Type { get; set; }
public Dictionary<string, object> Data { get; set; }
public bool Enabled { get; set; }
}
}

View File

@ -9,5 +9,6 @@ namespace Bit.Core.Models.Response
public List<CollectionDetailsResponse> Collections { get; set; } = new List<CollectionDetailsResponse>();
public List<CipherResponse> Ciphers { get; set; } = new List<CipherResponse>();
public DomainsResponse Domains { get; set; }
public List<PolicyResponse> Policies { get; set; } = new List<PolicyResponse>();
}
}

View File

@ -0,0 +1,66 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
using Bit.Core.Models.Domain;
namespace Bit.Core.Services
{
public class PolicyService : IPolicyService
{
private const string Keys_PoliciesPrefix = "policies_{0}";
private readonly IStorageService _storageService;
private readonly IUserService _userService;
private IEnumerable<Policy> _policyCache;
public PolicyService(
IStorageService storageService,
IUserService userService)
{
_storageService = storageService;
_userService = userService;
}
public void ClearCache()
{
_policyCache = null;
}
public async Task<IEnumerable<Policy>> GetAll(PolicyType? type)
{
if(_policyCache == null)
{
var userId = await _userService.GetUserIdAsync();
var policies = await _storageService.GetAsync<Dictionary<string, PolicyData>>(
string.Format(Keys_PoliciesPrefix, userId));
_policyCache = policies.Select(p => new Policy(policies[p.Key]));
}
if(type != null)
{
return _policyCache.Where(p => p.Type == type).ToList();
}
else
{
return _policyCache;
}
}
public async Task Replace(Dictionary<string, PolicyData> policies)
{
var userId = await _userService.GetUserIdAsync();
await _storageService.SaveAsync(string.Format(Keys_PoliciesPrefix, userId), policies);
_policyCache = null;
}
public async Task Clear(string userId)
{
await _storageService.RemoveAsync(string.Format(Keys_PoliciesPrefix, userId));
_policyCache = null;
}
}
}

View File

@ -23,6 +23,7 @@ namespace Bit.Core.Services
private readonly ICollectionService _collectionService;
private readonly IStorageService _storageService;
private readonly IMessagingService _messagingService;
private readonly IPolicyService _policyService;
private readonly Func<bool, Task> _logoutCallbackAsync;
public SyncService(
@ -35,6 +36,7 @@ namespace Bit.Core.Services
ICollectionService collectionService,
IStorageService storageService,
IMessagingService messagingService,
IPolicyService policyService,
Func<bool, Task> logoutCallbackAsync)
{
_userService = userService;
@ -46,6 +48,7 @@ namespace Bit.Core.Services
_collectionService = collectionService;
_storageService = storageService;
_messagingService = messagingService;
_policyService = policyService;
_logoutCallbackAsync = logoutCallbackAsync;
}
@ -101,6 +104,7 @@ namespace Bit.Core.Services
await SyncCollectionsAsync(response.Collections);
await SyncCiphersAsync(userId, response.Ciphers);
await SyncSettingsAsync(userId, response.Domains);
await SyncPolicies(response.Policies);
await SetLastSyncAsync(now);
return SyncCompleted(true);
}
@ -358,5 +362,11 @@ namespace Bit.Core.Services
}
await _settingsService.SetEquivalentDomainsAsync(eqDomains);
}
private async Task SyncPolicies(List<PolicyResponse> response)
{
var policies = response.ToDictionary(p => p.Id, p => new PolicyData(p));
await _policyService.Replace(policies);
}
}
}

View File

@ -47,8 +47,10 @@ namespace Bit.Core.Utilities
searchService = new SearchService(cipherService);
var lockService = new LockService(cryptoService, userService, platformUtilsService, storageService,
folderService, cipherService, collectionService, searchService, messagingService, null);
var policyService = new PolicyService(storageService, userService);
var syncService = new SyncService(userService, apiService, settingsService, folderService,
cipherService, cryptoService, collectionService, storageService, messagingService, (bool expired) =>
cipherService, cryptoService, collectionService, storageService, messagingService, policyService,
(bool expired) =>
{
messagingService.Send("logout", expired);
return Task.FromResult(0);
@ -75,6 +77,7 @@ namespace Bit.Core.Utilities
Register<IFolderService>("folderService", folderService);
Register<ICollectionService>("collectionService", collectionService);
Register<ISearchService>("searchService", searchService);
Register<IPolicyService>("policyService", policyService);
Register<ISyncService>("syncService", syncService);
Register<ILockService>("lockService", lockService);
Register<IPasswordGenerationService>("passwordGenerationService", passwordGenerationService);