Kaynağa Gözat

Add permissions checks for AI assist addon purchase (#26355)

* Add permissions checks for AI assist when trying to buy the addon

* more explicit check for DuplicateAddOnError

* remove useCapabilities()

GitOrigin-RevId: 1979e27410981e2ef020cecc731e228483d3315a
Domagoj Kriskovic 1 yıl önce
ebeveyn
işleme
ce00213c4a

+ 13 - 1
services/web/app/src/Features/Subscription/SubscriptionController.js

@@ -32,6 +32,7 @@ const PlansLocator = require('./PlansLocator')
 const PaymentProviderEntities = require('./PaymentProviderEntities')
 const { User } = require('../../models/User')
 const UserGetter = require('../User/UserGetter')
+const PermissionsManager = require('../Authorization/PermissionsManager')
 
 /**
  * @import { SubscriptionChangeDescription } from '../../../../types/subscription/subscription-change-preview'
@@ -336,7 +337,8 @@ function cancelV1Subscription(req, res, next) {
 }
 
 async function previewAddonPurchase(req, res) {
-  const userId = SessionManager.getLoggedInUserId(req.session)
+  const user = SessionManager.getSessionUser(req.session)
+  const userId = user._id
   const addOnCode = req.params.addOnCode
   const purchaseReferrer = req.query.purchaseReferrer
 
@@ -344,6 +346,16 @@ async function previewAddonPurchase(req, res) {
     return HttpErrorHandler.notFound(req, res, `Unknown add-on: ${addOnCode}`)
   }
 
+  const canUseAi = await PermissionsManager.promises.checkUserPermissions(
+    user,
+    ['use-ai']
+  )
+  if (!canUseAi) {
+    return res.redirect(
+      '/user/subscription?redirect-reason=ai-assist-unavailable'
+    )
+  }
+
   /** @type {PaymentMethod[]} */
   const paymentMethod = await Modules.promises.hooks.fire(
     'getPaymentMethod',

+ 1 - 0
services/web/frontend/extracted-translations.json

@@ -109,6 +109,7 @@
   "agree_with_the_terms": "",
   "ai_assist_in_overleaf_is_included_via_writefull_groups": "",
   "ai_assist_in_overleaf_is_included_via_writefull_individual": "",
+  "ai_assist_unavailable_due_to_subscription_type": "",
   "ai_assistance_to_help_you": "",
   "ai_based_language_tools": "",
   "ai_can_make_mistakes": "",

+ 0 - 2
services/web/frontend/js/features/subscription/components/dashboard/free-plan.tsx

@@ -1,6 +1,5 @@
 import { useTranslation, Trans } from 'react-i18next'
 import WritefullManagedBundleAddOn from '@/features/subscription/components/dashboard/states/active/change-plan/modals/writefull-bundle-management-modal'
-import RedirectAlerts from './redirect-alerts'
 import getMeta from '@/utils/meta'
 
 function FreePlan() {
@@ -9,7 +8,6 @@ function FreePlan() {
 
   return (
     <>
-      <RedirectAlerts />
       <Trans
         i18nKey="on_free_plan_upgrade_to_access_features"
         components={[

+ 0 - 2
services/web/frontend/js/features/subscription/components/dashboard/personal-subscription.tsx

@@ -7,7 +7,6 @@ import { ExpiredSubscription } from './states/expired'
 import { useSubscriptionDashboardContext } from '../../context/subscription-dashboard-context'
 import PersonalSubscriptionSyncEmail from './personal-subscription-sync-email'
 import OLNotification from '@/features/ui/components/ol/ol-notification'
-import RedirectAlerts from './redirect-alerts'
 
 function PastDueSubscriptionAlert({
   subscription,
@@ -76,7 +75,6 @@ function PersonalSubscription() {
 
   return (
     <>
-      <RedirectAlerts />
       {personalSubscription.payment.hasPastDueInvoice && (
         <PastDueSubscriptionAlert subscription={personalSubscription} />
       )}

+ 2 - 0
services/web/frontend/js/features/subscription/components/dashboard/redirect-alerts.tsx

@@ -15,6 +15,8 @@ export function RedirectAlerts() {
     warning = t('good_news_you_are_already_receiving_this_add_on_via_writefull')
   } else if (redirectReason === 'double-buy') {
     warning = t('good_news_you_already_purchased_this_add_on')
+  } else if (redirectReason === 'ai-assist-unavailable') {
+    warning = t('ai_assist_unavailable_due_to_subscription_type')
   } else {
     return null
   }

+ 2 - 0
services/web/frontend/js/features/subscription/components/dashboard/subscription-dashboard.tsx

@@ -15,6 +15,7 @@ import OLRow from '@/features/ui/components/ol/ol-row'
 import OLCol from '@/features/ui/components/ol/ol-col'
 import OLNotification from '@/features/ui/components/ol/ol-notification'
 import WritefullManagedBundleAddOn from './states/active/change-plan/modals/writefull-bundle-management-modal'
+import RedirectAlerts from './redirect-alerts'
 
 function SubscriptionDashboard() {
   const { t } = useTranslation()
@@ -40,6 +41,7 @@ function SubscriptionDashboard() {
               type="warning"
             />
           )}
+          <RedirectAlerts />
           <OLPageContentCard>
             <div className="page-header">
               <h1>{t('your_subscription')}</h1>

+ 1 - 0
services/web/locales/en.json

@@ -130,6 +130,7 @@
   "agree_with_the_terms": "I agree with the Overleaf terms",
   "ai_assist_in_overleaf_is_included_via_writefull_groups": "AI Assist in Overleaf is included as part of your group or organization’s Writefull subscription. To make changes you’ll need to speak to your subscription admin",
   "ai_assist_in_overleaf_is_included_via_writefull_individual": "AI Assist in Overleaf is included as part of your Writefull subscription. You can cancel or manage your access to AI Assist in your Writefull subscription settings.",
+  "ai_assist_unavailable_due_to_subscription_type": "We’re sorry—it looks like AI Assist isn’t available to you just yet due to your current subscription type.",
   "ai_assistance_to_help_you": "AI assistance to help you fix LaTeX errors",
   "ai_based_language_tools": "AI-based language tools tailored to research writing",
   "ai_can_make_mistakes": "AI can make mistakes. Review fixes before you apply them.",