mirror of
https://github.com/bitwarden/server.git
synced 2026-04-29 03:50:41 -05:00
Update OrganizationUserControllerPutTests and CollectionUserAuthorizationHandlerTests to throw BadRequestException for self-assignment attempts. Enhance unit tests to validate new exception handling and authorization logic for user and group operations.
This commit is contained in:
@@ -18,6 +18,7 @@ using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using NSubstitute;
|
||||
using NSubstitute.ExceptionExtensions;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Api.Test.AdminConsole.Controllers;
|
||||
@@ -358,7 +359,7 @@ public class OrganizationUserControllerPutTests
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task Put_FeatureFlagEnabled_SelfAssignment_ThrowsNotFound(OrganizationUserUpdateRequestModel model,
|
||||
public async Task Put_FeatureFlagEnabled_SelfAssignment_ThrowsBadRequest(OrganizationUserUpdateRequestModel model,
|
||||
OrganizationUser organizationUser, OrganizationAbility organizationAbility,
|
||||
SutProvider<OrganizationUsersController> sutProvider, Guid savingUserId)
|
||||
{
|
||||
@@ -370,14 +371,15 @@ public class OrganizationUserControllerPutTests
|
||||
.IsEnabled(FeatureFlagKeys.CollectionUserCollectionGroupAuthorizationHandlers)
|
||||
.Returns(true);
|
||||
|
||||
// Self-assignment check is now in the handler; when it denies, the extension throws NotFoundException
|
||||
// Self-assignment check in handler throws BadRequestException directly
|
||||
sutProvider.GetDependency<IAuthorizationService>()
|
||||
.AuthorizeAsync(Arg.Any<ClaimsPrincipal>(), Arg.Any<CollectionUserAccessResource>(),
|
||||
Arg.Is<IEnumerable<IAuthorizationRequirement>>(reqs => reqs.Contains(CollectionUserOperations.Create)))
|
||||
.Returns(AuthorizationResult.Failed());
|
||||
.Throws(new BadRequestException("You cannot add yourself to a collection."));
|
||||
|
||||
await Assert.ThrowsAsync<NotFoundException>(() =>
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.Put(organizationAbility.Id, organizationUser.Id, model));
|
||||
Assert.Equal("You cannot add yourself to a collection.", exception.Message);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
@@ -579,6 +579,128 @@ public class CollectionGroupAuthorizationHandlerTests
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanUpdate_WithCustomUserManageGroupsAndNoAllowAdminAccess_DoesNotSucceed(
|
||||
SutProvider<CollectionGroupAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
CurrentContextOrganization organization,
|
||||
Guid actingUserId)
|
||||
{
|
||||
organization.Type = OrganizationUserType.Custom;
|
||||
organization.Permissions = new Permissions { ManageGroups = true };
|
||||
|
||||
var resources = collections.ToList();
|
||||
|
||||
ArrangeFeatureFlag(sutProvider);
|
||||
ArrangeOrganizationAbility(sutProvider, organization, false);
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionGroupOperations.Update },
|
||||
new ClaimsPrincipal(),
|
||||
resources);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.Admin)]
|
||||
[BitAutoData(OrganizationUserType.Owner)]
|
||||
public async Task CanUpdate_WithAdminOrOwnerAndNoAllowAdminAccess_DoesNotSucceed(
|
||||
OrganizationUserType userType,
|
||||
Guid actingUserId,
|
||||
SutProvider<CollectionGroupAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions();
|
||||
|
||||
var resources = collections.ToList();
|
||||
|
||||
ArrangeFeatureFlag(sutProvider);
|
||||
ArrangeOrganizationAbility(sutProvider, organization, false);
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionGroupOperations.Update },
|
||||
new ClaimsPrincipal(),
|
||||
resources);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<ICurrentContext>().ProviderUserForOrgAsync(Arg.Any<Guid>())
|
||||
.Returns(false);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanDelete_WithCustomUserManageGroupsAndNoAllowAdminAccess_DoesNotSucceed(
|
||||
SutProvider<CollectionGroupAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
CurrentContextOrganization organization,
|
||||
Guid actingUserId)
|
||||
{
|
||||
organization.Type = OrganizationUserType.Custom;
|
||||
organization.Permissions = new Permissions { ManageGroups = true };
|
||||
|
||||
var resources = collections.ToList();
|
||||
|
||||
ArrangeFeatureFlag(sutProvider);
|
||||
ArrangeOrganizationAbility(sutProvider, organization, false);
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionGroupOperations.Delete },
|
||||
new ClaimsPrincipal(),
|
||||
resources);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.Admin)]
|
||||
[BitAutoData(OrganizationUserType.Owner)]
|
||||
public async Task CanDelete_WithAdminOrOwnerAndNoAllowAdminAccess_DoesNotSucceed(
|
||||
OrganizationUserType userType,
|
||||
Guid actingUserId,
|
||||
SutProvider<CollectionGroupAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions();
|
||||
|
||||
var resources = collections.ToList();
|
||||
|
||||
ArrangeFeatureFlag(sutProvider);
|
||||
ArrangeOrganizationAbility(sutProvider, organization, false);
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionGroupOperations.Delete },
|
||||
new ClaimsPrincipal(),
|
||||
resources);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<ICurrentContext>().ProviderUserForOrgAsync(Arg.Any<Guid>())
|
||||
.Returns(false);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
private static void ArrangeFeatureFlag(SutProvider<CollectionGroupAuthorizationHandler> sutProvider)
|
||||
{
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
|
||||
@@ -214,7 +214,7 @@ public class CollectionUserAuthorizationHandlerTests
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.Admin)]
|
||||
[BitAutoData(OrganizationUserType.Owner)]
|
||||
public async Task CanCreate_WithSelfAssignmentAndNoAllowAdminAccess_DoesNotSucceed(
|
||||
public async Task CanCreate_WithSelfAssignmentAndNoAllowAdminAccess_ThrowsBadRequest(
|
||||
OrganizationUserType userType,
|
||||
Guid actingUserId,
|
||||
SutProvider<CollectionUserAuthorizationHandler> sutProvider,
|
||||
@@ -235,9 +235,9 @@ public class CollectionUserAuthorizationHandlerTests
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.HandleAsync(context));
|
||||
Assert.Equal("You cannot add yourself to a collection.", exception.Message);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
@@ -657,6 +657,94 @@ public class CollectionUserAuthorizationHandlerTests
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.Admin)]
|
||||
[BitAutoData(OrganizationUserType.Owner)]
|
||||
public async Task CanUpdate_WithAdminOrOwnerAndNoAllowAdminAccess_DoesNotSucceed(
|
||||
OrganizationUserType userType,
|
||||
Guid actingUserId,
|
||||
SutProvider<CollectionUserAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions();
|
||||
|
||||
ArrangeFeatureFlag(sutProvider);
|
||||
ArrangeOrganizationAbility(sutProvider, organization, false);
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionUserOperations.Update },
|
||||
new ClaimsPrincipal(),
|
||||
MakeResource(collections));
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<ICurrentContext>().ProviderUserForOrgAsync(Arg.Any<Guid>())
|
||||
.Returns(false);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, CollectionCustomization]
|
||||
public async Task CanDelete_WithCustomUserManageUsersAndNoAllowAdminAccess_DoesNotSucceed(
|
||||
SutProvider<CollectionUserAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
CurrentContextOrganization organization,
|
||||
Guid actingUserId)
|
||||
{
|
||||
organization.Type = OrganizationUserType.Custom;
|
||||
organization.Permissions = new Permissions { ManageUsers = true };
|
||||
|
||||
ArrangeFeatureFlag(sutProvider);
|
||||
ArrangeOrganizationAbility(sutProvider, organization, false);
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionUserOperations.Delete },
|
||||
new ClaimsPrincipal(),
|
||||
MakeResource(collections));
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory, CollectionCustomization]
|
||||
[BitAutoData(OrganizationUserType.Admin)]
|
||||
[BitAutoData(OrganizationUserType.Owner)]
|
||||
public async Task CanDelete_WithAdminOrOwnerAndNoAllowAdminAccess_DoesNotSucceed(
|
||||
OrganizationUserType userType,
|
||||
Guid actingUserId,
|
||||
SutProvider<CollectionUserAuthorizationHandler> sutProvider,
|
||||
ICollection<Collection> collections,
|
||||
CurrentContextOrganization organization)
|
||||
{
|
||||
organization.Type = userType;
|
||||
organization.Permissions = new Permissions();
|
||||
|
||||
ArrangeFeatureFlag(sutProvider);
|
||||
ArrangeOrganizationAbility(sutProvider, organization, false);
|
||||
|
||||
var context = new AuthorizationHandlerContext(
|
||||
new[] { CollectionUserOperations.Delete },
|
||||
new ClaimsPrincipal(),
|
||||
MakeResource(collections));
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<ICurrentContext>().ProviderUserForOrgAsync(Arg.Any<Guid>())
|
||||
.Returns(false);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(context);
|
||||
|
||||
Assert.False(context.HasSucceeded);
|
||||
}
|
||||
|
||||
private static CollectionUserAccessResource MakeResource<T>(
|
||||
ICollection<T> collections, Guid? targetUserId = null) where T : Collection
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user