Skip to content

[PM-38874] fix: Keep Admin org page accessible when Stripe customer is deleted#7913

Open
kdenney wants to merge 8 commits into
mainfrom
billing/PM-38874/admin-org-invalid-customerid
Open

[PM-38874] fix: Keep Admin org page accessible when Stripe customer is deleted#7913
kdenney wants to merge 8 commits into
mainfrom
billing/PM-38874/admin-org-invalid-customerid

Conversation

@kdenney

@kdenney kdenney commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-38874

📔 Objective

Loading the edit page for an organization in the Admin portal calls GetBillingAsync and GetBillingHistoryAsync, both of which hit Stripe to fetch the customer. When an organization's Stripe customer has been deleted, these calls throw and the entire Edit page fails to render, leaving an admin with no way to reach the org and correct its Gateway Customer ID.

The Edit page now loads even when billing info cannot be retrieved. GetBillingAsync / GetBillingHistoryAsync are wrapped in a try/catch that resets both values to null on failure, and the Billing Information section is hidden when either is null. Two failure cases are distinguished:

  • A Stripe resource_missing error (the customer no longer exists) sets a TempData["Warning"] message telling the admin they can set a valid Gateway Customer ID.
  • Any other billing-load failure sets a TempData["Error"] message suggesting a reload and contacting support.

Note: The Admin layout previously rendered TempData["Error"] and TempData["Success"] toasts but not TempData["Warning"]. This adds a toastr.warning block so the new warning surfaces. As a side effect, warning messages that were already being set on the organization, provider, and user edit pages (all of the "updated successfully, but a follow-up Stripe/email step failed" variety) were previously set but never displayed, and now appear as warning toasts. These only fire when the corresponding secondary operation fails; normal saves are unaffected.

Unit tests cover the missing-customer path (both when the initial billing call fails and when the history call fails after billing succeeds) and the generic-error path.

📸 Screenshots

image

kdenney added 5 commits July 1, 2026 11:48
…-38874)

When GetBillingAsync succeeded but GetBillingHistoryAsync threw, the catch
left BillingInfo non-null while BillingHistoryInfo stayed null. The view
guard only checked BillingInfo, so _BillingInformation still rendered and
dereferenced BillingHistoryInfo, throwing an NRE and returning a 500, the
exact failure this fix set out to prevent.

Reset both billing values in the catch so billing loads as a unit, and add
BillingHistoryInfo to the view conditional as defense-in-depth. Add a test
covering the GetBillingHistoryAsync-throws path.
@kdenney kdenney requested review from a team and cyprain-okeke and removed request for a team July 1, 2026 17:58
@kdenney kdenney added the ai-review Request a Claude code review label Jul 1, 2026
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

Reviewed a bugfix that keeps the Admin org Edit page accessible when an organization's Stripe customer has been deleted. The billing loads are wrapped in a try/catch that resets both billingInfo and billingHistoryInfo to null, the view guards on both being non-null, and a new toastr.warning block surfaces the warning message. Unit tests cover the missing-customer path (on both the billing and history calls) and the generic-error path.

Code Review Details

No blocking findings.

Notes from analysis:

  • The new TempData["Warning"] toast renders a constant, server-controlled string through Razor HTML-encoding, matching the existing Error/Success toast pattern in _Layout.cshtml. No user-controlled input reaches the <script> block, so no XSS concern.
  • The catch blocks reset both billingInfo and billingHistoryInfo; the view (Edit.cshtml:102) guards on both being non-null before rendering _BillingInformation, which are the only view references. No NRE risk.
  • The generic catch (Exception) fallback was previously flagged by an automated tool, resolved, and is documented as intentional in the PR description; the try block scope is narrow (only the two billing calls) and logs with the exception preserved.
  • The side effect of previously-set-but-never-displayed warning toasts now surfacing on org/provider/user edit pages is intentional and documented; those are all constant strings.

Comment thread src/Admin/AdminConsole/Controllers/OrganizationsController.cs Dismissed
@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.50000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.37%. Comparing base (e899a9c) to head (2ebe54a).

Files with missing lines Patch % Lines
src/Admin/Views/Shared/_Layout.cshtml 0.00% 3 Missing ⚠️
...Admin/AdminConsole/Views/Organizations/Edit.cshtml 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7913      +/-   ##
==========================================
+ Coverage   61.35%   61.37%   +0.01%     
==========================================
  Files        2236     2236              
  Lines       98547    98576      +29     
  Branches     8911     8912       +1     
==========================================
+ Hits        60468    60501      +33     
+ Misses      35943    35939       -4     
  Partials     2136     2136              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@kdenney kdenney added the t:bugfix Change Type - Bugfix label Jul 1, 2026
@kdenney kdenney marked this pull request as ready for review July 1, 2026 22:42
@kdenney kdenney requested a review from a team as a code owner July 1, 2026 22:42
@kdenney kdenney requested a review from JaredScar July 1, 2026 22:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Request a Claude code review t:bugfix Change Type - Bugfix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants