diff --git a/services/web/app/src/Features/Subscription/SubscriptionController.mjs b/services/web/app/src/Features/Subscription/SubscriptionController.mjs
index b8d15c305d..9e0009585f 100644
--- a/services/web/app/src/Features/Subscription/SubscriptionController.mjs
+++ b/services/web/app/src/Features/Subscription/SubscriptionController.mjs
@@ -337,6 +337,7 @@ async function userSubscriptionPage(req, res) {
groupSettingsAdvertisedFor,
groupSettingsEnabledFor,
isManagedAccount: !!req.managedBy,
+ isManagedGroupAdmin: !!req.isManagedGroupAdmin,
userRestrictions: Array.from(req.userRestrictions || []),
hasAiAssistViaWritefull,
aiAssistViaWritefullSource,
diff --git a/services/web/app/views/subscriptions/dashboard-react.pug b/services/web/app/views/subscriptions/dashboard-react.pug
index 12ab2d272c..0348a1cc55 100644
--- a/services/web/app/views/subscriptions/dashboard-react.pug
+++ b/services/web/app/views/subscriptions/dashboard-react.pug
@@ -84,6 +84,11 @@ block append meta
data-type='string'
content=aiAssistViaWritefullSource
)
+ meta(
+ name='ol-isManagedGroupAdmin'
+ data-type='boolean'
+ content=isManagedGroupAdmin
+ )
meta(name='ol-user' data-type='json' content=user)
if personalSubscription && personalSubscription.payment
meta(name='ol-recurlyApiKey' content=settings.apis.recurly.publicKey)
diff --git a/services/web/frontend/js/features/subscription/components/dashboard/reactivate-subscription.tsx b/services/web/frontend/js/features/subscription/components/dashboard/reactivate-subscription.tsx
index 26416731b5..6717f843dd 100644
--- a/services/web/frontend/js/features/subscription/components/dashboard/reactivate-subscription.tsx
+++ b/services/web/frontend/js/features/subscription/components/dashboard/reactivate-subscription.tsx
@@ -20,8 +20,12 @@ function ReactivateSubscription() {
location.reload()
}
- // Don't show the button to reactivate the subscription for managed users
- if (getMeta('ol-cannot-reactivate-subscription')) {
+ // Don't show the button to reactivate the subscription for managed users,
+ // unless they are a managed group admin (who should be able to reactivate their own subscription)
+ if (
+ getMeta('ol-cannot-reactivate-subscription') &&
+ !getMeta('ol-isManagedGroupAdmin')
+ ) {
return null
}
diff --git a/services/web/frontend/js/utils/meta.ts b/services/web/frontend/js/utils/meta.ts
index d4462a3bc0..86d32af02a 100644
--- a/services/web/frontend/js/utils/meta.ts
+++ b/services/web/frontend/js/utils/meta.ts
@@ -185,6 +185,7 @@ export interface Meta {
'ol-isCollectionMethodManual': boolean
'ol-isExternalAuthenticationSystemUsed': boolean
'ol-isManagedAccount': boolean
+ 'ol-isManagedGroupAdmin': boolean
'ol-isProfessional': boolean
'ol-isRegisteredViaGoogle': boolean
'ol-isRestrictedTokenMember': boolean
diff --git a/services/web/test/frontend/features/subscription/components/dashboard/personal-subscription.test.tsx b/services/web/test/frontend/features/subscription/components/dashboard/personal-subscription.test.tsx
index a61c9fca7f..37e2861ec8 100644
--- a/services/web/test/frontend/features/subscription/components/dashboard/personal-subscription.test.tsx
+++ b/services/web/test/frontend/features/subscription/components/dashboard/personal-subscription.test.tsx
@@ -115,6 +115,45 @@ describe('', function () {
fetchMock.removeRoutes().clearHistory()
})
+ it('hides reactivate button for managed users who cannot reactivate', function () {
+ renderWithSubscriptionDashContext(, {
+ metaTags: [
+ { name: 'ol-subscription', value: canceledSubscription },
+ { name: 'ol-cannot-reactivate-subscription', value: true },
+ ],
+ })
+
+ screen.getByText(
+ 'Your subscription has been canceled and will terminate on',
+ { exact: false }
+ )
+ screen.getByRole('link', { name: 'View your invoices' })
+
+ // Should not show the reactivate button
+ expect(
+ screen.queryByRole('button', { name: 'Reactivate your subscription' })
+ ).to.be.null
+ })
+
+ it('shows reactivate button for managed group admins even if they have reactivate restriction', function () {
+ renderWithSubscriptionDashContext(, {
+ metaTags: [
+ { name: 'ol-subscription', value: canceledSubscription },
+ { name: 'ol-cannot-reactivate-subscription', value: true },
+ { name: 'ol-isManagedGroupAdmin', value: true },
+ ],
+ })
+
+ screen.getByText(
+ 'Your subscription has been canceled and will terminate on',
+ { exact: false }
+ )
+ screen.getByRole('link', { name: 'View your invoices' })
+
+ // Should show the reactivate button for group admins
+ screen.getByRole('button', { name: 'Reactivate your subscription' })
+ })
+
it('renders the expired dash', function () {
renderWithSubscriptionDashContext(, {
metaTags: [
diff --git a/services/web/test/unit/src/Subscription/SubscriptionController.test.mjs b/services/web/test/unit/src/Subscription/SubscriptionController.test.mjs
index 1d150dd56c..1abd80a383 100644
--- a/services/web/test/unit/src/Subscription/SubscriptionController.test.mjs
+++ b/services/web/test/unit/src/Subscription/SubscriptionController.test.mjs
@@ -492,6 +492,32 @@ describe('SubscriptionController', function () {
expect(ctx.data.groupSettingsEnabledFor).to.deep.equal([])
})
+ it('should pass isManagedGroupAdmin as false when not set', function (ctx) {
+ expect(ctx.data.isManagedGroupAdmin).to.equal(false)
+ })
+
+ describe('when user is a managed group admin', function () {
+ beforeEach(async function (ctx) {
+ ctx.req.isManagedGroupAdmin = true
+ await new Promise((resolve, reject) => {
+ ctx.res.render = (view, data) => {
+ ctx.data = data
+ expect(view).to.equal('subscriptions/dashboard-react')
+ resolve()
+ }
+ ctx.SubscriptionController.userSubscriptionPage(
+ ctx.req,
+ ctx.res,
+ ctx.rejectOnError(reject)
+ )
+ })
+ })
+
+ it('should pass isManagedGroupAdmin as true', function (ctx) {
+ expect(ctx.data.isManagedGroupAdmin).to.equal(true)
+ })
+ })
+
describe('when errorCode query param is present', function () {
beforeEach(async function (ctx) {
ctx.req.query.errorCode = 'payment_failed'