Просмотр исходного кода

Merge pull request #10442 from overleaf/jpa-convert-archived-trashed

[web] add migration for convert_archived_state script

GitOrigin-RevId: aeea3601a0c5f96e978c3f2a85458687d6d6678e
Jakob Ackermann 3 лет назад
Родитель
Сommit
d4551dc7ce

+ 9 - 0
services/web/migrations/20221111111111_ce_sp_convert_archived_state.js

@@ -0,0 +1,9 @@
+const runScript = require('../scripts/convert_archived_state')
+
+exports.tags = ['server-ce', 'server-pro']
+
+exports.migrate = async () => {
+  await runScript('FIRST,SECOND')
+}
+
+exports.rollback = async () => {}

+ 54 - 39
services/web/scripts/convert_archived_state.js

@@ -6,62 +6,77 @@ const { batchedUpdate } = require('./helpers/batchedUpdate')
 const { promiseMapWithLimit } = require('../app/src/util/promises')
 
 // $ node scripts/convert_archived_state.js FIRST,SECOND
-const STAGE = process.argv.pop()
 
-async function main() {
-  if (STAGE.includes('FIRST')) {
-    await batchedUpdate(
-      'projects',
-      { archived: false },
-      {
-        $set: { archived: [] },
-      }
-    )
+async function main(STAGE) {
+  for (const FIELD of ['archived', 'trashed']) {
+    if (STAGE.includes('FIRST')) {
+      await batchedUpdate(
+        'projects',
+        { [FIELD]: false },
+        {
+          $set: { [FIELD]: [] },
+        }
+      )
 
-    console.error('Done, with first part')
-  }
+      console.error('Done, with first part for field:', FIELD)
+    }
 
-  if (STAGE.includes('SECOND')) {
-    await batchedUpdate('projects', { archived: true }, performUpdate, {
-      _id: 1,
-      owner_ref: 1,
-      collaberator_refs: 1,
-      readOnly_refs: 1,
-      tokenAccessReadAndWrite_refs: 1,
-      tokenAccessReadOnly_refs: 1,
-    })
+    if (STAGE.includes('SECOND')) {
+      await batchedUpdate(
+        'projects',
+        { [FIELD]: true },
+        async function performUpdate(collection, nextBatch) {
+          await promiseMapWithLimit(
+            WRITE_CONCURRENCY,
+            nextBatch,
+            async project => {
+              try {
+                await upgradeFieldToArray({ collection, project, FIELD })
+              } catch (err) {
+                console.error(project._id, err)
+                throw err
+              }
+            }
+          )
+        },
+        {
+          _id: 1,
+          owner_ref: 1,
+          collaberator_refs: 1,
+          readOnly_refs: 1,
+          tokenAccessReadAndWrite_refs: 1,
+          tokenAccessReadOnly_refs: 1,
+        }
+      )
 
-    console.error('Done, with second part')
+      console.error('Done, with second part for field:', FIELD)
+    }
   }
 }
 
-main()
-  .then(() => {
-    process.exit(0)
-  })
-  .catch(error => {
-    console.error({ error })
-    process.exit(1)
-  })
+module.exports = main
 
-async function performUpdate(collection, nextBatch) {
-  await promiseMapWithLimit(WRITE_CONCURRENCY, nextBatch, project =>
-    setArchived(collection, project)
-  )
+if (require.main === module) {
+  main(process.argv.pop())
+    .then(() => {
+      process.exit(0)
+    })
+    .catch(error => {
+      console.error({ error })
+      process.exit(1)
+    })
 }
 
-async function setArchived(collection, project) {
-  const archived = calculateArchivedArray(project)
-
+async function upgradeFieldToArray({ collection, project, FIELD }) {
   return collection.updateOne(
     { _id: project._id },
     {
-      $set: { archived },
+      $set: { [FIELD]: getAllUserIds(project) },
     }
   )
 }
 
-function calculateArchivedArray(project) {
+function getAllUserIds(project) {
   return _.unionWith(
     [project.owner_ref],
     project.collaberator_refs,

+ 87 - 2
services/web/test/acceptance/src/ConvertArchivedState.js

@@ -10,6 +10,10 @@ describe('ConvertArchivedState', function () {
   let projectTwo, projectTwoId
   let projectThree, projectThreeId
   let projectFour, projectFourId
+  let projectIdTrashed
+  let projectIdNotTrashed
+  let projectIdArchivedAndTrashed
+  let projectIdNotArchivedNotTrashed
 
   beforeEach(async function () {
     userOne = new User()
@@ -64,15 +68,60 @@ describe('ConvertArchivedState', function () {
     projectFour.archived = false
 
     await userOne.saveProject(projectFour)
+
+    projectIdTrashed = await userOne.createProject('trashed', {
+      template: 'blank',
+    })
+    {
+      const p = await userOne.getProject(projectIdTrashed)
+      p.trashed = true
+      p.collaberator_refs.push(userTwo._id)
+      await userOne.saveProject(p)
+    }
+
+    projectIdNotTrashed = await userOne.createProject('not-trashed', {
+      template: 'blank',
+    })
+    {
+      const p = await userOne.getProject(projectIdNotTrashed)
+      p.trashed = false
+      p.collaberator_refs.push(userTwo._id)
+      await userOne.saveProject(p)
+    }
+
+    projectIdArchivedAndTrashed = await userOne.createProject('not-trashed', {
+      template: 'blank',
+    })
+    {
+      const p = await userOne.getProject(projectIdArchivedAndTrashed)
+      p.archived = true
+      p.trashed = true
+      p.collaberator_refs.push(userTwo._id)
+      await userOne.saveProject(p)
+    }
+
+    projectIdNotArchivedNotTrashed = await userOne.createProject(
+      'not-archived,not-trashed',
+      {
+        template: 'blank',
+      }
+    )
+    {
+      const p = await userOne.getProject(projectIdNotArchivedNotTrashed)
+      p.archived = false
+      p.trashed = false
+      p.collaberator_refs.push(userTwo._id)
+      await userOne.saveProject(p)
+    }
   })
 
   beforeEach(function (done) {
     exec(
       'CONNECT_DELAY=1 node scripts/convert_archived_state.js FIRST,SECOND',
       (error, stdout, stderr) => {
-        console.log(stdout)
-        console.error(stderr)
         if (error) {
+          console.log(stdout)
+          console.error(stderr)
           return done(error)
         }
         done()
@@ -95,6 +144,7 @@ describe('ConvertArchivedState', function () {
         userThree._id,
         userFour._id,
       ])
+      expect(projectTwo.trashed).to.deep.equal([])
     })
 
     it('should not change the value of a project already archived with an array', async function () {
@@ -104,11 +154,46 @@ describe('ConvertArchivedState', function () {
         userTwo._id,
         userFour._id,
       ])
+      expect(projectThree.trashed).to.deep.equal([])
     })
 
     it('should change a none-archived project with a boolean value to an array', async function () {
       projectFour = await userOne.getProject(projectFourId)
       expect(convertObjectIdsToStrings(projectFour.archived)).to.deep.equal([])
+      expect(projectFour.trashed).to.deep.equal([])
+    })
+
+    it('should change a archived and trashed project with a boolean value to an array', async function () {
+      const p = await userOne.getProject(projectIdArchivedAndTrashed)
+      expect(convertObjectIdsToStrings(p.archived)).to.deep.equal([
+        userOne._id,
+        userTwo._id,
+      ])
+      expect(convertObjectIdsToStrings(p.trashed)).to.deep.equal([
+        userOne._id,
+        userTwo._id,
+      ])
+    })
+
+    it('should change a trashed project with a boolean value to an array', async function () {
+      const p = await userOne.getProject(projectIdTrashed)
+      expect(p.archived).to.not.exist
+      expect(convertObjectIdsToStrings(p.trashed)).to.deep.equal([
+        userOne._id,
+        userTwo._id,
+      ])
+    })
+
+    it('should change a not-trashed project with a boolean value to an array', async function () {
+      const p = await userOne.getProject(projectIdNotTrashed)
+      expect(p.archived).to.not.exist
+      expect(convertObjectIdsToStrings(p.trashed)).to.deep.equal([])
+    })
+
+    it('should change a not-archived/not-trashed project with a boolean value to an array', async function () {
+      const p = await userOne.getProject(projectIdNotArchivedNotTrashed)
+      expect(p.archived).to.deep.equal([])
+      expect(p.trashed).to.deep.equal([])
     })
   })