diff --git a/src/Api/Controllers/CollectionsController.cs b/src/Api/Controllers/CollectionsController.cs index 053a51037c..1265a6ad48 100644 --- a/src/Api/Controllers/CollectionsController.cs +++ b/src/Api/Controllers/CollectionsController.cs @@ -8,6 +8,7 @@ using Bit.Core.Models.Api; using Bit.Core.Exceptions; using Bit.Core.Services; using Bit.Core; +using Bit.Core.Models.Data; namespace Bit.Api.Controllers { @@ -91,7 +92,7 @@ namespace Bit.Api.Controllers } var collection = model.ToCollection(orgIdGuid); - await _collectionService.SaveAsync(collection, model.GroupIds?.Select(g => new Guid(g))); + await _collectionService.SaveAsync(collection, model.Groups?.Select(g => g.ToSelectionReadOnly())); return new CollectionResponseModel(collection); } @@ -105,7 +106,8 @@ namespace Bit.Api.Controllers throw new NotFoundException(); } - await _collectionService.SaveAsync(model.ToCollection(collection), model.GroupIds?.Select(g => new Guid(g))); + await _collectionService.SaveAsync(model.ToCollection(collection), + model.Groups?.Select(g => g.ToSelectionReadOnly())); return new CollectionResponseModel(collection); } diff --git a/src/Core/Models/Api/Request/CollectionRequestModel.cs b/src/Core/Models/Api/Request/CollectionRequestModel.cs index 4710cb6523..8de88ebe64 100644 --- a/src/Core/Models/Api/Request/CollectionRequestModel.cs +++ b/src/Core/Models/Api/Request/CollectionRequestModel.cs @@ -13,7 +13,7 @@ namespace Bit.Core.Models.Api [EncryptedString] [StringLength(300)] public string Name { get; set; } - public IEnumerable GroupIds { get; set; } + public IEnumerable Groups { get; set; } public Collection ToCollection(Guid orgId) { diff --git a/src/Core/Models/Api/Response/CollectionResponseModel.cs b/src/Core/Models/Api/Response/CollectionResponseModel.cs index dc75f06f42..ac95234584 100644 --- a/src/Core/Models/Api/Response/CollectionResponseModel.cs +++ b/src/Core/Models/Api/Response/CollectionResponseModel.cs @@ -1,6 +1,8 @@ using System; using Bit.Core.Models.Table; using System.Collections.Generic; +using Bit.Core.Models.Data; +using System.Linq; namespace Bit.Core.Models.Api { @@ -26,12 +28,12 @@ namespace Bit.Core.Models.Api public class CollectionDetailsResponseModel : CollectionResponseModel { - public CollectionDetailsResponseModel(Collection collection, IEnumerable groupIds) + public CollectionDetailsResponseModel(Collection collection, IEnumerable groups) : base(collection, "collectionDetails") { - GroupIds = groupIds; + Groups = groups.Select(g => new SelectionReadOnlyResponseModel(g)); } - public IEnumerable GroupIds { get; set; } + public IEnumerable Groups { get; set; } } } diff --git a/src/Core/Repositories/ICollectionRepository.cs b/src/Core/Repositories/ICollectionRepository.cs index ddb134240f..51ae8a32fb 100644 --- a/src/Core/Repositories/ICollectionRepository.cs +++ b/src/Core/Repositories/ICollectionRepository.cs @@ -2,17 +2,18 @@ using System.Threading.Tasks; using Bit.Core.Models.Table; using System.Collections.Generic; +using Bit.Core.Models.Data; namespace Bit.Core.Repositories { public interface ICollectionRepository : IRepository { Task GetCountByOrganizationIdAsync(Guid organizationId); - Task>> GetByIdWithGroupsAsync(Guid id); + Task>> GetByIdWithGroupsAsync(Guid id); Task> GetManyByOrganizationIdAsync(Guid organizationId); Task> GetManyByUserIdAsync(Guid userId); - Task CreateAsync(Collection obj, IEnumerable groupIds); - Task ReplaceAsync(Collection obj, IEnumerable groupIds); + Task CreateAsync(Collection obj, IEnumerable groups); + Task ReplaceAsync(Collection obj, IEnumerable groups); } } diff --git a/src/Core/Repositories/SqlServer/CollectionRepository.cs b/src/Core/Repositories/SqlServer/CollectionRepository.cs index fcabacd8c6..a039337b50 100644 --- a/src/Core/Repositories/SqlServer/CollectionRepository.cs +++ b/src/Core/Repositories/SqlServer/CollectionRepository.cs @@ -8,6 +8,7 @@ using Dapper; using System.Linq; using Newtonsoft.Json; using Bit.Core.Utilities; +using Bit.Core.Models.Data; namespace Bit.Core.Repositories.SqlServer { @@ -34,7 +35,7 @@ namespace Bit.Core.Repositories.SqlServer } } - public async Task>> GetByIdWithGroupsAsync(Guid id) + public async Task>> GetByIdWithGroupsAsync(Guid id) { using(var connection = new SqlConnection(ConnectionString)) { @@ -44,9 +45,9 @@ namespace Bit.Core.Repositories.SqlServer commandType: CommandType.StoredProcedure); var collection = await results.ReadFirstOrDefaultAsync(); - var groupIds = (await results.ReadAsync()).ToList(); + var groups = (await results.ReadAsync()).ToList(); - return new Tuple>(collection, groupIds); + return new Tuple>(collection, groups); } } @@ -80,11 +81,11 @@ namespace Bit.Core.Repositories.SqlServer } } - public async Task CreateAsync(Collection obj, IEnumerable groupIds) + public async Task CreateAsync(Collection obj, IEnumerable groups) { obj.SetNewId(); var objWithGroups = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(obj)); - objWithGroups.GroupIds = groupIds.ToGuidIdArrayTVP(); + objWithGroups.Groups = groups.ToArrayTVP(); using(var connection = new SqlConnection(ConnectionString)) { @@ -95,10 +96,10 @@ namespace Bit.Core.Repositories.SqlServer } } - public async Task ReplaceAsync(Collection obj, IEnumerable groupIds) + public async Task ReplaceAsync(Collection obj, IEnumerable groups) { var objWithGroups = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(obj)); - objWithGroups.GroupIds = groupIds.ToGuidIdArrayTVP(); + objWithGroups.Groups = groups.ToArrayTVP(); using(var connection = new SqlConnection(ConnectionString)) { @@ -111,7 +112,7 @@ namespace Bit.Core.Repositories.SqlServer public class CollectionWithGroups : Collection { - public DataTable GroupIds { get; set; } + public DataTable Groups { get; set; } } } } diff --git a/src/Core/Services/ICollectionService.cs b/src/Core/Services/ICollectionService.cs index 74f5cc99cb..8c5363e842 100644 --- a/src/Core/Services/ICollectionService.cs +++ b/src/Core/Services/ICollectionService.cs @@ -2,11 +2,12 @@ using Bit.Core.Models.Table; using System.Collections.Generic; using System; +using Bit.Core.Models.Data; namespace Bit.Core.Services { public interface ICollectionService { - Task SaveAsync(Collection collection, IEnumerable groupIds = null); + Task SaveAsync(Collection collection, IEnumerable groups = null); } } diff --git a/src/Core/Services/Implementations/CollectionService.cs b/src/Core/Services/Implementations/CollectionService.cs index 7bb1ef5047..17e5d27a03 100644 --- a/src/Core/Services/Implementations/CollectionService.cs +++ b/src/Core/Services/Implementations/CollectionService.cs @@ -4,6 +4,7 @@ using Bit.Core.Exceptions; using Bit.Core.Models.Table; using Bit.Core.Repositories; using System.Collections.Generic; +using Bit.Core.Models.Data; namespace Bit.Core.Services { @@ -32,7 +33,7 @@ namespace Bit.Core.Services _mailService = mailService; } - public async Task SaveAsync(Collection collection, IEnumerable groupIds = null) + public async Task SaveAsync(Collection collection, IEnumerable groups = null) { var org = await _organizationRepository.GetByIdAsync(collection.OrganizationId); if(org == null) @@ -52,24 +53,24 @@ namespace Bit.Core.Services } } - if(groupIds == null || !org.UseGroups) + if(groups == null || !org.UseGroups) { await _collectionRepository.CreateAsync(collection); } else { - await _collectionRepository.CreateAsync(collection, groupIds); + await _collectionRepository.CreateAsync(collection, groups); } } else { - if(groupIds == null || !org.UseGroups) + if(groups == null || !org.UseGroups) { await _collectionRepository.ReplaceAsync(collection); } else { - await _collectionRepository.ReplaceAsync(collection, groupIds); + await _collectionRepository.ReplaceAsync(collection, groups); } } } diff --git a/src/Sql/dbo/Stored Procedures/Collection_ReadWithGroupsById.sql b/src/Sql/dbo/Stored Procedures/Collection_ReadWithGroupsById.sql index cda84735c0..d9caec30f9 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_ReadWithGroupsById.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_ReadWithGroupsById.sql @@ -7,7 +7,8 @@ BEGIN EXEC [dbo].[Collection_ReadById] @Id SELECT - [GroupId] + [GroupId] [Id], + [ReadOnly] FROM [dbo].[CollectionGroup] WHERE diff --git a/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroups.sql b/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroups.sql index 83d08c5b5e..2477fa49d8 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroups.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroups.sql @@ -4,7 +4,7 @@ @Name VARCHAR(MAX), @CreationDate DATETIME2(7), @RevisionDate DATETIME2(7), - @GroupIds AS [dbo].[GuidIdArray] READONLY + @Groups AS [dbo].[SelectionReadOnlyArray] READONLY AS BEGIN SET NOCOUNT ON @@ -22,7 +22,7 @@ BEGIN MERGE [dbo].[CollectionGroup] AS [Target] USING - @GroupIds AS [Source] + @Groups AS [Source] ON [Target].[CollectionId] = @Id AND [Target].[GroupId] = [Source].[Id] @@ -32,8 +32,10 @@ BEGIN ( @Id, [Source].[Id], - 0 + [Source].[ReadOnly] ) + WHEN MATCHED AND [Target].[ReadOnly] != [Source].[ReadOnly] THEN + UPDATE SET [Target].[ReadOnly] = [Source].[ReadOnly] WHEN NOT MATCHED BY SOURCE AND [Target].[CollectionId] = @Id THEN DELETE