Skip to content

[PM-32477]PremiumStatusChanged Push Notification#7198

Merged
cyprain-okeke merged 12 commits intomainfrom
billing/pm-32477/premiumStatusChanged-push-notification
Mar 19, 2026
Merged

[PM-32477]PremiumStatusChanged Push Notification#7198
cyprain-okeke merged 12 commits intomainfrom
billing/pm-32477/premiumStatusChanged-push-notification

Conversation

@cyprain-okeke
Copy link
Contributor

🎟️ Tracking

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

📔 Objective

Summary
Implement premium-status push notifications across billing flows so clients stay in sync whenever a user’s premium state changes.

Details

New adapter API for premium changes

  • Extend IPushNotificationAdapter with NotifyPremiumStatusChangedAsync(User user).
  • Implement in PushNotificationAdapter by delegating to IPushNotificationService.PushPremiumStatusChangedAsync(user).

Stripe payment and subscription handlers

  • PaymentSucceededHandler
    • Inject IUserRepository.
    • After EnablePremiumAsync(userId, subscription.GetCurrentPeriodEnd()), load the user and call NotifyPremiumStatusChangedAsync(user) so successful payments trigger a premium-status push.

SubscriptionDeletedHandler

  • Inject IUserRepository and IPushNotificationAdapter.
  • When a user subscription is deleted (userId present), call DisablePremiumAsync and then fetch the user and send NotifyPremiumStatusChangedAsync(user).

SubscriptionUpdatedHandler

  • Inject IUserRepository and IPushNotificationAdapter.
  • In DisableSubscriberAsync user branch: disable premium, fetch the user, then call NotifyPremiumStatusChangedAsync(user).
  • In EnableSubscriberAsync user branch: enable premium, fetch the user, then call NotifyPremiumStatusChangedAsync(user).

Premium subscription commands

  • CreatePremiumCloudHostedSubscriptionCommand

    • After saving the user and PushSyncVaultAsync(user.Id), call PushPremiumStatusChangedAsync(user) so new/updated cloud subscriptions immediately push the status change.
  • CreatePremiumSelfHostedSubscriptionCommand

  • After writing the license and saving the user, call PushPremiumStatusChangedAsync(user) to broadcast the new premium status for self-hosted subscriptions.

  • UpgradePremiumToOrganizationCommand

    • Inject IPushNotificationService.
    • After downgrading the user’s personal premium while upgrading to an organization, call PushPremiumStatusChangedAsync(user) so clients see the user’s premium flag change.

Tests

  • Update billing service tests to:

    • Use IUserRepository to return a User instance when subscriptions are enabled/disabled.
    • Assert IPushNotificationAdapter.NotifyPremiumStatusChangedAsync(user) is called in subscription deleted/updated scenarios.
  • Update premium command tests to:

    • Assert IPushNotificationService.PushPremiumStatusChangedAsync is called with a User whose Premium flag matches the expected post-command state (true for new subscriptions, false when upgrading to an organization).

📸 Screenshots

@github-actions
Copy link
Contributor

github-actions bot commented Mar 11, 2026

Logo
Checkmarx One – Scan Summary & Detailsd5c17320-44e4-4e07-b2d9-73ef41e3ea71


New Issues (2) Checkmarx found the following issues in this Pull Request
# Severity Issue Source File / Package Checkmarx Insight
1 MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1592
detailsMethod at line 1592 of /src/Api/Vault/Controllers/CiphersController.cs gets a parameter from a user request from id. This parameter value flows ...
Attack Vector
2 MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1419
detailsMethod at line 1419 of /src/Api/Vault/Controllers/CiphersController.cs gets a parameter from a user request from id. This parameter value flows ...
Attack Vector

Fixed Issues (1) Great job! The following issues were fixed in this Pull Request
Severity Issue Source File / Package
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 293

@codecov
Copy link

codecov bot commented Mar 11, 2026

Codecov Report

❌ Patch coverage is 61.36364% with 34 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.69%. Comparing base (2efacd5) to head (93c8e4c).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...ervices/Implementations/PushNotificationAdapter.cs 0.00% 12 Missing ⚠️
...lling/Services/Implementations/LicensingService.cs 20.00% 12 Missing ⚠️
...ervices/Implementations/PaymentSucceededHandler.cs 0.00% 7 Missing ⚠️
src/Notifications/HubHelpers.cs 66.66% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7198   +/-   ##
=======================================
  Coverage   57.69%   57.69%           
=======================================
  Files        2035     2036    +1     
  Lines       89672    89755   +83     
  Branches     7993     7997    +4     
=======================================
+ Hits        51738    51788   +50     
- Misses      36074    36106   +32     
- Partials     1860     1861    +1     

☔ View full report in Codecov by Sentry.
📢 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.

public Guid TargetOrganizationUserId { get; set; }
}

public class PremiumStatusPushNotification
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ Please review the comments on lines 7 and 8 of this file regarding the location this file should live in.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cyprain-okeke This still needs to be addressed - the location of the file should be owned to a location we own per the comments at the top of the file.

Copy link
Contributor

@djsmith85 djsmith85 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like after the comments from @amorask-bitwarden are addressed, a review from platform might not be necessary anymore. In case they do, please re-request a review.

@cyprain-okeke cyprain-okeke requested review from amorask-bitwarden and djsmith85 and removed request for djsmith85 March 12, 2026 12:22
Copy link
Contributor

@amorask-bitwarden amorask-bitwarden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for resolving the feedback - just one thing was missed and then we're good to go.

public Guid TargetOrganizationUserId { get; set; }
}

public class PremiumStatusPushNotification
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cyprain-okeke This still needs to be addressed - the location of the file should be owned to a location we own per the comments at the top of the file.

@sonarqubecloud
Copy link

@cyprain-okeke cyprain-okeke merged commit 768de5f into main Mar 19, 2026
43 checks passed
@cyprain-okeke cyprain-okeke deleted the billing/pm-32477/premiumStatusChanged-push-notification branch March 19, 2026 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants