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

Merge pull request #26575 from overleaf/jpa-archived-state

[web] remove runtime migration for project.archived/trashed state

GitOrigin-RevId: 69064878f3dfdcde3727a4e3eb555deb75c70588
Jakob Ackermann 1 год назад
Родитель
Сommit
87de73333a

+ 16 - 48
services/web/app/src/Features/Collaborators/CollaboratorsHandler.js

@@ -2,7 +2,6 @@ const { callbackify } = require('util')
 const OError = require('@overleaf/o-error')
 const OError = require('@overleaf/o-error')
 const { Project } = require('../../models/Project')
 const { Project } = require('../../models/Project')
 const ProjectGetter = require('../Project/ProjectGetter')
 const ProjectGetter = require('../Project/ProjectGetter')
-const ProjectHelper = require('../Project/ProjectHelper')
 const logger = require('@overleaf/logger')
 const logger = require('@overleaf/logger')
 const ContactManager = require('../Contacts/ContactManager')
 const ContactManager = require('../Contacts/ContactManager')
 const PrivilegeLevels = require('../Authorization/PrivilegeLevels')
 const PrivilegeLevels = require('../Authorization/PrivilegeLevels')
@@ -53,55 +52,24 @@ async function fixNullCollaboratorRefs(projectId) {
 
 
 async function removeUserFromProject(projectId, userId) {
 async function removeUserFromProject(projectId, userId) {
   try {
   try {
-    const project = await Project.findOne({ _id: projectId }).exec()
-
     await fixNullCollaboratorRefs(projectId)
     await fixNullCollaboratorRefs(projectId)
 
 
-    // Deal with the old type of boolean value for archived
-    // In order to clear it
-    if (typeof project.archived === 'boolean') {
-      let archived = ProjectHelper.calculateArchivedArray(
-        project,
-        userId,
-        'ARCHIVE'
-      )
-
-      archived = archived.filter(id => id.toString() !== userId.toString())
-
-      await Project.updateOne(
-        { _id: projectId },
-        {
-          $set: { archived },
-          $pull: {
-            collaberator_refs: userId,
-            reviewer_refs: userId,
-            readOnly_refs: userId,
-            pendingEditor_refs: userId,
-            pendingReviewer_refs: userId,
-            tokenAccessReadOnly_refs: userId,
-            tokenAccessReadAndWrite_refs: userId,
-            trashed: userId,
-          },
-        }
-      )
-    } else {
-      await Project.updateOne(
-        { _id: projectId },
-        {
-          $pull: {
-            collaberator_refs: userId,
-            readOnly_refs: userId,
-            reviewer_refs: userId,
-            pendingEditor_refs: userId,
-            pendingReviewer_refs: userId,
-            tokenAccessReadOnly_refs: userId,
-            tokenAccessReadAndWrite_refs: userId,
-            archived: userId,
-            trashed: userId,
-          },
-        }
-      )
-    }
+    await Project.updateOne(
+      { _id: projectId },
+      {
+        $pull: {
+          collaberator_refs: userId,
+          readOnly_refs: userId,
+          reviewer_refs: userId,
+          pendingEditor_refs: userId,
+          pendingReviewer_refs: userId,
+          tokenAccessReadOnly_refs: userId,
+          tokenAccessReadAndWrite_refs: userId,
+          archived: userId,
+          trashed: userId,
+        },
+      }
+    )
   } catch (err) {
   } catch (err) {
     throw OError.tag(err, 'problem removing user from project collaborators', {
     throw OError.tag(err, 'problem removing user from project collaborators', {
       projectId,
       projectId,

+ 20 - 72
services/web/app/src/Features/Project/ProjectDeleter.js

@@ -9,7 +9,6 @@ const Errors = require('../Errors/Errors')
 const logger = require('@overleaf/logger')
 const logger = require('@overleaf/logger')
 const DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
 const DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
 const TagsHandler = require('../Tags/TagsHandler')
 const TagsHandler = require('../Tags/TagsHandler')
-const ProjectHelper = require('./ProjectHelper')
 const ProjectDetailsHandler = require('./ProjectDetailsHandler')
 const ProjectDetailsHandler = require('./ProjectDetailsHandler')
 const CollaboratorsHandler = require('../Collaborators/CollaboratorsHandler')
 const CollaboratorsHandler = require('../Collaborators/CollaboratorsHandler')
 const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter')
 const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter')
@@ -135,88 +134,37 @@ async function restoreProject(projectId) {
 }
 }
 
 
 async function archiveProject(projectId, userId) {
 async function archiveProject(projectId, userId) {
-  try {
-    const project = await Project.findOne({ _id: projectId }).exec()
-    if (!project) {
-      throw new Errors.NotFoundError('project not found')
+  await Project.updateOne(
+    { _id: projectId },
+    {
+      $addToSet: { archived: new ObjectId(userId) },
+      $pull: { trashed: new ObjectId(userId) },
     }
     }
-    const archived = ProjectHelper.calculateArchivedArray(
-      project,
-      userId,
-      'ARCHIVE'
-    )
-
-    await Project.updateOne(
-      { _id: projectId },
-      { $set: { archived }, $pull: { trashed: new ObjectId(userId) } }
-    )
-  } catch (err) {
-    logger.warn({ err }, 'problem archiving project')
-    throw err
-  }
+  )
 }
 }
 
 
 async function unarchiveProject(projectId, userId) {
 async function unarchiveProject(projectId, userId) {
-  try {
-    const project = await Project.findOne({ _id: projectId }).exec()
-    if (!project) {
-      throw new Errors.NotFoundError('project not found')
-    }
-
-    const archived = ProjectHelper.calculateArchivedArray(
-      project,
-      userId,
-      'UNARCHIVE'
-    )
-
-    await Project.updateOne({ _id: projectId }, { $set: { archived } })
-  } catch (err) {
-    logger.warn({ err }, 'problem unarchiving project')
-    throw err
-  }
+  await Project.updateOne(
+    { _id: projectId },
+    { $pull: { archived: new ObjectId(userId) } }
+  )
 }
 }
 
 
 async function trashProject(projectId, userId) {
 async function trashProject(projectId, userId) {
-  try {
-    const project = await Project.findOne({ _id: projectId }).exec()
-    if (!project) {
-      throw new Errors.NotFoundError('project not found')
+  await Project.updateOne(
+    { _id: projectId },
+    {
+      $addToSet: { trashed: new ObjectId(userId) },
+      $pull: { archived: new ObjectId(userId) },
     }
     }
-
-    const archived = ProjectHelper.calculateArchivedArray(
-      project,
-      userId,
-      'UNARCHIVE'
-    )
-
-    await Project.updateOne(
-      { _id: projectId },
-      {
-        $addToSet: { trashed: new ObjectId(userId) },
-        $set: { archived },
-      }
-    )
-  } catch (err) {
-    logger.warn({ err }, 'problem trashing project')
-    throw err
-  }
+  )
 }
 }
 
 
 async function untrashProject(projectId, userId) {
 async function untrashProject(projectId, userId) {
-  try {
-    const project = await Project.findOne({ _id: projectId }).exec()
-    if (!project) {
-      throw new Errors.NotFoundError('project not found')
-    }
-
-    await Project.updateOne(
-      { _id: projectId },
-      { $pull: { trashed: new ObjectId(userId) } }
-    )
-  } catch (err) {
-    logger.warn({ err }, 'problem untrashing project')
-    throw err
-  }
+  await Project.updateOne(
+    { _id: projectId },
+    { $pull: { trashed: new ObjectId(userId) } }
+  )
 }
 }
 
 
 async function deleteProject(projectId, options = {}) {
 async function deleteProject(projectId, options = {}) {

+ 0 - 38
services/web/app/src/Features/Project/ProjectHelper.js

@@ -20,7 +20,6 @@ module.exports = {
   isArchived,
   isArchived,
   isTrashed,
   isTrashed,
   isArchivedOrTrashed,
   isArchivedOrTrashed,
-  calculateArchivedArray,
   ensureNameIsUnique,
   ensureNameIsUnique,
   getAllowedImagesForUser,
   getAllowedImagesForUser,
   promises: {
   promises: {
@@ -63,38 +62,6 @@ function isArchivedOrTrashed(project, userId) {
   return isArchived(project, userId) || isTrashed(project, userId)
   return isArchived(project, userId) || isTrashed(project, userId)
 }
 }
 
 
-function _allCollaborators(project) {
-  return _.unionWith(
-    [project.owner_ref],
-    project.collaberator_refs,
-    project.readOnly_refs,
-    project.tokenAccessReadAndWrite_refs,
-    project.tokenAccessReadOnly_refs,
-    _objectIdEquals
-  )
-}
-
-function calculateArchivedArray(project, userId, action) {
-  let archived = project.archived
-  userId = new ObjectId(userId)
-
-  if (archived === true) {
-    archived = _allCollaborators(project)
-  } else if (!archived) {
-    archived = []
-  }
-
-  if (action === 'ARCHIVE') {
-    archived = _.unionWith(archived, [userId], _objectIdEquals)
-  } else if (action === 'UNARCHIVE') {
-    archived = archived.filter(id => !_objectIdEquals(id, userId))
-  } else {
-    throw new Error('Unrecognised action')
-  }
-
-  return archived
-}
-
 function ensureNameIsUnique(nameList, name, suffixes, maxLength, callback) {
 function ensureNameIsUnique(nameList, name, suffixes, maxLength, callback) {
   // create a set of all project names
   // create a set of all project names
   if (suffixes == null) {
   if (suffixes == null) {
@@ -122,11 +89,6 @@ function ensureNameIsUnique(nameList, name, suffixes, maxLength, callback) {
   }
   }
 }
 }
 
 
-function _objectIdEquals(firstVal, secondVal) {
-  // For use as a comparator for unionWith
-  return firstVal.toString() === secondVal.toString()
-}
-
 function _addSuffixToProjectName(name, suffix, maxLength) {
 function _addSuffixToProjectName(name, suffix, maxLength) {
   // append the suffix and truncate the project title if needed
   // append the suffix and truncate the project title if needed
   if (suffix == null) {
   if (suffix == null) {

+ 49 - 2
services/web/migrations/20221111111111_ce_sp_convert_archived_state.mjs

@@ -1,9 +1,56 @@
-import runScript from '../scripts/convert_archived_state.mjs'
+import { batchedUpdate } from '@overleaf/mongo-utils/batchedUpdate.js'
+import { promiseMapWithLimit } from '@overleaf/promise-utils'
+import { db } from '../app/src/infrastructure/mongodb.js'
+import _ from 'lodash'
 
 
 const tags = ['server-ce', 'server-pro']
 const tags = ['server-ce', 'server-pro']
 
 
+const WRITE_CONCURRENCY = parseInt(process.env.WRITE_CONCURRENCY, 10) || 10
+
+function getAllUserIds(project) {
+  return _.unionWith(
+    [project.owner_ref],
+    project.collaberator_refs,
+    project.readOnly_refs,
+    project.tokenAccessReadAndWrite_refs,
+    project.tokenAccessReadOnly_refs,
+    (a, b) => a.toString() === b.toString()
+  )
+}
+
+async function migrateField(field) {
+  await batchedUpdate(
+    db.projects,
+    { [field]: false },
+    { $set: { [field]: [] } }
+  )
+
+  await batchedUpdate(
+    db.projects,
+    { [field]: true },
+    async nextBatch => {
+      await promiseMapWithLimit(WRITE_CONCURRENCY, nextBatch, async project => {
+        await db.projects.updateOne(
+          { _id: project._id },
+          { $set: { [field]: getAllUserIds(project) } }
+        )
+      })
+    },
+    {
+      _id: 1,
+      owner_ref: 1,
+      collaberator_refs: 1,
+      readOnly_refs: 1,
+      tokenAccessReadAndWrite_refs: 1,
+      tokenAccessReadOnly_refs: 1,
+    }
+  )
+}
+
 const migrate = async () => {
 const migrate = async () => {
-  await runScript('FIRST,SECOND')
+  for (const field of ['archived', 'trashed']) {
+    await migrateField(field)
+  }
 }
 }
 
 
 const rollback = async () => {}
 const rollback = async () => {}

+ 2 - 2
services/web/migrations/lib/adapter.mjs

@@ -10,9 +10,9 @@ class Adapter {
     if (
     if (
       !process.env.SKIP_TAG_CHECK &&
       !process.env.SKIP_TAG_CHECK &&
       !process.argv.includes('create') &&
       !process.argv.includes('create') &&
-      !(process.argv.includes('-t') || process.argv.includes('--tags'))
+      !(process.argv.includes('-t') || process.argv.includes('--tag'))
     ) {
     ) {
-      console.error("ERROR: must pass tags using '-t' or '--tags', exiting")
+      console.error("ERROR: must pass tags using '-t' or '--tag', exiting")
       process.exit(1)
       process.exit(1)
     }
     }
     this.params = params || {}
     this.params = params || {}

+ 0 - 93
services/web/scripts/convert_archived_state.mjs

@@ -1,93 +0,0 @@
-import _ from 'lodash'
-import { db } from '../app/src/infrastructure/mongodb.js'
-import { batchedUpdate } from '@overleaf/mongo-utils/batchedUpdate.js'
-import { promiseMapWithLimit } from '@overleaf/promise-utils'
-import { fileURLToPath } from 'node:url'
-
-const WRITE_CONCURRENCY = parseInt(process.env.WRITE_CONCURRENCY, 10) || 10
-
-// $ node scripts/convert_archived_state.mjs FIRST,SECOND
-
-async function main(STAGE) {
-  for (const FIELD of ['archived', 'trashed']) {
-    if (STAGE.includes('FIRST')) {
-      await batchedUpdate(
-        db.projects,
-        { [FIELD]: false },
-        {
-          $set: { [FIELD]: [] },
-        }
-      )
-
-      console.error('Done, with first part for field:', FIELD)
-    }
-
-    if (STAGE.includes('SECOND')) {
-      await batchedUpdate(
-        db.projects,
-        { [FIELD]: true },
-        async function performUpdate(nextBatch) {
-          await promiseMapWithLimit(
-            WRITE_CONCURRENCY,
-            nextBatch,
-            async project => {
-              try {
-                await upgradeFieldToArray({ 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 for field:', FIELD)
-    }
-  }
-}
-
-async function upgradeFieldToArray({ project, FIELD }) {
-  return db.projects.updateOne(
-    { _id: project._id },
-    {
-      $set: { [FIELD]: getAllUserIds(project) },
-    }
-  )
-}
-
-function getAllUserIds(project) {
-  return _.unionWith(
-    [project.owner_ref],
-    project.collaberator_refs,
-    project.readOnly_refs,
-    project.tokenAccessReadAndWrite_refs,
-    project.tokenAccessReadOnly_refs,
-    _objectIdEquals
-  )
-}
-
-function _objectIdEquals(firstVal, secondVal) {
-  // For use as a comparator for unionWith
-  return firstVal.toString() === secondVal.toString()
-}
-
-if (fileURLToPath(import.meta.url) === process.argv[1]) {
-  try {
-    await main(process.argv.pop())
-    process.exit(0)
-  } catch (error) {
-    console.error({ error })
-    process.exit(1)
-  }
-}
-
-export default main

+ 1 - 1
services/web/test/acceptance/src/ConvertArchivedState.mjs

@@ -120,7 +120,7 @@ describe('ConvertArchivedState', function () {
 
 
   beforeEach(function (done) {
   beforeEach(function (done) {
     exec(
     exec(
-      'CONNECT_DELAY=1 node scripts/convert_archived_state.mjs FIRST,SECOND',
+      'east migrate --tag server-ce --force 20221111111111_ce_sp_convert_archived_state',
       error => {
       error => {
         if (error) {
         if (error) {
           return done(error)
           return done(error)

+ 0 - 19
services/web/test/acceptance/src/ProjectCRUDTests.mjs

@@ -125,25 +125,6 @@ describe('Project CRUD', function () {
         expectObjectIdArrayEqual(trashedProject.archived, [])
         expectObjectIdArrayEqual(trashedProject.archived, [])
       })
       })
     })
     })
-
-    describe('with a legacy boolean state', function () {
-      it('should mark the project as not archived for the user', async function () {
-        await Project.updateOne(
-          { _id: this.projectId },
-          { $set: { archived: true } }
-        ).exec()
-
-        const { response } = await this.user.doRequest(
-          'POST',
-          `/project/${this.projectId}/trash`
-        )
-
-        expect(response.statusCode).to.equal(200)
-
-        const trashedProject = await Project.findById(this.projectId).exec()
-        expectObjectIdArrayEqual(trashedProject.archived, [])
-      })
-    })
   })
   })
 
 
   describe('when untrashing a project', function () {
   describe('when untrashing a project', function () {

+ 0 - 113
services/web/test/unit/src/Collaborators/CollaboratorsHandlerTests.js

@@ -24,16 +24,6 @@ describe('CollaboratorsHandler', function () {
       name: 'Foo',
       name: 'Foo',
     }
     }
 
 
-    this.archivedProject = {
-      _id: new ObjectId(),
-      archived: [new ObjectId(this.userId)],
-    }
-
-    this.oldArchivedProject = {
-      _id: new ObjectId(),
-      archived: true,
-    }
-
     this.UserGetter = {
     this.UserGetter = {
       promises: {
       promises: {
         getUser: sinon.stub().resolves(null),
         getUser: sinon.stub().resolves(null),
@@ -59,9 +49,6 @@ describe('CollaboratorsHandler', function () {
       },
       },
     }
     }
 
 
-    this.ProjectHelper = {
-      calculateArchivedArray: sinon.stub(),
-    }
     this.CollaboratorsGetter = {
     this.CollaboratorsGetter = {
       promises: {
       promises: {
         dangerouslyGetAllProjectsUserIsMemberOf: sinon.stub(),
         dangerouslyGetAllProjectsUserIsMemberOf: sinon.stub(),
@@ -77,7 +64,6 @@ describe('CollaboratorsHandler', function () {
         '../ThirdPartyDataStore/TpdsProjectFlusher': this.TpdsProjectFlusher,
         '../ThirdPartyDataStore/TpdsProjectFlusher': this.TpdsProjectFlusher,
         '../ThirdPartyDataStore/TpdsUpdateSender': this.TpdsUpdateSender,
         '../ThirdPartyDataStore/TpdsUpdateSender': this.TpdsUpdateSender,
         '../Project/ProjectGetter': this.ProjectGetter,
         '../Project/ProjectGetter': this.ProjectGetter,
-        '../Project/ProjectHelper': this.ProjectHelper,
         '../Editor/EditorRealTimeController': this.EditorRealTimeController,
         '../Editor/EditorRealTimeController': this.EditorRealTimeController,
         './CollaboratorsGetter': this.CollaboratorsGetter,
         './CollaboratorsGetter': this.CollaboratorsGetter,
       },
       },
@@ -130,15 +116,6 @@ describe('CollaboratorsHandler', function () {
 
 
   describe('removeUserFromProject', function () {
   describe('removeUserFromProject', function () {
     describe('a non-archived project', function () {
     describe('a non-archived project', function () {
-      beforeEach(function () {
-        this.ProjectMock.expects('findOne')
-          .withArgs({
-            _id: this.project._id,
-          })
-          .chain('exec')
-          .resolves(this.project)
-      })
-
       it('should remove the user from mongo', async function () {
       it('should remove the user from mongo', async function () {
         this.expectNullReferenceCleanup(this.project._id)
         this.expectNullReferenceCleanup(this.project._id)
         this.ProjectMock.expects('updateOne')
         this.ProjectMock.expects('updateOne')
@@ -168,89 +145,6 @@ describe('CollaboratorsHandler', function () {
         )
         )
       })
       })
     })
     })
-
-    describe('an archived project, archived with a boolean value', function () {
-      beforeEach(function () {
-        const archived = [new ObjectId(this.userId)]
-        this.ProjectHelper.calculateArchivedArray.returns(archived)
-
-        this.ProjectMock.expects('findOne')
-          .withArgs({
-            _id: this.oldArchivedProject._id,
-          })
-          .chain('exec')
-          .resolves(this.oldArchivedProject)
-      })
-
-      it('should remove the user from mongo', async function () {
-        this.expectNullReferenceCleanup(this.oldArchivedProject._id)
-        this.ProjectMock.expects('updateOne')
-          .withArgs(
-            {
-              _id: this.oldArchivedProject._id,
-            },
-            {
-              $set: {
-                archived: [],
-              },
-              $pull: {
-                collaberator_refs: this.userId,
-                reviewer_refs: this.userId,
-                readOnly_refs: this.userId,
-                pendingEditor_refs: this.userId,
-                pendingReviewer_refs: this.userId,
-                tokenAccessReadOnly_refs: this.userId,
-                tokenAccessReadAndWrite_refs: this.userId,
-                trashed: this.userId,
-              },
-            }
-          )
-          .resolves()
-        await this.CollaboratorsHandler.promises.removeUserFromProject(
-          this.oldArchivedProject._id,
-          this.userId
-        )
-      })
-    })
-
-    describe('an archived project, archived with an array value', function () {
-      beforeEach(function () {
-        this.ProjectMock.expects('findOne')
-          .withArgs({
-            _id: this.archivedProject._id,
-          })
-          .chain('exec')
-          .resolves(this.archivedProject)
-      })
-
-      it('should remove the user from mongo', async function () {
-        this.expectNullReferenceCleanup(this.archivedProject._id)
-        this.ProjectMock.expects('updateOne')
-          .withArgs(
-            {
-              _id: this.archivedProject._id,
-            },
-            {
-              $pull: {
-                collaberator_refs: this.userId,
-                reviewer_refs: this.userId,
-                readOnly_refs: this.userId,
-                pendingEditor_refs: this.userId,
-                pendingReviewer_refs: this.userId,
-                tokenAccessReadOnly_refs: this.userId,
-                tokenAccessReadAndWrite_refs: this.userId,
-                archived: this.userId,
-                trashed: this.userId,
-              },
-            }
-          )
-          .resolves()
-        await this.CollaboratorsHandler.promises.removeUserFromProject(
-          this.archivedProject._id,
-          this.userId
-        )
-      })
-    })
   })
   })
 
 
   describe('addUserIdToProject', function () {
   describe('addUserIdToProject', function () {
@@ -539,13 +433,6 @@ describe('CollaboratorsHandler', function () {
         'token-read-only-1',
         'token-read-only-1',
       ]
       ]
       for (const projectId of expectedProjects) {
       for (const projectId of expectedProjects) {
-        this.ProjectMock.expects('findOne')
-          .withArgs({
-            _id: projectId,
-          })
-          .chain('exec')
-          .resolves({ _id: projectId })
-
         this.expectNullReferenceCleanup(projectId)
         this.expectNullReferenceCleanup(projectId)
         this.ProjectMock.expects('updateOne')
         this.ProjectMock.expects('updateOne')
           .withArgs(
           .withArgs(

+ 6 - 73
services/web/test/unit/src/Project/ProjectDeleterTests.js

@@ -95,10 +95,6 @@ describe('ProjectDeleter', function () {
       },
       },
     }
     }
 
 
-    this.ProjectHelper = {
-      calculateArchivedArray: sinon.stub(),
-    }
-
     this.db = {
     this.db = {
       projects: {
       projects: {
         insertOne: sinon.stub().resolves(),
         insertOne: sinon.stub().resolves(),
@@ -143,7 +139,6 @@ describe('ProjectDeleter', function () {
         '../../infrastructure/Features': this.Features,
         '../../infrastructure/Features': this.Features,
         '../Editor/EditorRealTimeController': this.EditorRealTimeController,
         '../Editor/EditorRealTimeController': this.EditorRealTimeController,
         '../../models/Project': { Project },
         '../../models/Project': { Project },
-        './ProjectHelper': this.ProjectHelper,
         '../../models/DeletedProject': { DeletedProject },
         '../../models/DeletedProject': { DeletedProject },
         '../DocumentUpdater/DocumentUpdaterHandler':
         '../DocumentUpdater/DocumentUpdaterHandler':
           this.DocumentUpdaterHandler,
           this.DocumentUpdaterHandler,
@@ -559,19 +554,11 @@ describe('ProjectDeleter', function () {
 
 
   describe('archiveProject', function () {
   describe('archiveProject', function () {
     beforeEach(function () {
     beforeEach(function () {
-      const archived = [new ObjectId(this.user._id)]
-      this.ProjectHelper.calculateArchivedArray.returns(archived)
-
-      this.ProjectMock.expects('findOne')
-        .withArgs({ _id: this.project._id })
-        .chain('exec')
-        .resolves(this.project)
-
       this.ProjectMock.expects('updateOne')
       this.ProjectMock.expects('updateOne')
         .withArgs(
         .withArgs(
           { _id: this.project._id },
           { _id: this.project._id },
           {
           {
-            $set: { archived },
+            $addToSet: { archived: new ObjectId(this.user._id) },
             $pull: { trashed: new ObjectId(this.user._id) },
             $pull: { trashed: new ObjectId(this.user._id) },
           }
           }
         )
         )
@@ -585,32 +572,15 @@ describe('ProjectDeleter', function () {
       )
       )
       this.ProjectMock.verify()
       this.ProjectMock.verify()
     })
     })
-
-    it('calculates the archived array', async function () {
-      await this.ProjectDeleter.promises.archiveProject(
-        this.project._id,
-        this.user._id
-      )
-      expect(this.ProjectHelper.calculateArchivedArray).to.have.been.calledWith(
-        this.project,
-        this.user._id,
-        'ARCHIVE'
-      )
-    })
   })
   })
 
 
   describe('unarchiveProject', function () {
   describe('unarchiveProject', function () {
     beforeEach(function () {
     beforeEach(function () {
-      const archived = [new ObjectId(this.user._id)]
-      this.ProjectHelper.calculateArchivedArray.returns(archived)
-
-      this.ProjectMock.expects('findOne')
-        .withArgs({ _id: this.project._id })
-        .chain('exec')
-        .resolves(this.project)
-
       this.ProjectMock.expects('updateOne')
       this.ProjectMock.expects('updateOne')
-        .withArgs({ _id: this.project._id }, { $set: { archived } })
+        .withArgs(
+          { _id: this.project._id },
+          { $pull: { archived: new ObjectId(this.user._id) } }
+        )
         .resolves()
         .resolves()
     })
     })
 
 
@@ -621,36 +591,16 @@ describe('ProjectDeleter', function () {
       )
       )
       this.ProjectMock.verify()
       this.ProjectMock.verify()
     })
     })
-
-    it('calculates the archived array', async function () {
-      await this.ProjectDeleter.promises.unarchiveProject(
-        this.project._id,
-        this.user._id
-      )
-      expect(this.ProjectHelper.calculateArchivedArray).to.have.been.calledWith(
-        this.project,
-        this.user._id,
-        'UNARCHIVE'
-      )
-    })
   })
   })
 
 
   describe('trashProject', function () {
   describe('trashProject', function () {
     beforeEach(function () {
     beforeEach(function () {
-      const archived = [new ObjectId(this.user._id)]
-      this.ProjectHelper.calculateArchivedArray.returns(archived)
-
-      this.ProjectMock.expects('findOne')
-        .withArgs({ _id: this.project._id })
-        .chain('exec')
-        .resolves(this.project)
-
       this.ProjectMock.expects('updateOne')
       this.ProjectMock.expects('updateOne')
         .withArgs(
         .withArgs(
           { _id: this.project._id },
           { _id: this.project._id },
           {
           {
             $addToSet: { trashed: new ObjectId(this.user._id) },
             $addToSet: { trashed: new ObjectId(this.user._id) },
-            $set: { archived },
+            $pull: { archived: new ObjectId(this.user._id) },
           }
           }
         )
         )
         .resolves()
         .resolves()
@@ -663,27 +613,10 @@ describe('ProjectDeleter', function () {
       )
       )
       this.ProjectMock.verify()
       this.ProjectMock.verify()
     })
     })
-
-    it('unarchives the project', async function () {
-      await this.ProjectDeleter.promises.trashProject(
-        this.project._id,
-        this.user._id
-      )
-      expect(this.ProjectHelper.calculateArchivedArray).to.have.been.calledWith(
-        this.project,
-        this.user._id,
-        'UNARCHIVE'
-      )
-    })
   })
   })
 
 
   describe('untrashProject', function () {
   describe('untrashProject', function () {
     beforeEach(function () {
     beforeEach(function () {
-      this.ProjectMock.expects('findOne')
-        .withArgs({ _id: this.project._id })
-        .chain('exec')
-        .resolves(this.project)
-
       this.ProjectMock.expects('updateOne')
       this.ProjectMock.expects('updateOne')
         .withArgs(
         .withArgs(
           { _id: this.project._id },
           { _id: this.project._id },

+ 0 - 128
services/web/test/unit/src/Project/ProjectHelperTests.js

@@ -101,134 +101,6 @@ describe('ProjectHelper', function () {
     })
     })
   })
   })
 
 
-  describe('calculateArchivedArray', function () {
-    describe('project.archived being an array', function () {
-      it('returns an array adding the current user id when archiving', function () {
-        const project = { archived: [] }
-        const result = this.ProjectHelper.calculateArchivedArray(
-          project,
-          new ObjectId('5c922599cdb09e014aa7d499'),
-          'ARCHIVE'
-        )
-        expect(result).to.deep.equal([new ObjectId('5c922599cdb09e014aa7d499')])
-      })
-
-      it('returns an array without the current user id when unarchiving', function () {
-        const project = { archived: [new ObjectId('5c922599cdb09e014aa7d499')] }
-        const result = this.ProjectHelper.calculateArchivedArray(
-          project,
-          new ObjectId('5c922599cdb09e014aa7d499'),
-          'UNARCHIVE'
-        )
-        expect(result).to.deep.equal([])
-      })
-    })
-
-    describe('project.archived being a boolean and being true', function () {
-      it('returns an array of all associated user ids when archiving', function () {
-        const project = {
-          archived: true,
-          owner_ref: this.user._id,
-          collaberator_refs: [
-            new ObjectId('4f2cfb341eb5855a5b000f8b'),
-            new ObjectId('5c45f3bd425ead01488675aa'),
-          ],
-          readOnly_refs: [new ObjectId('5c92243fcdb09e014aa7d487')],
-          tokenAccessReadAndWrite_refs: [
-            new ObjectId('5c922599cdb09e014aa7d499'),
-          ],
-          tokenAccessReadOnly_refs: [],
-        }
-
-        const result = this.ProjectHelper.calculateArchivedArray(
-          project,
-          this.user._id,
-          'ARCHIVE'
-        )
-        expect(result).to.deep.equal([
-          this.user._id,
-          new ObjectId('4f2cfb341eb5855a5b000f8b'),
-          new ObjectId('5c45f3bd425ead01488675aa'),
-          new ObjectId('5c92243fcdb09e014aa7d487'),
-          new ObjectId('5c922599cdb09e014aa7d499'),
-        ])
-      })
-
-      it('returns an array of all associated users without the current user id when unarchived', function () {
-        const project = {
-          archived: true,
-          owner_ref: this.user._id,
-          collaberator_refs: [
-            new ObjectId('4f2cfb341eb5855a5b000f8b'),
-            new ObjectId('5c45f3bd425ead01488675aa'),
-            new ObjectId('5c922599cdb09e014aa7d499'),
-          ],
-          readOnly_refs: [new ObjectId('5c92243fcdb09e014aa7d487')],
-          tokenAccessReadAndWrite_refs: [
-            new ObjectId('5c922599cdb09e014aa7d499'),
-          ],
-          tokenAccessReadOnly_refs: [],
-        }
-
-        const result = this.ProjectHelper.calculateArchivedArray(
-          project,
-          this.user._id,
-          'UNARCHIVE'
-        )
-        expect(result).to.deep.equal([
-          new ObjectId('4f2cfb341eb5855a5b000f8b'),
-          new ObjectId('5c45f3bd425ead01488675aa'),
-          new ObjectId('5c922599cdb09e014aa7d499'),
-          new ObjectId('5c92243fcdb09e014aa7d487'),
-        ])
-      })
-    })
-
-    describe('project.archived being a boolean and being false', function () {
-      it('returns an array adding the current user id when archiving', function () {
-        const project = { archived: false }
-        const result = this.ProjectHelper.calculateArchivedArray(
-          project,
-          new ObjectId('5c922599cdb09e014aa7d499'),
-          'ARCHIVE'
-        )
-        expect(result).to.deep.equal([new ObjectId('5c922599cdb09e014aa7d499')])
-      })
-
-      it('returns an empty array when unarchiving', function () {
-        const project = { archived: false }
-        const result = this.ProjectHelper.calculateArchivedArray(
-          project,
-          new ObjectId('5c922599cdb09e014aa7d499'),
-          'UNARCHIVE'
-        )
-        expect(result).to.deep.equal([])
-      })
-    })
-
-    describe('project.archived not being set', function () {
-      it('returns an array adding the current user id when archiving', function () {
-        const project = { archived: undefined }
-        const result = this.ProjectHelper.calculateArchivedArray(
-          project,
-          new ObjectId('5c922599cdb09e014aa7d499'),
-          'ARCHIVE'
-        )
-        expect(result).to.deep.equal([new ObjectId('5c922599cdb09e014aa7d499')])
-      })
-
-      it('returns an empty array when unarchiving', function () {
-        const project = { archived: undefined }
-        const result = this.ProjectHelper.calculateArchivedArray(
-          project,
-          new ObjectId('5c922599cdb09e014aa7d499'),
-          'UNARCHIVE'
-        )
-        expect(result).to.deep.equal([])
-      })
-    })
-  })
-
   describe('compilerFromV1Engine', function () {
   describe('compilerFromV1Engine', function () {
     it('returns the correct engine for latex_dvipdf', function () {
     it('returns the correct engine for latex_dvipdf', function () {
       expect(this.ProjectHelper.compilerFromV1Engine('latex_dvipdf')).to.equal(
       expect(this.ProjectHelper.compilerFromV1Engine('latex_dvipdf')).to.equal(