1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-25 12:45:18 +01:00
bitwarden-server/test/Api.Test/Vault/AuthorizationHandlers/OrganizationUserAuthorizationHandlerTests.cs
Thomas Rittson 96f9fbb951
[AC-2027] Update Flexible Collections logic to use organization property (#3644)
* Update optionality to use org.FlexibleCollections

Also break old feature flag key to ensure it's never enabled

* Add logic to set defaults for collection management setting

* Update optionality logic to use org property

* Add comments

* Add helper method for getting individual orgAbility

* Fix validate user update permissions interface

* Fix tests

* dotnet format

* Fix more tests

* Simplify self-hosted update logic

* Fix mapping

* Use new getOrganizationAbility method

* Refactor invite and save orgUser methods

Pass in whole organization object instead of using OrganizationAbility

* fix CipherService tests

* dotnet format

* Remove manager check to simplify this set of changes

* Misc cleanup before review

* Fix undefined variable

* Refactor bulk-access endpoint to avoid early repo call

* Restore manager check

* Add tests for UpdateOrganizationLicenseCommand

* Add nullable regions

* Delete unused dependency

* dotnet format

* Fix test
2024-01-17 12:33:35 +00:00

215 lines
7.9 KiB
C#

using System.Security.Claims;
using Bit.Api.Vault.AuthorizationHandlers.OrganizationUsers;
using Bit.Core.Context;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
using Bit.Core.Models.Data.Organizations;
using Bit.Core.Services;
using Bit.Test.Common.AutoFixture;
using Bit.Test.Common.AutoFixture.Attributes;
using Microsoft.AspNetCore.Authorization;
using NSubstitute;
using Xunit;
namespace Bit.Api.Test.Vault.AuthorizationHandlers;
[SutProviderCustomize]
public class OrganizationUserAuthorizationHandlerTests
{
[Theory]
[BitAutoData(OrganizationUserType.Admin)]
[BitAutoData(OrganizationUserType.Owner)]
public async Task CanReadAllAsync_WhenAdminOrOwner_Success(
OrganizationUserType userType,
Guid userId, SutProvider<OrganizationUserAuthorizationHandler> sutProvider,
CurrentContextOrganization organization)
{
organization.Type = userType;
organization.Permissions = new Permissions();
ArrangeOrganizationAbility(sutProvider, organization, true);
var context = new AuthorizationHandlerContext(
new[] { OrganizationUserOperations.ReadAll(organization.Id) },
new ClaimsPrincipal(),
null);
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(userId);
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
await sutProvider.Sut.HandleAsync(context);
Assert.True(context.HasSucceeded);
}
[Theory, BitAutoData]
public async Task CanReadAllAsync_WithProviderUser_Success(
Guid userId,
SutProvider<OrganizationUserAuthorizationHandler> sutProvider, CurrentContextOrganization organization)
{
organization.Type = OrganizationUserType.User;
organization.Permissions = new Permissions();
ArrangeOrganizationAbility(sutProvider, organization, true);
var context = new AuthorizationHandlerContext(
new[] { OrganizationUserOperations.ReadAll(organization.Id) },
new ClaimsPrincipal(),
null);
sutProvider.GetDependency<ICurrentContext>()
.UserId
.Returns(userId);
sutProvider.GetDependency<ICurrentContext>()
.ProviderUserForOrgAsync(organization.Id)
.Returns(true);
await sutProvider.Sut.HandleAsync(context);
Assert.True(context.HasSucceeded);
}
[Theory]
[BitAutoData(true, false, false, false, true)]
[BitAutoData(false, true, false, false, true)]
[BitAutoData(false, false, true, false, true)]
[BitAutoData(false, false, false, true, true)]
[BitAutoData(false, false, false, false, false)]
public async Task CanReadAllAsync_WhenCustomUserWithRequiredPermissions_Success(
bool editAnyCollection, bool deleteAnyCollection, bool manageGroups,
bool manageUsers, bool limitCollectionCreationDeletion,
SutProvider<OrganizationUserAuthorizationHandler> sutProvider,
CurrentContextOrganization organization)
{
var actingUserId = Guid.NewGuid();
organization.Type = OrganizationUserType.Custom;
organization.Permissions = new Permissions
{
EditAnyCollection = editAnyCollection,
DeleteAnyCollection = deleteAnyCollection,
ManageGroups = manageGroups,
ManageUsers = manageUsers
};
ArrangeOrganizationAbility(sutProvider, organization, limitCollectionCreationDeletion);
var context = new AuthorizationHandlerContext(
new[] { OrganizationUserOperations.ReadAll(organization.Id) },
new ClaimsPrincipal(),
null);
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(actingUserId);
sutProvider.GetDependency<ICurrentContext>().GetOrganization(organization.Id).Returns(organization);
await sutProvider.Sut.HandleAsync(context);
Assert.True(context.HasSucceeded);
}
[Theory]
[BitAutoData(OrganizationUserType.User)]
[BitAutoData(OrganizationUserType.Custom)]
public async Task CanReadAllAsync_WhenMissingPermissions_NoSuccess(
OrganizationUserType userType,
SutProvider<OrganizationUserAuthorizationHandler> sutProvider,
CurrentContextOrganization organization)
{
var actingUserId = Guid.NewGuid();
organization.Type = userType;
organization.Permissions = new Permissions
{
EditAnyCollection = false,
DeleteAnyCollection = false,
ManageGroups = false,
ManageUsers = false
};
ArrangeOrganizationAbility(sutProvider, organization, true);
var context = new AuthorizationHandlerContext(
new[] { OrganizationUserOperations.ReadAll(organization.Id) },
new ClaimsPrincipal(),
null);
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]
public async Task HandleRequirementAsync_WhenMissingOrgAccess_NoSuccess(
Guid userId,
CurrentContextOrganization organization,
SutProvider<OrganizationUserAuthorizationHandler> sutProvider)
{
ArrangeOrganizationAbility(sutProvider, organization, true);
var context = new AuthorizationHandlerContext(
new[] { OrganizationUserOperations.ReadAll(organization.Id) },
new ClaimsPrincipal(),
null
);
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(userId);
sutProvider.GetDependency<ICurrentContext>().GetOrganization(Arg.Any<Guid>()).Returns((CurrentContextOrganization)null);
sutProvider.GetDependency<ICurrentContext>().ProviderUserForOrgAsync(Arg.Any<Guid>()).Returns(false);
await sutProvider.Sut.HandleAsync(context);
Assert.False(context.HasSucceeded);
}
[Theory, BitAutoData]
public async Task HandleRequirementAsync_MissingUserId_Failure(
Guid organizationId,
SutProvider<OrganizationUserAuthorizationHandler> sutProvider)
{
var context = new AuthorizationHandlerContext(
new[] { OrganizationUserOperations.ReadAll(organizationId) },
new ClaimsPrincipal(),
null
);
// Simulate missing user id
sutProvider.GetDependency<ICurrentContext>().UserId.Returns((Guid?)null);
await sutProvider.Sut.HandleAsync(context);
Assert.True(context.HasFailed);
}
[Theory, BitAutoData]
public async Task HandleRequirementAsync_NoSpecifiedOrgId_Failure(
SutProvider<OrganizationUserAuthorizationHandler> sutProvider)
{
var context = new AuthorizationHandlerContext(
new[] { OrganizationUserOperations.ReadAll(default) },
new ClaimsPrincipal(),
null
);
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(new Guid());
await sutProvider.Sut.HandleAsync(context);
Assert.True(context.HasFailed);
}
private static void ArrangeOrganizationAbility(
SutProvider<OrganizationUserAuthorizationHandler> sutProvider,
CurrentContextOrganization organization, bool limitCollectionCreationDeletion)
{
var organizationAbility = new OrganizationAbility();
organizationAbility.Id = organization.Id;
organizationAbility.FlexibleCollections = true;
organizationAbility.LimitCollectionCreationDeletion = limitCollectionCreationDeletion;
sutProvider.GetDependency<IApplicationCacheService>().GetOrganizationAbilityAsync(organizationAbility.Id)
.Returns(organizationAbility);
}
}