1
0
mirror of https://github.com/bitwarden/server.git synced 2025-05-20 11:04:31 -05:00

[PS-1806] Fix EF CollectionRepository GetManyByUserId (#2409)

* Rewrite ReadOnly and HidePasswords

* Rewrote them to generate a CASE statement similar to T-SQL

* Rewrite Grouping Expression

* Use multiple groups just like T-SQL
* Run it all on the database instead of in memory

* Fix linter
This commit is contained in:
Justin Baur 2022-11-14 10:18:09 -05:00 committed by GitHub
parent 9ecf69d9ca
commit b24ce17193
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 15 deletions

View File

@ -131,19 +131,19 @@ public class CollectionRepository : Repository<Core.Entities.Collection, Collect
using (var scope = ServiceScopeFactory.CreateScope()) using (var scope = ServiceScopeFactory.CreateScope())
{ {
var dbContext = GetDatabaseContext(scope); var dbContext = GetDatabaseContext(scope);
return (await new UserCollectionDetailsQuery(userId).Run(dbContext).ToListAsync()) return await (from c in new UserCollectionDetailsQuery(userId).Run(dbContext)
.GroupBy(c => c.Id) group c by new { c.Id, c.OrganizationId, c.Name, c.CreationDate, c.RevisionDate, c.ExternalId } into collectionGroup
.Select(g => new CollectionDetails select new CollectionDetails
{ {
Id = g.Key, Id = collectionGroup.Key.Id,
OrganizationId = g.FirstOrDefault().OrganizationId, OrganizationId = collectionGroup.Key.OrganizationId,
Name = g.FirstOrDefault().Name, Name = collectionGroup.Key.Name,
ExternalId = g.FirstOrDefault().ExternalId, CreationDate = collectionGroup.Key.CreationDate,
CreationDate = g.FirstOrDefault().CreationDate, RevisionDate = collectionGroup.Key.RevisionDate,
RevisionDate = g.FirstOrDefault().RevisionDate, ExternalId = collectionGroup.Key.ExternalId,
ReadOnly = g.Min(c => c.ReadOnly), ReadOnly = collectionGroup.Min(c => c.ReadOnly),
HidePasswords = g.Min(c => c.HidePasswords) HidePasswords = collectionGroup.Min(c => c.HidePasswords),
}).ToList(); }).ToListAsync();
} }
} }

View File

@ -10,6 +10,7 @@ public class UserCollectionDetailsQuery : IQuery<CollectionDetails>
{ {
_userId = userId; _userId = userId;
} }
public virtual IQueryable<CollectionDetails> Run(DatabaseContext dbContext) public virtual IQueryable<CollectionDetails> Run(DatabaseContext dbContext)
{ {
var query = from c in dbContext.Collections var query = from c in dbContext.Collections
@ -44,6 +45,8 @@ public class UserCollectionDetailsQuery : IQuery<CollectionDetails>
o.Enabled && o.Enabled &&
(ou.AccessAll || cu.CollectionId != null || g.AccessAll || cg.CollectionId != null) (ou.AccessAll || cu.CollectionId != null || g.AccessAll || cg.CollectionId != null)
select new { c, ou, o, cu, gu, g, cg }; select new { c, ou, o, cu, gu, g, cg };
#pragma warning disable IDE0075
// I want to leave the ReadOnly and HidePasswords the way they are because it helps show the exact logic we are trying to replicate
return query.Select(x => new CollectionDetails return query.Select(x => new CollectionDetails
{ {
Id = x.c.Id, Id = x.c.Id,
@ -52,8 +55,11 @@ public class UserCollectionDetailsQuery : IQuery<CollectionDetails>
ExternalId = x.c.ExternalId, ExternalId = x.c.ExternalId,
CreationDate = x.c.CreationDate, CreationDate = x.c.CreationDate,
RevisionDate = x.c.RevisionDate, RevisionDate = x.c.RevisionDate,
ReadOnly = !x.ou.AccessAll || !x.g.AccessAll || (x.cu.ReadOnly || x.cg.ReadOnly), ReadOnly = x.ou.AccessAll || x.g.AccessAll || ((x.cu != null ? x.cu.ReadOnly : (bool?)null) ?? (x.cg != null ? x.cg.ReadOnly : (bool?)null) ?? false) ? false : true,
HidePasswords = !x.ou.AccessAll || !x.g.AccessAll || (x.cu.HidePasswords || x.cg.HidePasswords), HidePasswords = x.ou.AccessAll || x.g.AccessAll || ((x.cu != null ? x.cu.HidePasswords : (bool?)null) ?? (x.cg != null ? x.cg.HidePasswords : (bool?)null) ?? false) ? false : true,
}); });
#pragma warning restore IDE0075
} }
} }