diff --git a/src/Api/Vault/AuthorizationHandlers/Collections/BulkCollectionAuthorizationHandler.cs b/src/Api/Vault/AuthorizationHandlers/Collections/BulkCollectionAuthorizationHandler.cs index 0638d16d6..d836b18e3 100644 --- a/src/Api/Vault/AuthorizationHandlers/Collections/BulkCollectionAuthorizationHandler.cs +++ b/src/Api/Vault/AuthorizationHandlers/Collections/BulkCollectionAuthorizationHandler.cs @@ -217,12 +217,22 @@ public class BulkCollectionAuthorizationHandler : BulkAuthorizationHandler CanUpdateUserAccessAsync(ICollection resources, CurrentContextOrganization? org) { - return await CanUpdateCollectionAsync(resources, org) || org?.Permissions.ManageUsers == true; + if (await AllowAdminAccessToAllCollectionItems(org) && org?.Permissions.ManageUsers == true) + { + return true; + } + + return await CanUpdateCollectionAsync(resources, org); } private async Task CanUpdateGroupAccessAsync(ICollection resources, CurrentContextOrganization? org) { - return await CanUpdateCollectionAsync(resources, org) || org?.Permissions.ManageGroups == true; + if (await AllowAdminAccessToAllCollectionItems(org) && org?.Permissions.ManageGroups == true) + { + return true; + } + + return await CanUpdateCollectionAsync(resources, org); } private async Task CanDeleteAsync(ICollection resources, CurrentContextOrganization? org) @@ -313,4 +323,11 @@ public class BulkCollectionAuthorizationHandler : BulkAuthorizationHandler AllowAdminAccessToAllCollectionItems(CurrentContextOrganization? org) + { + var organizationAbility = await GetOrganizationAbilityAsync(org); + return !_featureService.IsEnabled(FeatureFlagKeys.FlexibleCollectionsV1) || + organizationAbility is { AllowAdminAccessToAllCollectionItems: true }; + } } diff --git a/test/Api.Test/Vault/AuthorizationHandlers/BulkCollectionAuthorizationHandlerTests.cs b/test/Api.Test/Vault/AuthorizationHandlers/BulkCollectionAuthorizationHandlerTests.cs index 527896f93..dbc076bf7 100644 --- a/test/Api.Test/Vault/AuthorizationHandlers/BulkCollectionAuthorizationHandlerTests.cs +++ b/test/Api.Test/Vault/AuthorizationHandlers/BulkCollectionAuthorizationHandlerTests.cs @@ -828,79 +828,167 @@ public class BulkCollectionAuthorizationHandlerTests } [Theory, BitAutoData, CollectionCustomization] - public async Task CanUpdateUsers_WithManageUsersCustomPermission_Success( - SutProvider sutProvider, - ICollection collections, - CurrentContextOrganization organization) + public async Task CanUpdateUsers_WithManageUsersCustomPermission_V1Disabled_Success( + SutProvider sutProvider, ICollection collections, + CurrentContextOrganization organization, Guid actingUserId) { - var actingUserId = Guid.NewGuid(); - organization.Type = OrganizationUserType.Custom; organization.Permissions = new Permissions { ManageUsers = true }; - var operationsToTest = new[] - { - BulkCollectionOperations.ModifyUserAccess, - }; + sutProvider.GetDependency().UserId.Returns(actingUserId); + sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); + sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.FlexibleCollectionsV1) + .Returns(false); - foreach (var op in operationsToTest) - { - sutProvider.GetDependency().UserId.Returns(actingUserId); - sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); + var context = new AuthorizationHandlerContext( + new[] { BulkCollectionOperations.ModifyUserAccess }, + new ClaimsPrincipal(), + collections); - var context = new AuthorizationHandlerContext( - new[] { op }, - new ClaimsPrincipal(), - collections); + await sutProvider.Sut.HandleAsync(context); - await sutProvider.Sut.HandleAsync(context); - - Assert.True(context.HasSucceeded); - - // Recreate the SUT to reset the mocks/dependencies between tests - sutProvider.Recreate(); - } + Assert.True(context.HasSucceeded); } [Theory, BitAutoData, CollectionCustomization] - public async Task CanUpdateGroups_WithManageGroupsCustomPermission_Success( - SutProvider sutProvider, - ICollection collections, - CurrentContextOrganization organization) + public async Task CanUpdateUsers_WithManageUsersCustomPermission_AllowAdminAccessIsTrue_Success( + SutProvider sutProvider, ICollection collections, + CurrentContextOrganization organization, Guid actingUserId) { - var actingUserId = Guid.NewGuid(); + organization.Type = OrganizationUserType.Custom; + organization.Permissions = new Permissions + { + ManageUsers = true + }; + sutProvider.GetDependency().UserId.Returns(actingUserId); + sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); + sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.FlexibleCollectionsV1) + .Returns(true); + sutProvider.GetDependency().GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility { AllowAdminAccessToAllCollectionItems = true }); + + var context = new AuthorizationHandlerContext( + new[] { BulkCollectionOperations.ModifyUserAccess }, + new ClaimsPrincipal(), + collections); + + await sutProvider.Sut.HandleAsync(context); + + Assert.True(context.HasSucceeded); + } + + [Theory, BitAutoData, CollectionCustomization] + public async Task CanUpdateUsers_WithManageUsersCustomPermission_AllowAdminAccessIsFalse_Failure( + SutProvider sutProvider, ICollection collections, + CurrentContextOrganization organization, Guid actingUserId) + { + organization.Type = OrganizationUserType.Custom; + organization.Permissions = new Permissions + { + ManageUsers = true + }; + + sutProvider.GetDependency().UserId.Returns(actingUserId); + sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); + sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.FlexibleCollectionsV1) + .Returns(true); + sutProvider.GetDependency().GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility { AllowAdminAccessToAllCollectionItems = false }); + + var context = new AuthorizationHandlerContext( + new[] { BulkCollectionOperations.ModifyUserAccess }, + new ClaimsPrincipal(), + collections); + + await sutProvider.Sut.HandleAsync(context); + + Assert.False(context.HasSucceeded); + } + + [Theory, BitAutoData, CollectionCustomization] + public async Task CanUpdateGroups_WithManageGroupsCustomPermission_V1Disabled_Success( + SutProvider sutProvider, ICollection collections, + CurrentContextOrganization organization, Guid actingUserId) + { organization.Type = OrganizationUserType.Custom; organization.Permissions = new Permissions { ManageGroups = true }; - var operationsToTest = new[] + sutProvider.GetDependency().UserId.Returns(actingUserId); + sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); + sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.FlexibleCollectionsV1) + .Returns(false); + + var context = new AuthorizationHandlerContext( + new[] { BulkCollectionOperations.ModifyGroupAccess }, + new ClaimsPrincipal(), + collections); + + await sutProvider.Sut.HandleAsync(context); + + Assert.True(context.HasSucceeded); + } + + [Theory, BitAutoData, CollectionCustomization] + public async Task CanUpdateGroups_WithManageGroupsCustomPermission_AllowAdminAccessIsTrue_Success( + SutProvider sutProvider, ICollection collections, + CurrentContextOrganization organization, Guid actingUserId) + { + organization.Type = OrganizationUserType.Custom; + organization.Permissions = new Permissions { - BulkCollectionOperations.ModifyGroupAccess, + ManageGroups = true }; - foreach (var op in operationsToTest) + sutProvider.GetDependency().UserId.Returns(actingUserId); + sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); + sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.FlexibleCollectionsV1) + .Returns(true); + sutProvider.GetDependency().GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility { AllowAdminAccessToAllCollectionItems = true }); + + var context = new AuthorizationHandlerContext( + new[] { BulkCollectionOperations.ModifyGroupAccess }, + new ClaimsPrincipal(), + collections); + + await sutProvider.Sut.HandleAsync(context); + + Assert.True(context.HasSucceeded); + } + + [Theory, BitAutoData, CollectionCustomization] + public async Task CanUpdateGroups_WithManageGroupsCustomPermission_AllowAdminAccessIsFalse_Failure( + SutProvider sutProvider, ICollection collections, + CurrentContextOrganization organization, Guid actingUserId) + { + organization.Type = OrganizationUserType.Custom; + organization.Permissions = new Permissions { - sutProvider.GetDependency().UserId.Returns(actingUserId); - sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); + ManageGroups = true + }; - var context = new AuthorizationHandlerContext( - new[] { op }, - new ClaimsPrincipal(), - collections); + sutProvider.GetDependency().UserId.Returns(actingUserId); + sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); + sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.FlexibleCollectionsV1) + .Returns(true); + sutProvider.GetDependency().GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility { AllowAdminAccessToAllCollectionItems = false }); - await sutProvider.Sut.HandleAsync(context); + var context = new AuthorizationHandlerContext( + new[] { BulkCollectionOperations.ModifyGroupAccess }, + new ClaimsPrincipal(), + collections); - Assert.True(context.HasSucceeded); + await sutProvider.Sut.HandleAsync(context); - // Recreate the SUT to reset the mocks/dependencies between tests - sutProvider.Recreate(); - } + Assert.False(context.HasSucceeded); } [Theory, BitAutoData, CollectionCustomization]