1
0
mirror of https://github.com/bitwarden/server synced 2026-01-07 19:13:50 +00:00

[PM-21638] Stripe .NET v48 (#6202)

* Upgrade Stripe.net to v48.4.0

* Update PreviewTaxAmountCommand

* Remove unused UpcomingInvoiceOptionExtensions

* Added SubscriptionExtensions with GetCurrentPeriodEnd

* Update PremiumUserBillingService

* Update OrganizationBillingService

* Update GetOrganizationWarningsQuery

* Update BillingHistoryInfo

* Update SubscriptionInfo

* Remove unused Sql Billing folder

* Update StripeAdapter

* Update StripePaymentService

* Update InvoiceCreatedHandler

* Update PaymentFailedHandler

* Update PaymentSucceededHandler

* Update ProviderEventService

* Update StripeEventUtilityService

* Update SubscriptionDeletedHandler

* Update SubscriptionUpdatedHandler

* Update UpcomingInvoiceHandler

* Update ProviderSubscriptionResponse

* Remove unused Stripe Subscriptions Admin Tool

* Update RemoveOrganizationFromProviderCommand

* Update ProviderBillingService

* Update RemoveOrganizatinoFromProviderCommandTests

* Update PreviewTaxAmountCommandTests

* Update GetCloudOrganizationLicenseQueryTests

* Update GetOrganizationWarningsQueryTests

* Update StripePaymentServiceTests

* Update ProviderBillingControllerTests

* Update ProviderEventServiceTests

* Update SubscriptionDeletedHandlerTests

* Update SubscriptionUpdatedHandlerTests

* Resolve Billing test failures

I completely removed tests for the StripeEventService as they were using a system I setup a while back that read JSON files of the Stripe event structure. I did not anticipate how frequently these structures would change with each API version and the cost of trying to update these specific JSON files to test a very static data retrieval service far outweigh the benefit.

* Resolve Core test failures

* Run dotnet format

* Remove unused provider migration

* Fixed failing tests

* Run dotnet format

* Replace the old webhook secret key with new one (#6223)

* Fix compilation failures in additions

* Run dotnet format

* Bump Stripe API version

* Fix recent addition: CreatePremiumCloudHostedSubscriptionCommand

* Fix new code in main according to Stripe update

* Fix InvoiceExtensions

* Bump SDK version to match API Version

* Fix provider invoice generation validation

* More QA fixes

* Fix tests

* QA defect resolutions

* QA defect resolutions

* Run dotnet format

* Fix tests

---------

Co-authored-by: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com>
This commit is contained in:
Alex Morask
2025-10-21 14:07:55 -05:00
committed by GitHub
parent 6324f692b8
commit 9c51c9971b
81 changed files with 1273 additions and 3959 deletions

View File

@@ -1,83 +0,0 @@
using Bit.Admin.Billing.Models;
using Bit.Admin.Enums;
using Bit.Admin.Utilities;
using Bit.Core.Billing.Providers.Migration.Models;
using Bit.Core.Billing.Providers.Migration.Services;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Bit.Admin.Billing.Controllers;
[Authorize]
[Route("migrate-providers")]
[SelfHosted(NotSelfHostedOnly = true)]
public class MigrateProvidersController(
IProviderMigrator providerMigrator) : Controller
{
[HttpGet]
[RequirePermission(Permission.Tools_MigrateProviders)]
public IActionResult Index()
{
return View(new MigrateProvidersRequestModel());
}
[HttpPost]
[RequirePermission(Permission.Tools_MigrateProviders)]
[ValidateAntiForgeryToken]
public async Task<IActionResult> PostAsync(MigrateProvidersRequestModel request)
{
var providerIds = GetProviderIdsFromInput(request.ProviderIds);
if (providerIds.Count == 0)
{
return RedirectToAction("Index");
}
foreach (var providerId in providerIds)
{
await providerMigrator.Migrate(providerId);
}
return RedirectToAction("Results", new { ProviderIds = string.Join("\r\n", providerIds) });
}
[HttpGet("results")]
[RequirePermission(Permission.Tools_MigrateProviders)]
public async Task<IActionResult> ResultsAsync(MigrateProvidersRequestModel request)
{
var providerIds = GetProviderIdsFromInput(request.ProviderIds);
if (providerIds.Count == 0)
{
return View(Array.Empty<ProviderMigrationResult>());
}
var results = await Task.WhenAll(providerIds.Select(providerMigrator.GetResult));
return View(results);
}
[HttpGet("results/{providerId:guid}")]
[RequirePermission(Permission.Tools_MigrateProviders)]
public async Task<IActionResult> DetailsAsync([FromRoute] Guid providerId)
{
var result = await providerMigrator.GetResult(providerId);
if (result == null)
{
return RedirectToAction("Index");
}
return View(result);
}
private static List<Guid> GetProviderIdsFromInput(string text) => !string.IsNullOrEmpty(text)
? text.Split(
["\r\n", "\r", "\n"],
StringSplitOptions.TrimEntries
)
.Select(id => new Guid(id))
.ToList()
: [];
}

View File

@@ -1,13 +0,0 @@
// FIXME: Update this file to be null safe and then delete the line below
#nullable disable
using System.ComponentModel.DataAnnotations;
namespace Bit.Admin.Billing.Models;
public class MigrateProvidersRequestModel
{
[Required]
[Display(Name = "Provider IDs")]
public string ProviderIds { get; set; }
}

View File

@@ -1,39 +0,0 @@
@using System.Text.Json
@model Bit.Core.Billing.Providers.Migration.Models.ProviderMigrationResult
@{
ViewData["Title"] = "Results";
}
<h1>Migrate Providers</h1>
<h2>Migration Details: @Model.ProviderName</h2>
<dl class="row">
<dt class="col-sm-4 col-lg-3">Id</dt>
<dd class="col-sm-8 col-lg-9"><code>@Model.ProviderId</code></dd>
<dt class="col-sm-4 col-lg-3">Result</dt>
<dd class="col-sm-8 col-lg-9">@Model.Result</dd>
</dl>
<h3>Client Organizations</h3>
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Result</th>
<th>Previous State</th>
</tr>
</thead>
<tbody>
@foreach (var clientResult in Model.Clients)
{
<tr>
<td>@clientResult.OrganizationId</td>
<td>@clientResult.OrganizationName</td>
<td>@clientResult.Result</td>
<td><pre>@Html.Raw(JsonSerializer.Serialize(clientResult.PreviousState))</pre></td>
</tr>
}
</tbody>
</table>
</div>

View File

@@ -1,46 +0,0 @@
@model Bit.Admin.Billing.Models.MigrateProvidersRequestModel;
@{
ViewData["Title"] = "Migrate Providers";
}
<h1>Migrate Providers</h1>
<h2>Bulk Consolidated Billing Migration Tool</h2>
<section>
<p>
This tool allows you to provide a list of IDs for Providers that you would like to migrate to Consolidated Billing.
Because of the expensive nature of the operation, you can only migrate 10 Providers at a time.
</p>
<p class="alert alert-warning">
Updates made through this tool are irreversible without manual intervention.
</p>
<p>Example Input (Please enter each Provider ID separated by a new line):</p>
<div class="card">
<div class="card-body">
<pre class="mb-0">f513affc-2290-4336-879e-21ec3ecf3e78
f7a5cb0d-4b74-445c-8d8c-232d1d32bbe2
bf82d3cf-0e21-4f39-b81b-ef52b2fc6a3a
174e82fc-70c3-448d-9fe7-00bad2a3ab00
22a4bbbf-58e3-4e4c-a86a-a0d7caf4ff14</pre>
</div>
</div>
<form method="post" asp-controller="MigrateProviders" asp-action="Post" class="mt-2">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="mb-3">
<label class="form-label" asp-for="ProviderIds"></label>
<textarea rows="10" class="form-control" type="text" asp-for="ProviderIds"></textarea>
</div>
<div class="mb-3">
<input type="submit" value="Run" class="btn btn-primary"/>
</div>
</form>
<form method="get" asp-controller="MigrateProviders" asp-action="Results" class="mt-2">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="mb-3">
<label class="form-label" asp-for="ProviderIds"></label>
<textarea rows="10" class="form-control" type="text" asp-for="ProviderIds"></textarea>
</div>
<div class="mb-3">
<input type="submit" value="See Previous Results" class="btn btn-primary"/>
</div>
</form>
</section>

View File

@@ -1,28 +0,0 @@
@model Bit.Core.Billing.Providers.Migration.Models.ProviderMigrationResult[]
@{
ViewData["Title"] = "Results";
}
<h1>Migrate Providers</h1>
<h2>Results</h2>
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Result</th>
</tr>
</thead>
<tbody>
@foreach (var result in Model)
{
<tr>
<td><a href="@Url.Action("Details", "MigrateProviders", new { providerId = result.ProviderId })">@result.ProviderId</a></td>
<td>@result.ProviderName</td>
<td>@result.Result</td>
</tr>
}
</tbody>
</table>
</div>