mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-24 17:51:51 +02:00
Merge pull request #26575 from overleaf/jpa-archived-state
[web] remove runtime migration for project.archived/trashed state GitOrigin-RevId: 69064878f3dfdcde3727a4e3eb555deb75c70588
This commit is contained in:
@@ -2,7 +2,6 @@ const { callbackify } = require('util')
|
||||
const OError = require('@overleaf/o-error')
|
||||
const { Project } = require('../../models/Project')
|
||||
const ProjectGetter = require('../Project/ProjectGetter')
|
||||
const ProjectHelper = require('../Project/ProjectHelper')
|
||||
const logger = require('@overleaf/logger')
|
||||
const ContactManager = require('../Contacts/ContactManager')
|
||||
const PrivilegeLevels = require('../Authorization/PrivilegeLevels')
|
||||
@@ -53,55 +52,24 @@ async function fixNullCollaboratorRefs(projectId) {
|
||||
|
||||
async function removeUserFromProject(projectId, userId) {
|
||||
try {
|
||||
const project = await Project.findOne({ _id: projectId }).exec()
|
||||
|
||||
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) {
|
||||
throw OError.tag(err, 'problem removing user from project collaborators', {
|
||||
projectId,
|
||||
|
||||
@@ -9,7 +9,6 @@ const Errors = require('../Errors/Errors')
|
||||
const logger = require('@overleaf/logger')
|
||||
const DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
|
||||
const TagsHandler = require('../Tags/TagsHandler')
|
||||
const ProjectHelper = require('./ProjectHelper')
|
||||
const ProjectDetailsHandler = require('./ProjectDetailsHandler')
|
||||
const CollaboratorsHandler = require('../Collaborators/CollaboratorsHandler')
|
||||
const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter')
|
||||
@@ -135,88 +134,37 @@ async function restoreProject(projectId) {
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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 = {}) {
|
||||
|
||||
@@ -20,7 +20,6 @@ module.exports = {
|
||||
isArchived,
|
||||
isTrashed,
|
||||
isArchivedOrTrashed,
|
||||
calculateArchivedArray,
|
||||
ensureNameIsUnique,
|
||||
getAllowedImagesForUser,
|
||||
promises: {
|
||||
@@ -63,38 +62,6 @@ function isArchivedOrTrashed(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) {
|
||||
// create a set of all project names
|
||||
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) {
|
||||
// append the suffix and truncate the project title if needed
|
||||
if (suffix == null) {
|
||||
|
||||
@@ -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 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 () => {
|
||||
await runScript('FIRST,SECOND')
|
||||
for (const field of ['archived', 'trashed']) {
|
||||
await migrateField(field)
|
||||
}
|
||||
}
|
||||
|
||||
const rollback = async () => {}
|
||||
|
||||
@@ -10,9 +10,9 @@ class Adapter {
|
||||
if (
|
||||
!process.env.SKIP_TAG_CHECK &&
|
||||
!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)
|
||||
}
|
||||
this.params = params || {}
|
||||
|
||||
@@ -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
|
||||
@@ -120,7 +120,7 @@ describe('ConvertArchivedState', function () {
|
||||
|
||||
beforeEach(function (done) {
|
||||
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 => {
|
||||
if (error) {
|
||||
return done(error)
|
||||
|
||||
@@ -125,25 +125,6 @@ describe('Project CRUD', function () {
|
||||
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 () {
|
||||
|
||||
@@ -24,16 +24,6 @@ describe('CollaboratorsHandler', function () {
|
||||
name: 'Foo',
|
||||
}
|
||||
|
||||
this.archivedProject = {
|
||||
_id: new ObjectId(),
|
||||
archived: [new ObjectId(this.userId)],
|
||||
}
|
||||
|
||||
this.oldArchivedProject = {
|
||||
_id: new ObjectId(),
|
||||
archived: true,
|
||||
}
|
||||
|
||||
this.UserGetter = {
|
||||
promises: {
|
||||
getUser: sinon.stub().resolves(null),
|
||||
@@ -59,9 +49,6 @@ describe('CollaboratorsHandler', function () {
|
||||
},
|
||||
}
|
||||
|
||||
this.ProjectHelper = {
|
||||
calculateArchivedArray: sinon.stub(),
|
||||
}
|
||||
this.CollaboratorsGetter = {
|
||||
promises: {
|
||||
dangerouslyGetAllProjectsUserIsMemberOf: sinon.stub(),
|
||||
@@ -77,7 +64,6 @@ describe('CollaboratorsHandler', function () {
|
||||
'../ThirdPartyDataStore/TpdsProjectFlusher': this.TpdsProjectFlusher,
|
||||
'../ThirdPartyDataStore/TpdsUpdateSender': this.TpdsUpdateSender,
|
||||
'../Project/ProjectGetter': this.ProjectGetter,
|
||||
'../Project/ProjectHelper': this.ProjectHelper,
|
||||
'../Editor/EditorRealTimeController': this.EditorRealTimeController,
|
||||
'./CollaboratorsGetter': this.CollaboratorsGetter,
|
||||
},
|
||||
@@ -130,15 +116,6 @@ describe('CollaboratorsHandler', function () {
|
||||
|
||||
describe('removeUserFromProject', 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 () {
|
||||
this.expectNullReferenceCleanup(this.project._id)
|
||||
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 () {
|
||||
@@ -539,13 +433,6 @@ describe('CollaboratorsHandler', function () {
|
||||
'token-read-only-1',
|
||||
]
|
||||
for (const projectId of expectedProjects) {
|
||||
this.ProjectMock.expects('findOne')
|
||||
.withArgs({
|
||||
_id: projectId,
|
||||
})
|
||||
.chain('exec')
|
||||
.resolves({ _id: projectId })
|
||||
|
||||
this.expectNullReferenceCleanup(projectId)
|
||||
this.ProjectMock.expects('updateOne')
|
||||
.withArgs(
|
||||
|
||||
@@ -95,10 +95,6 @@ describe('ProjectDeleter', function () {
|
||||
},
|
||||
}
|
||||
|
||||
this.ProjectHelper = {
|
||||
calculateArchivedArray: sinon.stub(),
|
||||
}
|
||||
|
||||
this.db = {
|
||||
projects: {
|
||||
insertOne: sinon.stub().resolves(),
|
||||
@@ -143,7 +139,6 @@ describe('ProjectDeleter', function () {
|
||||
'../../infrastructure/Features': this.Features,
|
||||
'../Editor/EditorRealTimeController': this.EditorRealTimeController,
|
||||
'../../models/Project': { Project },
|
||||
'./ProjectHelper': this.ProjectHelper,
|
||||
'../../models/DeletedProject': { DeletedProject },
|
||||
'../DocumentUpdater/DocumentUpdaterHandler':
|
||||
this.DocumentUpdaterHandler,
|
||||
@@ -559,19 +554,11 @@ describe('ProjectDeleter', function () {
|
||||
|
||||
describe('archiveProject', 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')
|
||||
.withArgs(
|
||||
{ _id: this.project._id },
|
||||
{
|
||||
$set: { archived },
|
||||
$addToSet: { archived: new ObjectId(this.user._id) },
|
||||
$pull: { trashed: new ObjectId(this.user._id) },
|
||||
}
|
||||
)
|
||||
@@ -585,32 +572,15 @@ describe('ProjectDeleter', function () {
|
||||
)
|
||||
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 () {
|
||||
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')
|
||||
.withArgs({ _id: this.project._id }, { $set: { archived } })
|
||||
.withArgs(
|
||||
{ _id: this.project._id },
|
||||
{ $pull: { archived: new ObjectId(this.user._id) } }
|
||||
)
|
||||
.resolves()
|
||||
})
|
||||
|
||||
@@ -621,36 +591,16 @@ describe('ProjectDeleter', function () {
|
||||
)
|
||||
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 () {
|
||||
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')
|
||||
.withArgs(
|
||||
{ _id: this.project._id },
|
||||
{
|
||||
$addToSet: { trashed: new ObjectId(this.user._id) },
|
||||
$set: { archived },
|
||||
$pull: { archived: new ObjectId(this.user._id) },
|
||||
}
|
||||
)
|
||||
.resolves()
|
||||
@@ -663,27 +613,10 @@ describe('ProjectDeleter', function () {
|
||||
)
|
||||
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 () {
|
||||
beforeEach(function () {
|
||||
this.ProjectMock.expects('findOne')
|
||||
.withArgs({ _id: this.project._id })
|
||||
.chain('exec')
|
||||
.resolves(this.project)
|
||||
|
||||
this.ProjectMock.expects('updateOne')
|
||||
.withArgs(
|
||||
{ _id: this.project._id },
|
||||
|
||||
@@ -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 () {
|
||||
it('returns the correct engine for latex_dvipdf', function () {
|
||||
expect(this.ProjectHelper.compilerFromV1Engine('latex_dvipdf')).to.equal(
|
||||
|
||||
Reference in New Issue
Block a user