From afa6421809a9d208fb3120e7ef54386378a0f621 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 24 Jul 2026 14:47:58 +0530 Subject: [PATCH] feat: allow suspended accounts to access billing (#15153) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Administrators of suspended accounts can now reach the billing page to settle payment and restore their account, instead of being fully locked out on the suspended screen. The suspended screen shows a subtle **Manage billing** link below the contact support button (admins on Cloud only). Agents remain restricted to the suspended screen. ## How to test 1. On Cloud, suspend an account from Super Admin. 2. Log in as an administrator of that account — you land on the suspended screen with a "Manage billing" link below contact support. 3. Click it — the billing settings page opens; subscription, Stripe portal, and top-ups all work. 4. Log in as an agent — no billing link, and navigating to `/settings/billing` manually redirects back to the suspended screen. ## What changed - Router guard allows `billing_settings_index` for administrators when the account is not active. - Suspended screen gets a billing link gated by admin role and Cloud installation. CleanShot 2026-07-24 at 12 25
56@2x --------- Co-authored-by: Muhsin Keloth --- .../dashboard/helper/routeHelpers.js | 10 +++++++-- .../dashboard/i18n/locale/en/settings.json | 3 ++- .../routes/dashboard/suspended/Index.vue | 21 +++++++++++++++++-- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/app/javascript/dashboard/helper/routeHelpers.js b/app/javascript/dashboard/helper/routeHelpers.js index 292e5e6e1..2f18132b5 100644 --- a/app/javascript/dashboard/helper/routeHelpers.js +++ b/app/javascript/dashboard/helper/routeHelpers.js @@ -67,8 +67,14 @@ export const validateLoggedInRoutes = (to, user) => { return validateActiveAccountRoutes(to, user); } - // If the current account is not active, then redirect the user to the suspended screen - if (to.name !== 'account_suspended') { + // If the current account is not active, only the suspended screen is + // reachable; administrators can also access billing to restore the account + const userPermissions = getUserPermissions(user, to.params.accountId); + const accessibleRoutes = userPermissions.includes('administrator') + ? ['account_suspended', 'billing_settings_index'] + : ['account_suspended']; + + if (!accessibleRoutes.includes(to.name)) { return `accounts/${to.params.accountId}/suspended`; } diff --git a/app/javascript/dashboard/i18n/locale/en/settings.json b/app/javascript/dashboard/i18n/locale/en/settings.json index 5852b5769..b133ca590 100644 --- a/app/javascript/dashboard/i18n/locale/en/settings.json +++ b/app/javascript/dashboard/i18n/locale/en/settings.json @@ -264,7 +264,8 @@ "EMAIL_VERIFICATION_SENT": "Verification email has been sent. Please check your inbox.", "ACCOUNT_SUSPENDED": { "TITLE": "Account Suspended", - "MESSAGE": "Your account has been suspended due to activity that may violate our policies. If you believe this is a mistake, please contact our support team." + "MESSAGE": "Your account has been suspended due to activity that may violate our policies. If you believe this is a mistake, please contact our support team.", + "MANAGE_BILLING": "Manage billing" }, "NO_ACCOUNTS": { "TITLE": "No account found", diff --git a/app/javascript/dashboard/routes/dashboard/suspended/Index.vue b/app/javascript/dashboard/routes/dashboard/suspended/Index.vue index 027f75ff5..bc7a2fa06 100644 --- a/app/javascript/dashboard/routes/dashboard/suspended/Index.vue +++ b/app/javascript/dashboard/routes/dashboard/suspended/Index.vue @@ -1,7 +1,16 @@