1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-24 04:38:48 -05:00

add GetAllOrganizationCiphersExcludingDefaultUserCollections

This commit is contained in:
jaasen-livefront 2025-06-20 15:45:03 -07:00
parent cdfe51f9d6
commit 79e6b8d7a2
No known key found for this signature in database
4 changed files with 80 additions and 5 deletions

View File

@ -45,6 +45,7 @@ public class CiphersController : Controller
private readonly IOrganizationCiphersQuery _organizationCiphersQuery;
private readonly IApplicationCacheService _applicationCacheService;
private readonly ICollectionRepository _collectionRepository;
private readonly IFeatureService _featureService;
public CiphersController(
ICipherRepository cipherRepository,
@ -58,7 +59,8 @@ public class CiphersController : Controller
GlobalSettings globalSettings,
IOrganizationCiphersQuery organizationCiphersQuery,
IApplicationCacheService applicationCacheService,
ICollectionRepository collectionRepository)
ICollectionRepository collectionRepository,
IFeatureService featureService)
{
_cipherRepository = cipherRepository;
_collectionCipherRepository = collectionCipherRepository;
@ -72,6 +74,7 @@ public class CiphersController : Controller
_organizationCiphersQuery = organizationCiphersQuery;
_applicationCacheService = applicationCacheService;
_collectionRepository = collectionRepository;
_featureService = featureService;
}
[HttpGet("{id}")]
@ -306,8 +309,11 @@ public class CiphersController : Controller
{
throw new NotFoundException();
}
var allOrganizationCiphers = await _organizationCiphersQuery.GetAllOrganizationCiphers(organizationId);
var allOrganizationCiphers = _featureService.IsEnabled(FeatureFlagKeys.CreateDefaultLocation)
?
await _organizationCiphersQuery.GetAllOrganizationCiphersExcludingDefaultUserCollections(organizationId)
:
await _organizationCiphersQuery.GetAllOrganizationCiphers(organizationId);
var allOrganizationCipherResponses =
allOrganizationCiphers.Select(c =>

View File

@ -37,4 +37,10 @@ public interface IOrganizationCiphersQuery
/// </remarks>
public Task<IEnumerable<CipherOrganizationDetailsWithCollections>> GetOrganizationCiphersByCollectionIds(
Guid organizationId, IEnumerable<Guid> collectionIds);
/// <summary>
/// Returns all organization ciphers except those in default user collections.
/// </summary>
public Task<IEnumerable<CipherOrganizationDetailsWithCollections>>
GetAllOrganizationCiphersExcludingDefaultUserCollections(Guid organizationId);
}

View File

@ -1,4 +1,5 @@
using Bit.Core.Repositories;
using Bit.Core.Enums;
using Bit.Core.Repositories;
using Bit.Core.Vault.Models.Data;
using Bit.Core.Vault.Repositories;
@ -8,11 +9,13 @@ public class OrganizationCiphersQuery : IOrganizationCiphersQuery
{
private readonly ICipherRepository _cipherRepository;
private readonly ICollectionCipherRepository _collectionCipherRepository;
private readonly ICollectionRepository _collectionRepository;
public OrganizationCiphersQuery(ICipherRepository cipherRepository, ICollectionCipherRepository collectionCipherRepository)
public OrganizationCiphersQuery(ICipherRepository cipherRepository, ICollectionCipherRepository collectionCipherRepository, ICollectionRepository collectionRepository)
{
_cipherRepository = cipherRepository;
_collectionCipherRepository = collectionCipherRepository;
_collectionRepository = collectionRepository;
}
/// <summary>
@ -61,4 +64,28 @@ public class OrganizationCiphersQuery : IOrganizationCiphersQuery
var allOrganizationCiphers = await GetAllOrganizationCiphers(organizationId);
return allOrganizationCiphers.Where(c => c.CollectionIds.Intersect(managedCollectionIds).Any());
}
public async Task<IEnumerable<CipherOrganizationDetailsWithCollections>>
GetAllOrganizationCiphersExcludingDefaultUserCollections(Guid orgId)
{
var defaultCollIds = (await _collectionRepository
.GetManyByOrganizationIdAsync(orgId))
.Where(col => col.Type == CollectionType.DefaultUserCollection)
.Select(col => col.Id)
.ToHashSet();
var cipherGroups = (await _collectionCipherRepository
.GetManyByOrganizationIdAsync(orgId))
.GroupBy(cc => cc.CipherId)
.ToDictionary(g => g.Key, g => g);
return (await _cipherRepository
.GetManyOrganizationDetailsByOrganizationIdAsync(orgId))
.Where(c =>
// select ciphers with no collections or none of its collections are default
!cipherGroups.TryGetValue(c.Id, out var grp)
|| !grp.Any(cc => defaultCollIds.Contains(cc.CollectionId))
)
.Select(c => new CipherOrganizationDetailsWithCollections(c, cipherGroups));
}
}

View File

@ -1,5 +1,6 @@
using AutoFixture;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Repositories;
using Bit.Core.Vault.Models.Data;
using Bit.Core.Vault.Queries;
@ -89,4 +90,39 @@ public class OrganizationCiphersQueryTests
c.CollectionIds.Any(cId => cId == targetCollectionId) &&
c.CollectionIds.Any(cId => cId == otherCollectionId));
}
[Theory, BitAutoData]
public async Task GetAllOrganizationCiphersExcludingDefaultUserCollections_ExcludesCiphersInDefaultCollections(
Guid organizationId, SutProvider<OrganizationCiphersQuery> sutProvider)
{
var defaultColId = Guid.NewGuid();
var otherColId = Guid.NewGuid();
var cipherDefault = new CipherOrganizationDetails { Id = Guid.NewGuid(), OrganizationId = organizationId, OrganizationUseTotp = false };
var cipherOther = new CipherOrganizationDetails { Id = Guid.NewGuid(), OrganizationId = organizationId, OrganizationUseTotp = false };
var ciphers = new[] { cipherDefault, cipherOther };
var collections = new[] {
new Collection { Id = defaultColId, OrganizationId = organizationId, Type = CollectionType.DefaultUserCollection },
new Collection { Id = otherColId, OrganizationId = organizationId, Type = CollectionType.SharedCollection }
};
var collectionsCiphers = new[] {
new CollectionCipher { CollectionId = defaultColId, CipherId = cipherDefault.Id },
new CollectionCipher { CollectionId = otherColId, CipherId = cipherOther.Id }
};
sutProvider.GetDependency<ICipherRepository>().GetManyOrganizationDetailsByOrganizationIdAsync(organizationId)
.Returns(ciphers);
sutProvider.GetDependency<ICollectionRepository>().GetManyByOrganizationIdAsync(organizationId)
.Returns(collections);
sutProvider.GetDependency<ICollectionCipherRepository>().GetManyByOrganizationIdAsync(organizationId)
.Returns(collectionsCiphers);
var result = (await sutProvider.Sut
.GetAllOrganizationCiphersExcludingDefaultUserCollections(organizationId))
.ToList();
Assert.Single(result);
Assert.Equal(cipherOther.Id, result.Single().Id);
}
}