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() { }