diff --git a/src/Api/Controllers/SyncController.cs b/src/Api/Controllers/SyncController.cs index ad961da52..436de3e42 100644 --- a/src/Api/Controllers/SyncController.cs +++ b/src/Api/Controllers/SyncController.cs @@ -25,6 +25,7 @@ namespace Bit.Api.Controllers private readonly ICollectionRepository _collectionRepository; private readonly ICollectionCipherRepository _collectionCipherRepository; private readonly IOrganizationUserRepository _organizationUserRepository; + private readonly IPolicyRepository _policyRepository; private readonly GlobalSettings _globalSettings; public SyncController( @@ -34,6 +35,7 @@ namespace Bit.Api.Controllers ICollectionRepository collectionRepository, ICollectionCipherRepository collectionCipherRepository, IOrganizationUserRepository organizationUserRepository, + IPolicyRepository policyRepository, GlobalSettings globalSettings) { _userService = userService; @@ -42,6 +44,7 @@ namespace Bit.Api.Controllers _collectionRepository = collectionRepository; _collectionCipherRepository = collectionCipherRepository; _organizationUserRepository = organizationUserRepository; + _policyRepository = policyRepository; _globalSettings = globalSettings; } @@ -62,16 +65,18 @@ namespace Bit.Api.Controllers IEnumerable collections = null; IDictionary> collectionCiphersGroupDict = null; + IEnumerable policies = null; if(hasEnabledOrgs) { collections = await _collectionRepository.GetManyByUserIdAsync(user.Id); var collectionCiphers = await _collectionCipherRepository.GetManyByUserIdAsync(user.Id); collectionCiphersGroupDict = collectionCiphers.GroupBy(c => c.CipherId).ToDictionary(s => s.Key); + policies = await _policyRepository.GetManyByUserIdAsync(user.Id); } var userTwoFactorEnabled = await _userService.TwoFactorIsEnabledAsync(user); var response = new SyncResponseModel(_globalSettings, user, userTwoFactorEnabled, organizationUserDetails, - folders, collections, ciphers, collectionCiphersGroupDict, excludeDomains); + folders, collections, ciphers, collectionCiphersGroupDict, excludeDomains, policies); return response; } } diff --git a/src/Core/Models/Api/Response/SyncResponseModel.cs b/src/Core/Models/Api/Response/SyncResponseModel.cs index 7e196d229..a55e31d3f 100644 --- a/src/Core/Models/Api/Response/SyncResponseModel.cs +++ b/src/Core/Models/Api/Response/SyncResponseModel.cs @@ -18,7 +18,8 @@ namespace Bit.Core.Models.Api IEnumerable collections, IEnumerable ciphers, IDictionary> collectionCiphersDict, - bool excludeDomains) + bool excludeDomains, + IEnumerable policies) : base("sync") { Profile = new ProfileResponseModel(user, organizationUserDetails, userTwoFactorEnabled); @@ -27,6 +28,7 @@ namespace Bit.Core.Models.Api Collections = collections?.Select( c => new CollectionDetailsResponseModel(c)) ?? new List(); Domains = excludeDomains ? null : new DomainsResponseModel(user, false); + Policies = policies.Select(p => new PolicyResponseModel(p)); } public ProfileResponseModel Profile { get; set; } @@ -34,5 +36,6 @@ namespace Bit.Core.Models.Api public IEnumerable Collections { get; set; } public IEnumerable Ciphers { get; set; } public DomainsResponseModel Domains { get; set; } + public IEnumerable Policies { get; set; } } } diff --git a/src/Core/Repositories/IPolicyRepository.cs b/src/Core/Repositories/IPolicyRepository.cs index 42b54c0b7..185b631a3 100644 --- a/src/Core/Repositories/IPolicyRepository.cs +++ b/src/Core/Repositories/IPolicyRepository.cs @@ -10,5 +10,6 @@ namespace Bit.Core.Repositories { Task GetByOrganizationIdTypeAsync(Guid organizationId, PolicyType type); Task> GetManyByOrganizationIdAsync(Guid organizationId); + Task> GetManyByUserIdAsync(Guid userId); } } diff --git a/src/Core/Repositories/SqlServer/PolicyRepository.cs b/src/Core/Repositories/SqlServer/PolicyRepository.cs index fcbca41ae..c8843282f 100644 --- a/src/Core/Repositories/SqlServer/PolicyRepository.cs +++ b/src/Core/Repositories/SqlServer/PolicyRepository.cs @@ -44,5 +44,18 @@ namespace Bit.Core.Repositories.SqlServer return results.ToList(); } } + + public async Task> GetManyByUserIdAsync(Guid userId) + { + using(var connection = new SqlConnection(ConnectionString)) + { + var results = await connection.QueryAsync( + $"[{Schema}].[{Table}_ReadByUserId]", + new { UserId = userId }, + commandType: CommandType.StoredProcedure); + + return results.ToList(); + } + } } } diff --git a/src/Sql/Sql.sqlproj b/src/Sql/Sql.sqlproj index 6a8f2eac3..4f00de05a 100644 --- a/src/Sql/Sql.sqlproj +++ b/src/Sql/Sql.sqlproj @@ -260,5 +260,6 @@ + \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Policy_ReadByUserId.sql b/src/Sql/dbo/Stored Procedures/Policy_ReadByUserId.sql new file mode 100644 index 000000000..872a4d319 --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/Policy_ReadByUserId.sql @@ -0,0 +1,15 @@ +CREATE PROCEDURE [dbo].[Policy_ReadByUserId] + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + P.* + FROM + [dbo].[PolicyView] P + INNER JOIN + [dbo].[OrganizationUser] OU ON P.[OrganizationId] = OU.[OrganizationId] + WHERE + OU.[UserId] = @UserId +END \ No newline at end of file diff --git a/util/Migrator/DbScripts/2020-01-15_00_PolicySetup.sql b/util/Migrator/DbScripts/2020-01-28_00_PolicySetup.sql similarity index 96% rename from util/Migrator/DbScripts/2020-01-15_00_PolicySetup.sql rename to util/Migrator/DbScripts/2020-01-28_00_PolicySetup.sql index ef2348205..8d25ffdd6 100644 --- a/util/Migrator/DbScripts/2020-01-15_00_PolicySetup.sql +++ b/util/Migrator/DbScripts/2020-01-28_00_PolicySetup.sql @@ -557,3 +557,26 @@ BEGIN [Id] = @Id END GO + +IF OBJECT_ID('[dbo].[Policy_ReadByUserId]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Policy_ReadByUserId] +END +GO + +CREATE PROCEDURE [dbo].[Policy_ReadByUserId] + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + P.* + FROM + [dbo].[PolicyView] P + INNER JOIN + [dbo].[OrganizationUser] OU ON P.[OrganizationId] = OU.[OrganizationId] + WHERE + OU.[UserId] = @UserId +END +GO