1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 15:42:48 -05:00

[AC-2568] Added invoices and transaction history endpoints. Added cursor paging for each (#4692)

* Added invoices and transaction history endpoints. Added cursor paging for each

* Removed try/catch since it's handled by middleware. Updated condition to use pattern matching

* Added unit tests for PaymentHistoryService

* Removed organizationId from account billing controller endpoints
This commit is contained in:
Conner Turnbull
2024-09-09 09:38:58 -04:00
committed by GitHub
parent ebf8bc0b85
commit 46ac2a9b3b
16 changed files with 385 additions and 34 deletions

View File

@ -1,4 +1,5 @@
using Bit.Api.Billing.Models.Responses;
using Bit.Core.Billing.Services;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Authorization;
@ -10,7 +11,8 @@ namespace Bit.Api.Billing.Controllers;
[Authorize("Application")]
public class AccountsBillingController(
IPaymentService paymentService,
IUserService userService) : Controller
IUserService userService,
IPaymentHistoryService paymentHistoryService) : Controller
{
[HttpGet("history")]
[SelfHosted(NotSelfHostedOnly = true)]
@ -39,4 +41,38 @@ public class AccountsBillingController(
var billingInfo = await paymentService.GetBillingAsync(user);
return new BillingPaymentResponseModel(billingInfo);
}
[HttpGet("invoices")]
public async Task<IResult> GetInvoicesAsync([FromQuery] string startAfter = null)
{
var user = await userService.GetUserByPrincipalAsync(User);
if (user == null)
{
throw new UnauthorizedAccessException();
}
var invoices = await paymentHistoryService.GetInvoiceHistoryAsync(
user,
5,
startAfter);
return TypedResults.Ok(invoices);
}
[HttpGet("transactions")]
public async Task<IResult> GetTransactionsAsync([FromQuery] DateTime? startAfter = null)
{
var user = await userService.GetUserByPrincipalAsync(User);
if (user == null)
{
throw new UnauthorizedAccessException();
}
var transactions = await paymentHistoryService.GetTransactionHistoryAsync(
user,
5,
startAfter);
return TypedResults.Ok(transactions);
}
}

View File

@ -19,7 +19,8 @@ public class OrganizationBillingController(
IOrganizationBillingService organizationBillingService,
IOrganizationRepository organizationRepository,
IPaymentService paymentService,
ISubscriberService subscriberService) : BaseBillingController
ISubscriberService subscriberService,
IPaymentHistoryService paymentHistoryService) : BaseBillingController
{
[HttpGet("metadata")]
public async Task<IResult> GetMetadataAsync([FromRoute] Guid organizationId)
@ -61,6 +62,52 @@ public class OrganizationBillingController(
return TypedResults.Ok(billingInfo);
}
[HttpGet("invoices")]
public async Task<IResult> GetInvoicesAsync([FromRoute] Guid organizationId, [FromQuery] string startAfter = null)
{
if (!await currentContext.ViewBillingHistory(organizationId))
{
return TypedResults.Unauthorized();
}
var organization = await organizationRepository.GetByIdAsync(organizationId);
if (organization == null)
{
return TypedResults.NotFound();
}
var invoices = await paymentHistoryService.GetInvoiceHistoryAsync(
organization,
5,
startAfter);
return TypedResults.Ok(invoices);
}
[HttpGet("transactions")]
public async Task<IResult> GetTransactionsAsync([FromRoute] Guid organizationId, [FromQuery] DateTime? startAfter = null)
{
if (!await currentContext.ViewBillingHistory(organizationId))
{
return TypedResults.Unauthorized();
}
var organization = await organizationRepository.GetByIdAsync(organizationId);
if (organization == null)
{
return TypedResults.NotFound();
}
var transactions = await paymentHistoryService.GetTransactionHistoryAsync(
organization,
5,
startAfter);
return TypedResults.Ok(transactions);
}
[HttpGet]
[SelfHosted(NotSelfHostedOnly = true)]
public async Task<IResult> GetBillingAsync(Guid organizationId)