From 8d2b36d1873af1784d58c33f891f2ac6b7e7e17b Mon Sep 17 00:00:00 2001 From: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Date: Mon, 2 Aug 2021 11:49:27 +1000 Subject: [PATCH] Fix conflicting group permissions (#1473) * Return collection with highest permission levels * Revert "Return collection with highest permission levels" This reverts commit 06e0f3b73e3d8f05f14849da4d0d8a1e9c6c6d58. * Combine duplicate collectionDetails * Update EF to combine duplicate CollectionDetails * Delete unneeded using statements --- .../EntityFramework/CollectionRepository.cs | 10 +-- .../Queries/CollectionReadByIdUserId.cs | 22 +++++++ .../Queries/CollectionReadByUserId.cs | 34 ++++++++++ .../SqlServer/CollectionRepository.cs | 6 +- .../Collection_ReadByIdUserId.sql | 22 +++++-- .../Collection_ReadByUserId.sql | 18 ++++- .../2021-07-22_00_FixCollectionReadBy.sql | 66 +++++++++++++++++++ 7 files changed, 161 insertions(+), 17 deletions(-) create mode 100644 src/Core/Repositories/EntityFramework/Queries/CollectionReadByIdUserId.cs create mode 100644 src/Core/Repositories/EntityFramework/Queries/CollectionReadByUserId.cs create mode 100644 util/Migrator/DbScripts/2021-07-22_00_FixCollectionReadBy.sql diff --git a/src/Core/Repositories/EntityFramework/CollectionRepository.cs b/src/Core/Repositories/EntityFramework/CollectionRepository.cs index 33823bd3e..ea8fc9dd9 100644 --- a/src/Core/Repositories/EntityFramework/CollectionRepository.cs +++ b/src/Core/Repositories/EntityFramework/CollectionRepository.cs @@ -70,8 +70,8 @@ namespace Bit.Core.Repositories.EntityFramework using (var scope = ServiceScopeFactory.CreateScope()) { var dbContext = GetDatabaseContext(scope); - var query = new UserCollectionDetailsQuery(userId); - var collection = await query.Run(dbContext).FirstOrDefaultAsync(); + var query = new CollectionReadByIdUserId(id, userId).Run(dbContext); + var collection = await query.FirstOrDefaultAsync(); return collection; } } @@ -138,9 +138,9 @@ namespace Bit.Core.Repositories.EntityFramework using (var scope = ServiceScopeFactory.CreateScope()) { var dbContext = GetDatabaseContext(scope); - var query = new UserCollectionDetailsQuery(userId).Run(dbContext); - var data = await query.ToListAsync(); - return data.GroupBy(c => c.Id).Select(c => c.First()).ToList(); + var query = new CollectionReadByUserId(userId).Run(dbContext); + var collections = await query.ToListAsync(); + return collections; } } diff --git a/src/Core/Repositories/EntityFramework/Queries/CollectionReadByIdUserId.cs b/src/Core/Repositories/EntityFramework/Queries/CollectionReadByIdUserId.cs new file mode 100644 index 000000000..ced18e34e --- /dev/null +++ b/src/Core/Repositories/EntityFramework/Queries/CollectionReadByIdUserId.cs @@ -0,0 +1,22 @@ +using System.Linq; +using System; +using Bit.Core.Models.Data; + +namespace Bit.Core.Repositories.EntityFramework.Queries +{ + public class CollectionReadByIdUserId : CollectionReadByUserId + { + private readonly Guid _id; + + public CollectionReadByIdUserId(Guid id, Guid userId) : base(userId) + { + _id = id; + } + + public override IQueryable Run(DatabaseContext dbContext) + { + var query = base.Run(dbContext); + return query.Where(c => c.Id == _id); + } + } +} diff --git a/src/Core/Repositories/EntityFramework/Queries/CollectionReadByUserId.cs b/src/Core/Repositories/EntityFramework/Queries/CollectionReadByUserId.cs new file mode 100644 index 000000000..c37db0ceb --- /dev/null +++ b/src/Core/Repositories/EntityFramework/Queries/CollectionReadByUserId.cs @@ -0,0 +1,34 @@ +using System.Linq; +using System; +using Bit.Core.Models.Data; + +namespace Bit.Core.Repositories.EntityFramework.Queries +{ + public class CollectionReadByUserId : UserCollectionDetailsQuery + { + private readonly Guid _userId; + + public CollectionReadByUserId(Guid userId) : base(userId) + { + _userId = userId; + } + + public override IQueryable Run(DatabaseContext dbContext) + { + var query = base.Run(dbContext); + return query + .GroupBy(c => c.Id) + .Select(g => new CollectionDetails + { + Id = g.Key, + OrganizationId = g.FirstOrDefault().OrganizationId, + Name = g.FirstOrDefault().Name, + ExternalId = g.FirstOrDefault().ExternalId, + CreationDate = g.FirstOrDefault().CreationDate, + RevisionDate = g.FirstOrDefault().RevisionDate, + ReadOnly = g.Min(c => c.ReadOnly), + HidePasswords = g.Min(c => c.HidePasswords) + }); + } + } +} diff --git a/src/Core/Repositories/SqlServer/CollectionRepository.cs b/src/Core/Repositories/SqlServer/CollectionRepository.cs index e774dbaec..c7de1c7c7 100644 --- a/src/Core/Repositories/SqlServer/CollectionRepository.cs +++ b/src/Core/Repositories/SqlServer/CollectionRepository.cs @@ -104,11 +104,7 @@ namespace Bit.Core.Repositories.SqlServer new { UserId = userId }, commandType: CommandType.StoredProcedure); - // Return distinct Id results. - return results - .GroupBy(c => c.Id) - .Select(c => c.First()) - .ToList(); + return results.ToList(); } } diff --git a/src/Sql/dbo/Stored Procedures/Collection_ReadByIdUserId.sql b/src/Sql/dbo/Stored Procedures/Collection_ReadByIdUserId.sql index 0987ad317..e8eac21d4 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_ReadByIdUserId.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_ReadByIdUserId.sql @@ -4,12 +4,24 @@ AS BEGIN SET NOCOUNT ON - SELECT TOP 1 - * + SELECT + Id, + OrganizationId, + [Name], + CreationDate, + RevisionDate, + ExternalId, + MIN([ReadOnly]) AS [ReadOnly], + MIN([HidePasswords]) AS [HidePasswords] FROM [dbo].[UserCollectionDetails](@UserId) WHERE [Id] = @Id - ORDER BY - [ReadOnly] ASC -END \ No newline at end of file + GROUP BY + Id, + OrganizationId, + [Name], + CreationDate, + RevisionDate, + ExternalId +END diff --git a/src/Sql/dbo/Stored Procedures/Collection_ReadByUserId.sql b/src/Sql/dbo/Stored Procedures/Collection_ReadByUserId.sql index 4a7e18d17..01e6bb588 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_ReadByUserId.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_ReadByUserId.sql @@ -5,7 +5,21 @@ BEGIN SET NOCOUNT ON SELECT - * + Id, + OrganizationId, + [Name], + CreationDate, + RevisionDate, + ExternalId, + MIN([ReadOnly]) AS [ReadOnly], + MIN([HidePasswords]) AS [HidePasswords] FROM [dbo].[UserCollectionDetails](@UserId) -END \ No newline at end of file + GROUP BY + Id, + OrganizationId, + [Name], + CreationDate, + RevisionDate, + ExternalId +END diff --git a/util/Migrator/DbScripts/2021-07-22_00_FixCollectionReadBy.sql b/util/Migrator/DbScripts/2021-07-22_00_FixCollectionReadBy.sql new file mode 100644 index 000000000..f1c4358a9 --- /dev/null +++ b/util/Migrator/DbScripts/2021-07-22_00_FixCollectionReadBy.sql @@ -0,0 +1,66 @@ +IF OBJECT_ID('[dbo].[Collection_ReadByUserId]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Collection_ReadByUserId] +END +GO + +CREATE PROCEDURE [dbo].[Collection_ReadByUserId] + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + Id, + OrganizationId, + [Name], + CreationDate, + RevisionDate, + ExternalId, + MIN([ReadOnly]) AS [ReadOnly], + MIN([HidePasswords]) AS [HidePasswords] + FROM + [dbo].[UserCollectionDetails](@UserId) + GROUP BY + Id, + OrganizationId, + [Name], + CreationDate, + RevisionDate, + ExternalId +END +GO + +IF OBJECT_ID('[dbo].[Collection_ReadByIdUserId]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Collection_ReadByIdUserId] +END +GO + +CREATE PROCEDURE [dbo].[Collection_ReadByIdUserId] + @Id UNIQUEIDENTIFIER, + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + SELECT + Id, + OrganizationId, + [Name], + CreationDate, + RevisionDate, + ExternalId, + MIN([ReadOnly]) AS [ReadOnly], + MIN([HidePasswords]) AS [HidePasswords] + FROM + [dbo].[UserCollectionDetails](@UserId) + WHERE + [Id] = @Id + GROUP BY + Id, + OrganizationId, + [Name], + CreationDate, + RevisionDate, + ExternalId +END