1
0
mirror of https://github.com/bitwarden/server.git synced 2024-12-22 16:57:36 +01:00

[AC-2887] Added Billing Authorization Where Missing (#4525)

* Added missing authorization validation to OrganizationBillingController endpoints

* Moved authorization validation to top of each method

* Resolved broken unit tests and added some new ones
This commit is contained in:
Conner Turnbull 2024-07-17 16:15:28 -04:00 committed by GitHub
parent 88d5a97a86
commit 45ec57f81b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 85 additions and 6 deletions

View File

@ -20,6 +20,11 @@ public class OrganizationBillingController(
[HttpGet("metadata")]
public async Task<IResult> GetMetadataAsync([FromRoute] Guid organizationId)
{
if (!await currentContext.ViewBillingHistory(organizationId))
{
return TypedResults.Unauthorized();
}
var metadata = await organizationBillingService.GetMetadata(organizationId);
if (metadata == null)
@ -35,6 +40,11 @@ public class OrganizationBillingController(
[HttpGet("history")]
public async Task<IResult> GetHistoryAsync([FromRoute] Guid organizationId)
{
if (!await currentContext.ViewBillingHistory(organizationId))
{
return TypedResults.Unauthorized();
}
var organization = await organizationRepository.GetByIdAsync(organizationId);
if (organization == null)

View File

@ -162,13 +162,13 @@ public class OrganizationsController(
[SelfHosted(NotSelfHostedOnly = true)]
public async Task PostSmSubscription(Guid id, [FromBody] SecretsManagerSubscriptionUpdateRequestModel model)
{
var organization = await organizationRepository.GetByIdAsync(id);
if (organization == null)
if (!await currentContext.EditSubscription(id))
{
throw new NotFoundException();
}
if (!await currentContext.EditSubscription(id))
var organization = await organizationRepository.GetByIdAsync(id);
if (organization == null)
{
throw new NotFoundException();
}
@ -195,13 +195,13 @@ public class OrganizationsController(
[SelfHosted(NotSelfHostedOnly = true)]
public async Task<ProfileOrganizationResponseModel> PostSubscribeSecretsManagerAsync(Guid id, [FromBody] SecretsManagerSubscribeRequestModel model)
{
var organization = await organizationRepository.GetByIdAsync(id);
if (organization == null)
if (!await currentContext.EditSubscription(id))
{
throw new NotFoundException();
}
if (!await currentContext.EditSubscription(id))
var organization = await organizationRepository.GetByIdAsync(id);
if (organization == null)
{
throw new NotFoundException();
}

View File

@ -1,7 +1,11 @@
using Bit.Api.Billing.Controllers;
using Bit.Api.Billing.Models.Responses;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.Billing.Models;
using Bit.Core.Billing.Services;
using Bit.Core.Context;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Test.Common.AutoFixture;
using Bit.Test.Common.AutoFixture.Attributes;
using Microsoft.AspNetCore.Http.HttpResults;
@ -14,11 +18,26 @@ namespace Bit.Api.Test.Billing.Controllers;
[SutProviderCustomize]
public class OrganizationBillingControllerTests
{
[Theory, BitAutoData]
public async Task GetMetadataAsync_Unauthorized_ReturnsUnauthorized(
Guid organizationId,
SutProvider<OrganizationBillingController> sutProvider)
{
sutProvider.GetDependency<ICurrentContext>().ViewBillingHistory(organizationId).Returns(false);
var result = await sutProvider.Sut.GetMetadataAsync(organizationId);
Assert.IsType<UnauthorizedHttpResult>(result);
}
[Theory, BitAutoData]
public async Task GetMetadataAsync_MetadataNull_NotFound(
Guid organizationId,
SutProvider<OrganizationBillingController> sutProvider)
{
sutProvider.GetDependency<ICurrentContext>().ViewBillingHistory(organizationId).Returns(true);
sutProvider.GetDependency<IOrganizationBillingService>().GetMetadata(organizationId).Returns((OrganizationMetadataDTO)null);
var result = await sutProvider.Sut.GetMetadataAsync(organizationId);
Assert.IsType<NotFound>(result);
@ -29,6 +48,7 @@ public class OrganizationBillingControllerTests
Guid organizationId,
SutProvider<OrganizationBillingController> sutProvider)
{
sutProvider.GetDependency<ICurrentContext>().ViewBillingHistory(organizationId).Returns(true);
sutProvider.GetDependency<IOrganizationBillingService>().GetMetadata(organizationId)
.Returns(new OrganizationMetadataDTO(true));
@ -40,4 +60,53 @@ public class OrganizationBillingControllerTests
Assert.True(organizationMetadataResponse.IsOnSecretsManagerStandalone);
}
[Theory, BitAutoData]
public async Task GetHistoryAsync_Unauthorized_ReturnsUnauthorized(
Guid organizationId,
SutProvider<OrganizationBillingController> sutProvider)
{
sutProvider.GetDependency<ICurrentContext>().ViewBillingHistory(organizationId).Returns(false);
var result = await sutProvider.Sut.GetHistoryAsync(organizationId);
Assert.IsType<UnauthorizedHttpResult>(result);
}
[Theory, BitAutoData]
public async Task GetHistoryAsync_OrganizationNotFound_ReturnsNotFound(
Guid organizationId,
SutProvider<OrganizationBillingController> sutProvider)
{
sutProvider.GetDependency<ICurrentContext>().ViewBillingHistory(organizationId).Returns(true);
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organizationId).Returns((Organization)null);
var result = await sutProvider.Sut.GetHistoryAsync(organizationId);
Assert.IsType<NotFound>(result);
}
[Theory]
[BitAutoData]
public async Task GetHistoryAsync_OK(
Guid organizationId,
Organization organization,
SutProvider<OrganizationBillingController> sutProvider)
{
// Arrange
sutProvider.GetDependency<ICurrentContext>().ViewBillingHistory(organizationId).Returns(true);
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organizationId).Returns(organization);
// Manually create a BillingHistoryInfo object to avoid requiring AutoFixture to create HttpResponseHeaders
var billingInfo = new BillingHistoryInfo();
sutProvider.GetDependency<IPaymentService>().GetBillingHistoryAsync(organization).Returns(billingInfo);
// Act
var result = await sutProvider.Sut.GetHistoryAsync(organizationId);
// Assert
var okResult = Assert.IsType<Ok<BillingHistoryInfo>>(result);
Assert.Equal(billingInfo, okResult.Value);
}
}