Explorar el Código

Migrate user.writefull.enabled -> user.writefull.promotionSet (#31475)

* feat: migrate from aiErrorAssist naming for disabling AI features to aiFeatures.enabled to avoid confusion

feat: keep aiErrorAssistant as setting on user object until migration is run

* feat: migrate writefull.enabled unset to instead use promotionSet false

* Update tools/migrations/20260213102825_swap_writefull_enabled_for_initialized.mjs

Co-authored-by: Mathias Jakobsen <mathias.jakobsen@overleaf.com>

* feat: addind backfill of ai features as a migration as well to help with dev environment setup

---------

Co-authored-by: Mathias Jakobsen <mathias.jakobsen@overleaf.com>
GitOrigin-RevId: fd3f0fc07c91678cd7fd1e0d5237221694b3027b
Jimmy Domagala-Tang hace 5 meses
padre
commit
97c4c550d7

+ 12 - 2
services/web/app/src/Features/Project/ProjectController.mjs

@@ -1266,18 +1266,28 @@ const _ProjectController = {
     if (shouldAutoCreateAccount) {
       await UserUpdater.promises.updateUser(userId, {
         $set: {
-          writefull: { enabled: true, autoCreatedAccount: true },
+          writefull: {
+            enabled: true,
+            initialized: true,
+            autoCreatedAccount: true,
+          },
         },
       })
       user.writefull.enabled = true
+      user.writefull.initialized = true
       user.writefull.autoCreatedAccount = true
     } else if (shouldAutoLoad) {
       await UserUpdater.promises.updateUser(userId, {
         $set: {
-          writefull: { enabled: true, autoCreatedAccount: false },
+          writefull: {
+            enabled: true,
+            initialized: true,
+            autoCreatedAccount: false,
+          },
         },
       })
       user.writefull.enabled = true
+      user.writefull.initialized = true
       user.writefull.autoCreatedAccount = false
     }
   },

+ 2 - 0
services/web/app/src/models/User.mjs

@@ -194,6 +194,8 @@ export const UserSchema = new Schema(
     },
     writefull: {
       enabled: { type: Boolean, default: null },
+      // whether we have attached an autocreated account or autoloading for the user
+      initialized: { type: Boolean, default: false },
       autoCreatedAccount: { type: Boolean, default: false },
       isPremium: { type: Boolean, default: false },
       premiumSource: { type: String, default: null },

+ 30 - 0
services/web/scripts/writefull/migrate_to_promotion_set.mjs

@@ -0,0 +1,30 @@
+import { db } from '../../app/src/infrastructure/mongodb.mjs'
+import { batchedUpdate } from '@overleaf/mongo-utils/batchedUpdate.js'
+import { scriptRunner } from '../lib/ScriptRunner.mjs'
+
+async function main(trackProgress) {
+  // if writefull.enabled is unset or null then the account has no promotion attached yet
+  await batchedUpdate(db.users, {}, [
+    {
+      $set: {
+        'writefull.initialized': {
+          $or: [
+            { $eq: ['$writefull.enabled', true] },
+            { $eq: ['$writefull.enabled', false] },
+          ],
+        },
+      },
+    },
+  ])
+  console.log('completed migration to writefull.initialized')
+}
+
+export default main
+
+try {
+  await scriptRunner(main)
+  process.exit(0)
+} catch (error) {
+  console.error({ error })
+  process.exit(1)
+}

+ 41 - 0
tools/migrations/20260213102825_swap_writefull_enabled_for_initialized.mjs

@@ -0,0 +1,41 @@
+/* eslint-disable no-unused-vars */
+
+import Helpers from './lib/helpers.mjs'
+
+import { batchedUpdate } from '@overleaf/mongo-utils/batchedUpdate.js'
+const tags = ['saas']
+
+const migrate = async client => {
+  const { db } = client
+  // if writefull.enabled is unset or null then the account has no promotion attached yet
+  await batchedUpdate(db.users, {}, [
+    {
+      $set: {
+        'writefull.initialized': {
+          $or: [
+            { $eq: ['$writefull.enabled', true] },
+            { $eq: ['$writefull.enabled', false] },
+          ],
+        },
+      },
+    },
+  ])
+  console.log('completed migration to writefull.initialized')
+}
+
+const rollback = async client => {
+  const { db } = client
+  // unset the user.writefull.initialized value only if its been set
+  await batchedUpdate(
+    db.users,
+    { 'writefull.initialized': { $exists: true } },
+    { $unset: { 'writefull.initialized': 1 } }
+  )
+  console.log('completed rollback of writefull.initialized migration')
+}
+
+export default {
+  tags,
+  migrate,
+  rollback,
+}

+ 51 - 0
tools/migrations/20260216141836_back_fill_hiding_ai_features.mjs

@@ -0,0 +1,51 @@
+/* eslint-disable no-unused-vars */
+
+import { batchedUpdate } from '@overleaf/mongo-utils/batchedUpdate.js'
+
+const tags = ['saas']
+
+const migrate = async client => {
+  const { db } = client
+  // Set aiFeatures.enabled to false where writefull.enabled is false
+  await batchedUpdate(
+    db.users,
+    {
+      'writefull.enabled': false,
+      // dont re-set in cases where we already set aiFeatures, ie: by running the script
+      'aiFeatures.enabled': { $exists: false },
+    },
+    { $set: { 'aiFeatures.enabled': false } }
+  )
+
+  // Set aiFeatures.enabled to true for all other cases (true, null, or not exists)
+  await batchedUpdate(
+    db.users,
+    {
+      'writefull.enabled': { $ne: false },
+      // dont re-set in cases where we already set aiFeatures, ie: by running the script
+      'aiFeatures.enabled': { $exists: false },
+    },
+    { $set: { 'aiFeatures.enabled': true } }
+  )
+
+  console.log(
+    'completed syncing rename of aiErrorAssist.enabled to aiFeatures.enabled'
+  )
+}
+
+const rollback = async client => {
+  const { db } = client
+  // unset the user.writefull.initialized value only if its been set
+  await batchedUpdate(
+    db.users,
+    { 'aiFeatures.enabled': { $exists: true } },
+    { $unset: { 'aiFeatures.enabled': 1 } }
+  )
+  console.log('completed rollback of aiFeatures.enabled migration')
+}
+
+export default {
+  tags,
+  migrate,
+  rollback,
+}