diff --git a/src/Api/Vault/AuthorizationHandlers/Collections/CollectionAuthorizationHandler.cs b/src/Api/Vault/AuthorizationHandlers/Collections/CollectionAuthorizationHandler.cs
index 9663bbdd63..509d2fe433 100644
--- a/src/Api/Vault/AuthorizationHandlers/Collections/CollectionAuthorizationHandler.cs
+++ b/src/Api/Vault/AuthorizationHandlers/Collections/CollectionAuthorizationHandler.cs
@@ -10,11 +10,84 @@ using Microsoft.AspNetCore.Authorization;
namespace Bit.Api.Vault.AuthorizationHandlers.Collections;
+///
+/// Handles authorization logic for Collection operations.
+/// This uses new logic implemented in the Flexible Collections initiative.
+///
+public class CollectionAuthorizationHandler : AuthorizationHandler
+{
+ private readonly ICurrentContext _currentContext;
+ private readonly IFeatureService _featureService;
+
+ private bool FlexibleCollectionsIsEnabled => _featureService.IsEnabled(FeatureFlagKeys.FlexibleCollections, _currentContext);
+
+ public CollectionAuthorizationHandler(
+ ICurrentContext currentContext,
+ IFeatureService featureService)
+ {
+ _currentContext = currentContext;
+ _featureService = featureService;
+ }
+
+ protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,
+ CollectionOperationRequirement requirement)
+ {
+ if (!FlexibleCollectionsIsEnabled)
+ {
+ // Flexible collections is OFF, should not be using this handler
+ throw new FeatureUnavailableException("Flexible collections is OFF when it should be ON.");
+ }
+
+ if (!_currentContext.UserId.HasValue)
+ {
+ context.Fail();
+ return;
+ }
+
+ var targetOrganizationId = requirement.OrganizationId;
+ if (targetOrganizationId == default)
+ {
+ context.Fail();
+ return;
+ }
+
+ // Acting user is not a member of the target organization, fail
+ var org = _currentContext.GetOrganization(targetOrganizationId);
+ if (org == null)
+ {
+ context.Fail();
+ return;
+ }
+
+ switch (requirement)
+ {
+ case not null when requirement.Name == nameof(CollectionOperations.ReadAll):
+ await CanReadAllAsync(context, requirement, org);
+ break;
+ }
+ }
+
+ private async Task CanReadAllAsync(AuthorizationHandlerContext context, CollectionOperationRequirement requirement,
+ CurrentContextOrganization org)
+ {
+ if (org.Type is OrganizationUserType.Owner or OrganizationUserType.Admin ||
+ org.Permissions.ManageGroups ||
+ org.Permissions.ManageUsers ||
+ org.Permissions.EditAnyCollection ||
+ org.Permissions.DeleteAnyCollection ||
+ org.Permissions.AccessImportExport ||
+ await _currentContext.ProviderUserForOrgAsync(org.Id))
+ {
+ context.Succeed(requirement);
+ }
+ }
+}
+
///
/// Handles authorization logic for Collection objects, including access permissions for users and groups.
/// This uses new logic implemented in the Flexible Collections initiative.
///
-public class CollectionAuthorizationHandler : BulkAuthorizationHandler
+public class BulkCollectionAuthorizationHandler : BulkAuthorizationHandler
{
private readonly ICurrentContext _currentContext;
private readonly ICollectionRepository _collectionRepository;
@@ -22,7 +95,9 @@ public class CollectionAuthorizationHandler : BulkAuthorizationHandler _featureService.IsEnabled(FeatureFlagKeys.FlexibleCollections, _currentContext);
- public CollectionAuthorizationHandler(ICurrentContext currentContext, ICollectionRepository collectionRepository,
+ public BulkCollectionAuthorizationHandler(
+ ICurrentContext currentContext,
+ ICollectionRepository collectionRepository,
IFeatureService featureService)
{
_currentContext = currentContext;
@@ -53,7 +128,13 @@ public class CollectionAuthorizationHandler : BulkAuthorizationHandler tc.OrganizationId != targetOrganizationId))
@@ -79,10 +160,6 @@ public class CollectionAuthorizationHandler : BulkAuthorizationHandler targetCollections, CurrentContextOrganization org)
{
diff --git a/src/Api/Vault/AuthorizationHandlers/Collections/CollectionOperations.cs b/src/Api/Vault/AuthorizationHandlers/Collections/CollectionOperations.cs
index c85c8fcd8f..960addfa6d 100644
--- a/src/Api/Vault/AuthorizationHandlers/Collections/CollectionOperations.cs
+++ b/src/Api/Vault/AuthorizationHandlers/Collections/CollectionOperations.cs
@@ -4,7 +4,7 @@ namespace Bit.Api.Vault.AuthorizationHandlers.Collections;
public class CollectionOperationRequirement : OperationAuthorizationRequirement
{
- public Guid OrganizationId { get; set; }
+ public Guid OrganizationId { get; init; }
public CollectionOperationRequirement() { }