mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #2618 from overleaf/ew-clear-root-doc-on-delete
Clear root doc on delete GitOrigin-RevId: 4121d198f5253417bca2284c5f750c088debcb8c
This commit is contained in:
parent
17969c50ce
commit
1da929fcdb
4 changed files with 154 additions and 60 deletions
|
@ -10,7 +10,6 @@
|
||||||
/*
|
/*
|
||||||
* decaffeinate suggestions:
|
* decaffeinate suggestions:
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
* DS102: Remove unnecessary code created because of implicit returns
|
||||||
* DS103: Rewrite code to no longer use __guard__
|
|
||||||
* DS207: Consider shorter variations of null checks
|
* DS207: Consider shorter variations of null checks
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||||
*/
|
*/
|
||||||
|
@ -35,59 +34,52 @@ const COMPILE_TIMEOUT_MS = 10 * 60 * 1000
|
||||||
|
|
||||||
module.exports = CompileController = {
|
module.exports = CompileController = {
|
||||||
compile(req, res, next) {
|
compile(req, res, next) {
|
||||||
if (next == null) {
|
|
||||||
next = function(error) {}
|
|
||||||
}
|
|
||||||
res.setTimeout(COMPILE_TIMEOUT_MS)
|
res.setTimeout(COMPILE_TIMEOUT_MS)
|
||||||
const project_id = req.params.Project_id
|
const project_id = req.params.Project_id
|
||||||
const isAutoCompile = !!(req.query != null
|
const isAutoCompile = !!req.query.auto_compile
|
||||||
? req.query.auto_compile
|
|
||||||
: undefined)
|
|
||||||
const user_id = AuthenticationController.getLoggedInUserId(req)
|
const user_id = AuthenticationController.getLoggedInUserId(req)
|
||||||
const options = {
|
const options = {
|
||||||
isAutoCompile
|
isAutoCompile
|
||||||
}
|
}
|
||||||
if ((req.body != null ? req.body.rootDoc_id : undefined) != null) {
|
|
||||||
|
if (req.body.rootDoc_id) {
|
||||||
options.rootDoc_id = req.body.rootDoc_id
|
options.rootDoc_id = req.body.rootDoc_id
|
||||||
} else if (
|
} else if (
|
||||||
__guard__(
|
req.body.settingsOverride &&
|
||||||
req.body != null ? req.body.settingsOverride : undefined,
|
req.body.settingsOverride.rootDoc_id
|
||||||
x => x.rootDoc_id
|
|
||||||
) != null
|
|
||||||
) {
|
) {
|
||||||
// Can be removed after deploy
|
// Can be removed after deploy
|
||||||
options.rootDoc_id = req.body.settingsOverride.rootDoc_id
|
options.rootDoc_id = req.body.settingsOverride.rootDoc_id
|
||||||
}
|
}
|
||||||
if (req.body != null ? req.body.compiler : undefined) {
|
if (req.body.compiler) {
|
||||||
options.compiler = req.body.compiler
|
options.compiler = req.body.compiler
|
||||||
}
|
}
|
||||||
if (req.body != null ? req.body.draft : undefined) {
|
if (req.body.draft) {
|
||||||
options.draft = req.body.draft
|
options.draft = req.body.draft
|
||||||
}
|
}
|
||||||
if (
|
if (['validate', 'error', 'silent'].includes(req.body.check)) {
|
||||||
['validate', 'error', 'silent'].includes(
|
|
||||||
req.body != null ? req.body.check : undefined
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
options.check = req.body.check
|
options.check = req.body.check
|
||||||
}
|
}
|
||||||
if (req.body != null ? req.body.incrementalCompilesEnabled : undefined) {
|
if (req.body.incrementalCompilesEnabled) {
|
||||||
options.incrementalCompilesEnabled = true
|
options.incrementalCompilesEnabled = true
|
||||||
}
|
}
|
||||||
return CompileManager.compile(project_id, user_id, options, function(
|
|
||||||
|
CompileManager.compile(
|
||||||
|
project_id,
|
||||||
|
user_id,
|
||||||
|
options,
|
||||||
|
(
|
||||||
error,
|
error,
|
||||||
status,
|
status,
|
||||||
outputFiles,
|
outputFiles,
|
||||||
clsiServerId,
|
clsiServerId,
|
||||||
limits,
|
limits,
|
||||||
validationProblems
|
validationProblems
|
||||||
) {
|
) => {
|
||||||
if (error != null) {
|
if (error) {
|
||||||
return next(error)
|
return next(error)
|
||||||
}
|
}
|
||||||
res.contentType('application/json')
|
res.json({
|
||||||
return res.status(200).send(
|
|
||||||
JSON.stringify({
|
|
||||||
status,
|
status,
|
||||||
outputFiles,
|
outputFiles,
|
||||||
compileGroup: limits != null ? limits.compileGroup : undefined,
|
compileGroup: limits != null ? limits.compileGroup : undefined,
|
||||||
|
@ -95,8 +87,8 @@ module.exports = CompileController = {
|
||||||
validationProblems,
|
validationProblems,
|
||||||
pdfDownloadDomain: Settings.pdfDownloadDomain
|
pdfDownloadDomain: Settings.pdfDownloadDomain
|
||||||
})
|
})
|
||||||
|
}
|
||||||
)
|
)
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
|
||||||
stopCompile(req, res, next) {
|
stopCompile(req, res, next) {
|
||||||
|
@ -540,9 +532,3 @@ module.exports = CompileController = {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function __guard__(value, transform) {
|
|
||||||
return typeof value !== 'undefined' && value !== null
|
|
||||||
? transform(value)
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
|
|
|
@ -314,8 +314,12 @@ async function moveEntity(projectId, entityId, destFolderId, entityType) {
|
||||||
async function deleteEntity(projectId, entityId, entityType, callback) {
|
async function deleteEntity(projectId, entityId, entityType, callback) {
|
||||||
const project = await ProjectGetter.promises.getProjectWithoutLock(
|
const project = await ProjectGetter.promises.getProjectWithoutLock(
|
||||||
projectId,
|
projectId,
|
||||||
{ name: true, rootFolder: true, overleaf: true }
|
{ name: true, rootFolder: true, overleaf: true, rootDoc_id: true }
|
||||||
)
|
)
|
||||||
|
const deleteRootDoc =
|
||||||
|
project.rootDoc_id &&
|
||||||
|
entityId &&
|
||||||
|
project.rootDoc_id.toString() === entityId.toString()
|
||||||
const { element: entity, path } = await ProjectLocator.promises.findElement({
|
const { element: entity, path } = await ProjectLocator.promises.findElement({
|
||||||
project,
|
project,
|
||||||
element_id: entityId,
|
element_id: entityId,
|
||||||
|
@ -325,7 +329,8 @@ async function deleteEntity(projectId, entityId, entityType, callback) {
|
||||||
Project,
|
Project,
|
||||||
projectId,
|
projectId,
|
||||||
path.mongo,
|
path.mongo,
|
||||||
entityId
|
entityId,
|
||||||
|
deleteRootDoc
|
||||||
)
|
)
|
||||||
return { entity, path, projectBeforeDeletion: project, newProject }
|
return { entity, path, projectBeforeDeletion: project, newProject }
|
||||||
}
|
}
|
||||||
|
@ -414,19 +419,24 @@ async function _insertDeletedFileReference(projectId, fileRef) {
|
||||||
).exec()
|
).exec()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _removeElementFromMongoArray(model, modelId, path, elementId) {
|
async function _removeElementFromMongoArray(
|
||||||
|
model,
|
||||||
|
modelId,
|
||||||
|
path,
|
||||||
|
elementId,
|
||||||
|
deleteRootDoc = false
|
||||||
|
) {
|
||||||
const nonArrayPath = path.slice(0, path.lastIndexOf('.'))
|
const nonArrayPath = path.slice(0, path.lastIndexOf('.'))
|
||||||
const newDoc = model
|
const options = { new: true }
|
||||||
.findOneAndUpdate(
|
const query = { _id: modelId }
|
||||||
{ _id: modelId },
|
const update = {
|
||||||
{
|
|
||||||
$pull: { [nonArrayPath]: { _id: elementId } },
|
$pull: { [nonArrayPath]: { _id: elementId } },
|
||||||
$inc: { version: 1 }
|
$inc: { version: 1 }
|
||||||
},
|
}
|
||||||
{ new: true }
|
if (deleteRootDoc) {
|
||||||
)
|
update.$unset = { rootDoc_id: 1 }
|
||||||
.exec()
|
}
|
||||||
return newDoc
|
return model.findOneAndUpdate(query, update, options).exec()
|
||||||
}
|
}
|
||||||
|
|
||||||
function _countElements(project) {
|
function _countElements(project) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ const fs = require('fs')
|
||||||
const Settings = require('settings-sharelatex')
|
const Settings = require('settings-sharelatex')
|
||||||
const _ = require('underscore')
|
const _ = require('underscore')
|
||||||
|
|
||||||
|
const { Project } = require('../../../app/src/models/Project')
|
||||||
const ProjectGetter = require('../../../app/src/Features/Project/ProjectGetter.js')
|
const ProjectGetter = require('../../../app/src/Features/Project/ProjectGetter.js')
|
||||||
|
|
||||||
const MockDocUpdaterApi = require('./helpers/MockDocUpdaterApi')
|
const MockDocUpdaterApi = require('./helpers/MockDocUpdaterApi')
|
||||||
|
@ -1098,6 +1099,105 @@ describe('ProjectStructureChanges', function() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('deleting docs', function() {
|
||||||
|
beforeEach(function(done) {
|
||||||
|
createExampleProject(owner, (err, projectId) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
this.exampleProjectId = projectId
|
||||||
|
createExampleFolder(owner, projectId, (err, folderId) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
this.exampleFolderId = folderId
|
||||||
|
createExampleDoc(owner, projectId, (err, docId) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
this.exampleDocId = docId
|
||||||
|
MockDocUpdaterApi.clearProjectStructureUpdates()
|
||||||
|
ProjectGetter.getProject(
|
||||||
|
this.exampleProjectId,
|
||||||
|
(error, project) => {
|
||||||
|
if (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
this.project0 = project
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('when rootDoc_id matches doc being deleted', function() {
|
||||||
|
beforeEach(function(done) {
|
||||||
|
Project.update(
|
||||||
|
{ _id: this.exampleProjectId },
|
||||||
|
{ $set: { rootDoc_id: this.exampleDocId } },
|
||||||
|
done
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should clear rootDoc_id', function(done) {
|
||||||
|
deleteItem(
|
||||||
|
owner,
|
||||||
|
this.exampleProjectId,
|
||||||
|
'doc',
|
||||||
|
this.exampleDocId,
|
||||||
|
() => {
|
||||||
|
ProjectGetter.getProject(
|
||||||
|
this.exampleProjectId,
|
||||||
|
(error, project) => {
|
||||||
|
if (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
expect(project.rootDoc_id).to.be.undefined
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('when rootDoc_id does not match doc being deleted', function() {
|
||||||
|
beforeEach(function(done) {
|
||||||
|
this.exampleRootDocId = new ObjectId()
|
||||||
|
Project.update(
|
||||||
|
{ _id: this.exampleProjectId },
|
||||||
|
{ $set: { rootDoc_id: this.exampleRootDocId } },
|
||||||
|
done
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not clear rootDoc_id', function(done) {
|
||||||
|
deleteItem(
|
||||||
|
owner,
|
||||||
|
this.exampleProjectId,
|
||||||
|
'doc',
|
||||||
|
this.exampleDocId,
|
||||||
|
() => {
|
||||||
|
ProjectGetter.getProject(
|
||||||
|
this.exampleProjectId,
|
||||||
|
(error, project) => {
|
||||||
|
if (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
expect(project.rootDoc_id.toString()).to.equal(
|
||||||
|
this.exampleRootDocId.toString()
|
||||||
|
)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('tpds', function() {
|
describe('tpds', function() {
|
||||||
let projectName, exampleProjectId, oldVersion, rootFolderId
|
let projectName, exampleProjectId, oldVersion, rootFolderId
|
||||||
|
|
||||||
|
|
|
@ -120,14 +120,12 @@ describe('CompileController', function() {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should set the content-type of the response to application/json', function() {
|
it('should set the content-type of the response to application/json', function() {
|
||||||
return this.res.contentType
|
this.res.type.should.equal('application/json')
|
||||||
.calledWith('application/json')
|
|
||||||
.should.equal(true)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should send a successful response reporting the status and files', function() {
|
it('should send a successful response reporting the status and files', function() {
|
||||||
this.res.statusCode.should.equal(200)
|
this.res.statusCode.should.equal(200)
|
||||||
return this.res.body.should.equal(
|
this.res.body.should.equal(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
status: this.status,
|
status: this.status,
|
||||||
outputFiles: this.outputFiles
|
outputFiles: this.outputFiles
|
||||||
|
|
Loading…
Reference in a new issue