mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Move functions to be promisified
Moving these first will make later commits have a cleaner diff. There are no substantive code changes in the moved functions. GitOrigin-RevId: 06e0c5bb02f300942c8fbe80e81484c4d717dbc9
This commit is contained in:
parent
10ef61a02b
commit
c4d7da87a6
1 changed files with 1270 additions and 1249 deletions
|
@ -154,10 +154,7 @@ function getDocContext(projectId, docId, callback) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProjectEntityUpdateHandler = {
|
function updateDocLines(
|
||||||
LOCK_NAMESPACE,
|
|
||||||
|
|
||||||
updateDocLines(
|
|
||||||
projectId,
|
projectId,
|
||||||
docId,
|
docId,
|
||||||
lines,
|
lines,
|
||||||
|
@ -180,10 +177,7 @@ const ProjectEntityUpdateHandler = {
|
||||||
return callback(err)
|
return callback(err)
|
||||||
}
|
}
|
||||||
const { projectName, isDeletedDoc, path, folder } = ctx
|
const { projectName, isDeletedDoc, path, folder } = ctx
|
||||||
logger.debug(
|
logger.debug({ projectId, docId }, 'telling docstore manager to update doc')
|
||||||
{ projectId, docId },
|
|
||||||
'telling docstore manager to update doc'
|
|
||||||
)
|
|
||||||
DocstoreManager.updateDoc(
|
DocstoreManager.updateDoc(
|
||||||
projectId,
|
projectId,
|
||||||
docId,
|
docId,
|
||||||
|
@ -231,9 +225,9 @@ const ProjectEntityUpdateHandler = {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
|
|
||||||
setRootDoc(projectId, newRootDocID, callback) {
|
function setRootDoc(projectId, newRootDocID, callback) {
|
||||||
logger.debug({ projectId, rootDocId: newRootDocID }, 'setting root doc')
|
logger.debug({ projectId, rootDocId: newRootDocID }, 'setting root doc')
|
||||||
if (projectId == null || newRootDocID == null) {
|
if (projectId == null || newRootDocID == null) {
|
||||||
return callback(
|
return callback(
|
||||||
|
@ -265,9 +259,9 @@ const ProjectEntityUpdateHandler = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
|
|
||||||
unsetRootDoc(projectId, callback) {
|
function unsetRootDoc(projectId, callback) {
|
||||||
logger.debug({ projectId }, 'removing root doc')
|
logger.debug({ projectId }, 'removing root doc')
|
||||||
// Ignore spurious floating promises warning until we promisify
|
// Ignore spurious floating promises warning until we promisify
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
@ -277,44 +271,17 @@ const ProjectEntityUpdateHandler = {
|
||||||
{},
|
{},
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
|
|
||||||
_addDocAndSendToTpds(projectId, folderId, doc, callback) {
|
function addDoc(
|
||||||
ProjectEntityMongoUpdateHandler.addDoc(
|
|
||||||
projectId,
|
projectId,
|
||||||
folderId,
|
folderId,
|
||||||
doc,
|
docName,
|
||||||
(err, result, project) => {
|
docLines,
|
||||||
if (err != null) {
|
userId,
|
||||||
OError.tag(err, 'error adding file with project', {
|
source,
|
||||||
projectId,
|
callback
|
||||||
folderId,
|
) {
|
||||||
doc_name: doc != null ? doc.name : undefined,
|
|
||||||
doc_id: doc != null ? doc._id : undefined,
|
|
||||||
})
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
TpdsUpdateSender.addDoc(
|
|
||||||
{
|
|
||||||
projectId,
|
|
||||||
docId: doc != null ? doc._id : undefined,
|
|
||||||
path: result?.path?.fileSystem,
|
|
||||||
projectName: project.name,
|
|
||||||
rev: 0,
|
|
||||||
folderId,
|
|
||||||
},
|
|
||||||
err => {
|
|
||||||
if (err != null) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
callback(null, result, project)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
addDoc(projectId, folderId, docName, docLines, userId, source, callback) {
|
|
||||||
ProjectEntityUpdateHandler.addDocWithRanges(
|
ProjectEntityUpdateHandler.addDocWithRanges(
|
||||||
projectId,
|
projectId,
|
||||||
folderId,
|
folderId,
|
||||||
|
@ -325,9 +292,9 @@ const ProjectEntityUpdateHandler = {
|
||||||
source,
|
source,
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
|
|
||||||
addDocWithRanges: wrapWithLock({
|
const addDocWithRanges = wrapWithLock({
|
||||||
beforeLock(next) {
|
beforeLock(next) {
|
||||||
return function (
|
return function (
|
||||||
projectId,
|
projectId,
|
||||||
|
@ -419,71 +386,9 @@ const ProjectEntityUpdateHandler = {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}),
|
|
||||||
|
|
||||||
_uploadFile(projectId, folderId, fileName, fsPath, linkedFileData, callback) {
|
|
||||||
if (!SafePath.isCleanFilename(fileName)) {
|
|
||||||
return callback(new Errors.InvalidNameError('invalid element name'))
|
|
||||||
}
|
|
||||||
const fileArgs = {
|
|
||||||
name: fileName,
|
|
||||||
linkedFileData,
|
|
||||||
}
|
|
||||||
FileStoreHandler.uploadFileFromDisk(
|
|
||||||
projectId,
|
|
||||||
fileArgs,
|
|
||||||
fsPath,
|
|
||||||
(err, fileStoreUrl, fileRef) => {
|
|
||||||
if (err != null) {
|
|
||||||
OError.tag(err, 'error uploading image to s3', {
|
|
||||||
projectId,
|
|
||||||
folderId,
|
|
||||||
file_name: fileName,
|
|
||||||
fileRef,
|
|
||||||
})
|
})
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
callback(null, fileStoreUrl, fileRef)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
_addFileAndSendToTpds(projectId, folderId, fileRef, callback) {
|
const addFile = wrapWithLock({
|
||||||
ProjectEntityMongoUpdateHandler.addFile(
|
|
||||||
projectId,
|
|
||||||
folderId,
|
|
||||||
fileRef,
|
|
||||||
(err, result, project) => {
|
|
||||||
if (err != null) {
|
|
||||||
OError.tag(err, 'error adding file with project', {
|
|
||||||
projectId,
|
|
||||||
folderId,
|
|
||||||
file_name: fileRef.name,
|
|
||||||
fileRef,
|
|
||||||
})
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
TpdsUpdateSender.addFile(
|
|
||||||
{
|
|
||||||
projectId,
|
|
||||||
fileId: fileRef._id,
|
|
||||||
path: result?.path?.fileSystem,
|
|
||||||
projectName: project.name,
|
|
||||||
rev: fileRef.rev,
|
|
||||||
folderId,
|
|
||||||
},
|
|
||||||
err => {
|
|
||||||
if (err != null) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
callback(null, result, project)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
addFile: wrapWithLock({
|
|
||||||
beforeLock(next) {
|
beforeLock(next) {
|
||||||
return function (
|
return function (
|
||||||
projectId,
|
projectId,
|
||||||
|
@ -576,93 +481,10 @@ const ProjectEntityUpdateHandler = {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}),
|
|
||||||
|
|
||||||
_replaceFile(
|
|
||||||
projectId,
|
|
||||||
fileId,
|
|
||||||
fsPath,
|
|
||||||
linkedFileData,
|
|
||||||
userId,
|
|
||||||
newFileRef,
|
|
||||||
fileStoreUrl,
|
|
||||||
folderId,
|
|
||||||
source,
|
|
||||||
callback
|
|
||||||
) {
|
|
||||||
ProjectEntityMongoUpdateHandler.replaceFileWithNew(
|
|
||||||
projectId,
|
|
||||||
fileId,
|
|
||||||
newFileRef,
|
|
||||||
(err, oldFileRef, project, path, newProject, newFileRef) => {
|
|
||||||
if (err != null) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
const oldFiles = [
|
|
||||||
{
|
|
||||||
file: oldFileRef,
|
|
||||||
path: path.fileSystem,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
const newFiles = [
|
|
||||||
{
|
|
||||||
file: newFileRef,
|
|
||||||
path: path.fileSystem,
|
|
||||||
url: fileStoreUrl,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
const projectHistoryId =
|
|
||||||
project.overleaf &&
|
|
||||||
project.overleaf.history &&
|
|
||||||
project.overleaf.history.id
|
|
||||||
TpdsUpdateSender.addFile(
|
|
||||||
{
|
|
||||||
projectId: project._id,
|
|
||||||
fileId: newFileRef._id,
|
|
||||||
path: path.fileSystem,
|
|
||||||
rev: newFileRef.rev,
|
|
||||||
projectName: project.name,
|
|
||||||
folderId,
|
|
||||||
},
|
|
||||||
err => {
|
|
||||||
if (err != null) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
ProjectUpdateHandler.promises
|
|
||||||
.markAsUpdated(projectId, new Date(), userId)
|
|
||||||
.catch(error => {
|
|
||||||
logger.error({ error }, 'failed to mark project as updated')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
DocumentUpdaterHandler.updateProjectStructure(
|
const upsertDoc = wrapWithLock(
|
||||||
projectId,
|
function (projectId, folderId, docName, docLines, source, userId, callback) {
|
||||||
projectHistoryId,
|
|
||||||
userId,
|
|
||||||
{ oldFiles, newFiles, newProject },
|
|
||||||
source,
|
|
||||||
err => {
|
|
||||||
if (err) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
callback(null, newFileRef)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
upsertDoc: wrapWithLock(
|
|
||||||
function (
|
|
||||||
projectId,
|
|
||||||
folderId,
|
|
||||||
docName,
|
|
||||||
docLines,
|
|
||||||
source,
|
|
||||||
userId,
|
|
||||||
callback
|
|
||||||
) {
|
|
||||||
if (!SafePath.isCleanFilename(docName)) {
|
if (!SafePath.isCleanFilename(docName)) {
|
||||||
return callback(new Errors.InvalidNameError('invalid element name'))
|
return callback(new Errors.InvalidNameError('invalid element name'))
|
||||||
}
|
}
|
||||||
|
@ -778,11 +600,7 @@ const ProjectEntityUpdateHandler = {
|
||||||
// flushes it as part of setDoc.
|
// flushes it as part of setDoc.
|
||||||
//
|
//
|
||||||
// combine rev from response with existing doc metadata
|
// combine rev from response with existing doc metadata
|
||||||
callback(
|
callback(null, { ...existingDoc, ...result }, existingDoc == null)
|
||||||
null,
|
|
||||||
{ ...existingDoc, ...result },
|
|
||||||
existingDoc == null
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -805,9 +623,9 @@ const ProjectEntityUpdateHandler = {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
),
|
)
|
||||||
|
|
||||||
upsertFile: wrapWithLock({
|
const upsertFile = wrapWithLock({
|
||||||
beforeLock(next) {
|
beforeLock(next) {
|
||||||
return function (
|
return function (
|
||||||
projectId,
|
projectId,
|
||||||
|
@ -995,9 +813,9 @@ const ProjectEntityUpdateHandler = {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
|
|
||||||
upsertDocWithPath: wrapWithLock(
|
const upsertDocWithPath = wrapWithLock(
|
||||||
function (projectId, elementPath, docLines, source, userId, callback) {
|
function (projectId, elementPath, docLines, source, userId, callback) {
|
||||||
if (!SafePath.isCleanPath(elementPath)) {
|
if (!SafePath.isCleanPath(elementPath)) {
|
||||||
return callback(new Errors.InvalidNameError('invalid element name'))
|
return callback(new Errors.InvalidNameError('invalid element name'))
|
||||||
|
@ -1028,9 +846,9 @@ const ProjectEntityUpdateHandler = {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
),
|
)
|
||||||
|
|
||||||
upsertFileWithPath: wrapWithLock({
|
const upsertFileWithPath = wrapWithLock({
|
||||||
beforeLock(next) {
|
beforeLock(next) {
|
||||||
return function (
|
return function (
|
||||||
projectId,
|
projectId,
|
||||||
|
@ -1109,27 +927,17 @@ const ProjectEntityUpdateHandler = {
|
||||||
if (err != null) {
|
if (err != null) {
|
||||||
return callback(err)
|
return callback(err)
|
||||||
}
|
}
|
||||||
callback(
|
callback(null, newFile, isNewFile, existingFile, newFolders, folder)
|
||||||
null,
|
|
||||||
newFile,
|
|
||||||
isNewFile,
|
|
||||||
existingFile,
|
|
||||||
newFolders,
|
|
||||||
folder
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
|
|
||||||
deleteEntity: wrapWithLock(
|
const deleteEntity = wrapWithLock(
|
||||||
function (projectId, entityId, entityType, userId, source, callback) {
|
function (projectId, entityId, entityType, userId, source, callback) {
|
||||||
logger.debug(
|
logger.debug({ entityId, entityType, projectId }, 'deleting project entity')
|
||||||
{ entityId, entityType, projectId },
|
|
||||||
'deleting project entity'
|
|
||||||
)
|
|
||||||
if (entityType == null) {
|
if (entityType == null) {
|
||||||
logger.warn({ err: 'No entityType set', projectId, entityId })
|
logger.warn({ err: 'No entityType set', projectId, entityId })
|
||||||
return callback(new Error('No entityType set'))
|
return callback(new Error('No entityType set'))
|
||||||
|
@ -1179,9 +987,9 @@ const ProjectEntityUpdateHandler = {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
),
|
)
|
||||||
|
|
||||||
deleteEntityWithPath: wrapWithLock(
|
const deleteEntityWithPath = wrapWithLock(
|
||||||
(projectId, path, userId, source, callback) =>
|
(projectId, path, userId, source, callback) =>
|
||||||
ProjectLocator.findElementByPath(
|
ProjectLocator.findElementByPath(
|
||||||
{ project_id: projectId, path, exactCaseMatch: true },
|
{ project_id: projectId, path, exactCaseMatch: true },
|
||||||
|
@ -1202,9 +1010,9 @@ const ProjectEntityUpdateHandler = {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
|
|
||||||
mkdirp: wrapWithLock(function (projectId, path, callback) {
|
const mkdirp = wrapWithLock(function (projectId, path, callback) {
|
||||||
for (const folder of path.split('/')) {
|
for (const folder of path.split('/')) {
|
||||||
if (folder.length > 0 && !SafePath.isCleanFilename(folder)) {
|
if (folder.length > 0 && !SafePath.isCleanFilename(folder)) {
|
||||||
return callback(new Errors.InvalidNameError('invalid element name'))
|
return callback(new Errors.InvalidNameError('invalid element name'))
|
||||||
|
@ -1216,9 +1024,9 @@ const ProjectEntityUpdateHandler = {
|
||||||
{ exactCaseMatch: false },
|
{ exactCaseMatch: false },
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
}),
|
})
|
||||||
|
|
||||||
mkdirpWithExactCase: wrapWithLock(function (projectId, path, callback) {
|
const mkdirpWithExactCase = wrapWithLock(function (projectId, path, callback) {
|
||||||
for (const folder of path.split('/')) {
|
for (const folder of path.split('/')) {
|
||||||
if (folder.length > 0 && !SafePath.isCleanFilename(folder)) {
|
if (folder.length > 0 && !SafePath.isCleanFilename(folder)) {
|
||||||
return callback(new Errors.InvalidNameError('invalid element name'))
|
return callback(new Errors.InvalidNameError('invalid element name'))
|
||||||
|
@ -1230,9 +1038,9 @@ const ProjectEntityUpdateHandler = {
|
||||||
{ exactCaseMatch: true },
|
{ exactCaseMatch: true },
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
}),
|
})
|
||||||
|
|
||||||
addFolder: wrapWithLock(
|
const addFolder = wrapWithLock(
|
||||||
function (projectId, parentFolderId, folderName, callback) {
|
function (projectId, parentFolderId, folderName, callback) {
|
||||||
if (!SafePath.isCleanFilename(folderName)) {
|
if (!SafePath.isCleanFilename(folderName)) {
|
||||||
return callback(new Errors.InvalidNameError('invalid element name'))
|
return callback(new Errors.InvalidNameError('invalid element name'))
|
||||||
|
@ -1244,9 +1052,9 @@ const ProjectEntityUpdateHandler = {
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
),
|
)
|
||||||
|
|
||||||
moveEntity: wrapWithLock(
|
const moveEntity = wrapWithLock(
|
||||||
function (
|
function (
|
||||||
projectId,
|
projectId,
|
||||||
entityId,
|
entityId,
|
||||||
|
@ -1311,9 +1119,9 @@ const ProjectEntityUpdateHandler = {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
),
|
)
|
||||||
|
|
||||||
renameEntity: wrapWithLock(
|
const renameEntity = wrapWithLock(
|
||||||
function (
|
function (
|
||||||
projectId,
|
projectId,
|
||||||
entityId,
|
entityId,
|
||||||
|
@ -1392,11 +1200,11 @@ const ProjectEntityUpdateHandler = {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
),
|
)
|
||||||
|
|
||||||
// This doesn't directly update project structure but we need to take the lock
|
// This doesn't directly update project structure, but we need to take the lock
|
||||||
// to prevent anything else being queued before the resync update
|
// to prevent anything else being queued before the resync update
|
||||||
resyncProjectHistory: wrapWithLock(
|
const resyncProjectHistory = wrapWithLock(
|
||||||
(projectId, opts, callback) =>
|
(projectId, opts, callback) =>
|
||||||
ProjectGetter.getProject(
|
ProjectGetter.getProject(
|
||||||
projectId,
|
projectId,
|
||||||
|
@ -1462,7 +1270,364 @@ const ProjectEntityUpdateHandler = {
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
LockManager.withTimeout(6 * 60) // use an extended lock for the resync operations
|
LockManager.withTimeout(6 * 60) // use an extended lock for the resync operations
|
||||||
),
|
)
|
||||||
|
|
||||||
|
const convertDocToFile = wrapWithLock({
|
||||||
|
beforeLock(next) {
|
||||||
|
return function (projectId, docId, userId, source, callback) {
|
||||||
|
DocumentUpdaterHandler.flushDocToMongo(projectId, docId, err => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
ProjectLocator.findElement(
|
||||||
|
{ project_id: projectId, element_id: docId, type: 'doc' },
|
||||||
|
(err, doc, path) => {
|
||||||
|
const docPath = path.fileSystem
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
DocstoreManager.getDoc(
|
||||||
|
projectId,
|
||||||
|
docId,
|
||||||
|
(err, docLines, rev, version, ranges) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
if (!_.isEmpty(ranges)) {
|
||||||
|
return callback(new Errors.DocHasRangesError({}))
|
||||||
|
}
|
||||||
|
DocumentUpdaterHandler.deleteDoc(projectId, docId, err => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
FileWriter.writeLinesToDisk(
|
||||||
|
projectId,
|
||||||
|
docLines,
|
||||||
|
(err, fsPath) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
FileStoreHandler.uploadFileFromDisk(
|
||||||
|
projectId,
|
||||||
|
{ name: doc.name, rev: rev + 1 },
|
||||||
|
fsPath,
|
||||||
|
(err, fileStoreUrl, fileRef) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
fs.unlink(fsPath, err => {
|
||||||
|
if (err) {
|
||||||
|
logger.warn(
|
||||||
|
{ err, path: fsPath },
|
||||||
|
'failed to clean up temporary file'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
next(
|
||||||
|
projectId,
|
||||||
|
doc,
|
||||||
|
docPath,
|
||||||
|
fileRef,
|
||||||
|
fileStoreUrl,
|
||||||
|
userId,
|
||||||
|
source,
|
||||||
|
callback
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
withLock(
|
||||||
|
projectId,
|
||||||
|
doc,
|
||||||
|
path,
|
||||||
|
fileRef,
|
||||||
|
fileStoreUrl,
|
||||||
|
userId,
|
||||||
|
source,
|
||||||
|
callback
|
||||||
|
) {
|
||||||
|
ProjectEntityMongoUpdateHandler.replaceDocWithFile(
|
||||||
|
projectId,
|
||||||
|
doc._id,
|
||||||
|
fileRef,
|
||||||
|
(err, project) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
const projectHistoryId =
|
||||||
|
project.overleaf &&
|
||||||
|
project.overleaf.history &&
|
||||||
|
project.overleaf.history.id
|
||||||
|
DocumentUpdaterHandler.updateProjectStructure(
|
||||||
|
projectId,
|
||||||
|
projectHistoryId,
|
||||||
|
userId,
|
||||||
|
{
|
||||||
|
oldDocs: [{ doc, path }],
|
||||||
|
newFiles: [{ file: fileRef, path, url: fileStoreUrl }],
|
||||||
|
newProject: project,
|
||||||
|
},
|
||||||
|
source,
|
||||||
|
err => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
ProjectLocator.findElement(
|
||||||
|
{
|
||||||
|
project_id: projectId,
|
||||||
|
element_id: fileRef._id,
|
||||||
|
type: 'file',
|
||||||
|
},
|
||||||
|
(err, element, path, folder) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
EditorRealTimeController.emitToRoom(
|
||||||
|
projectId,
|
||||||
|
'removeEntity',
|
||||||
|
doc._id,
|
||||||
|
'convertDocToFile'
|
||||||
|
)
|
||||||
|
EditorRealTimeController.emitToRoom(
|
||||||
|
projectId,
|
||||||
|
'reciveNewFile',
|
||||||
|
folder._id,
|
||||||
|
fileRef,
|
||||||
|
'convertDocToFile',
|
||||||
|
null,
|
||||||
|
userId
|
||||||
|
)
|
||||||
|
callback(null, fileRef)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const ProjectEntityUpdateHandler = {
|
||||||
|
LOCK_NAMESPACE,
|
||||||
|
|
||||||
|
addDoc,
|
||||||
|
|
||||||
|
addDocWithRanges,
|
||||||
|
|
||||||
|
addFile,
|
||||||
|
|
||||||
|
addFolder,
|
||||||
|
|
||||||
|
convertDocToFile,
|
||||||
|
|
||||||
|
deleteEntity,
|
||||||
|
|
||||||
|
deleteEntityWithPath,
|
||||||
|
|
||||||
|
mkdirp,
|
||||||
|
|
||||||
|
mkdirpWithExactCase,
|
||||||
|
|
||||||
|
moveEntity,
|
||||||
|
|
||||||
|
renameEntity,
|
||||||
|
|
||||||
|
resyncProjectHistory,
|
||||||
|
|
||||||
|
setRootDoc,
|
||||||
|
|
||||||
|
unsetRootDoc,
|
||||||
|
|
||||||
|
updateDocLines,
|
||||||
|
|
||||||
|
upsertDoc,
|
||||||
|
|
||||||
|
upsertDocWithPath,
|
||||||
|
|
||||||
|
upsertFile,
|
||||||
|
|
||||||
|
upsertFileWithPath,
|
||||||
|
|
||||||
|
_addDocAndSendToTpds(projectId, folderId, doc, callback) {
|
||||||
|
ProjectEntityMongoUpdateHandler.addDoc(
|
||||||
|
projectId,
|
||||||
|
folderId,
|
||||||
|
doc,
|
||||||
|
(err, result, project) => {
|
||||||
|
if (err != null) {
|
||||||
|
OError.tag(err, 'error adding file with project', {
|
||||||
|
projectId,
|
||||||
|
folderId,
|
||||||
|
doc_name: doc != null ? doc.name : undefined,
|
||||||
|
doc_id: doc != null ? doc._id : undefined,
|
||||||
|
})
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
TpdsUpdateSender.addDoc(
|
||||||
|
{
|
||||||
|
projectId,
|
||||||
|
docId: doc != null ? doc._id : undefined,
|
||||||
|
path: result?.path?.fileSystem,
|
||||||
|
projectName: project.name,
|
||||||
|
rev: 0,
|
||||||
|
folderId,
|
||||||
|
},
|
||||||
|
err => {
|
||||||
|
if (err != null) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
callback(null, result, project)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
_uploadFile(projectId, folderId, fileName, fsPath, linkedFileData, callback) {
|
||||||
|
if (!SafePath.isCleanFilename(fileName)) {
|
||||||
|
return callback(new Errors.InvalidNameError('invalid element name'))
|
||||||
|
}
|
||||||
|
const fileArgs = {
|
||||||
|
name: fileName,
|
||||||
|
linkedFileData,
|
||||||
|
}
|
||||||
|
FileStoreHandler.uploadFileFromDisk(
|
||||||
|
projectId,
|
||||||
|
fileArgs,
|
||||||
|
fsPath,
|
||||||
|
(err, fileStoreUrl, fileRef) => {
|
||||||
|
if (err != null) {
|
||||||
|
OError.tag(err, 'error uploading image to s3', {
|
||||||
|
projectId,
|
||||||
|
folderId,
|
||||||
|
file_name: fileName,
|
||||||
|
fileRef,
|
||||||
|
})
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
callback(null, fileStoreUrl, fileRef)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
_addFileAndSendToTpds(projectId, folderId, fileRef, callback) {
|
||||||
|
ProjectEntityMongoUpdateHandler.addFile(
|
||||||
|
projectId,
|
||||||
|
folderId,
|
||||||
|
fileRef,
|
||||||
|
(err, result, project) => {
|
||||||
|
if (err != null) {
|
||||||
|
OError.tag(err, 'error adding file with project', {
|
||||||
|
projectId,
|
||||||
|
folderId,
|
||||||
|
file_name: fileRef.name,
|
||||||
|
fileRef,
|
||||||
|
})
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
TpdsUpdateSender.addFile(
|
||||||
|
{
|
||||||
|
projectId,
|
||||||
|
fileId: fileRef._id,
|
||||||
|
path: result?.path?.fileSystem,
|
||||||
|
projectName: project.name,
|
||||||
|
rev: fileRef.rev,
|
||||||
|
folderId,
|
||||||
|
},
|
||||||
|
err => {
|
||||||
|
if (err != null) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
callback(null, result, project)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
_replaceFile(
|
||||||
|
projectId,
|
||||||
|
fileId,
|
||||||
|
fsPath,
|
||||||
|
linkedFileData,
|
||||||
|
userId,
|
||||||
|
newFileRef,
|
||||||
|
fileStoreUrl,
|
||||||
|
folderId,
|
||||||
|
source,
|
||||||
|
callback
|
||||||
|
) {
|
||||||
|
ProjectEntityMongoUpdateHandler.replaceFileWithNew(
|
||||||
|
projectId,
|
||||||
|
fileId,
|
||||||
|
newFileRef,
|
||||||
|
(err, oldFileRef, project, path, newProject, newFileRef) => {
|
||||||
|
if (err != null) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
const oldFiles = [
|
||||||
|
{
|
||||||
|
file: oldFileRef,
|
||||||
|
path: path.fileSystem,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
const newFiles = [
|
||||||
|
{
|
||||||
|
file: newFileRef,
|
||||||
|
path: path.fileSystem,
|
||||||
|
url: fileStoreUrl,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
const projectHistoryId =
|
||||||
|
project.overleaf &&
|
||||||
|
project.overleaf.history &&
|
||||||
|
project.overleaf.history.id
|
||||||
|
TpdsUpdateSender.addFile(
|
||||||
|
{
|
||||||
|
projectId: project._id,
|
||||||
|
fileId: newFileRef._id,
|
||||||
|
path: path.fileSystem,
|
||||||
|
rev: newFileRef.rev,
|
||||||
|
projectName: project.name,
|
||||||
|
folderId,
|
||||||
|
},
|
||||||
|
err => {
|
||||||
|
if (err != null) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
ProjectUpdateHandler.promises
|
||||||
|
.markAsUpdated(projectId, new Date(), userId)
|
||||||
|
.catch(error => {
|
||||||
|
logger.error({ error }, 'failed to mark project as updated')
|
||||||
|
})
|
||||||
|
|
||||||
|
DocumentUpdaterHandler.updateProjectStructure(
|
||||||
|
projectId,
|
||||||
|
projectHistoryId,
|
||||||
|
userId,
|
||||||
|
{ oldFiles, newFiles, newProject },
|
||||||
|
source,
|
||||||
|
err => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
callback(null, newFileRef)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
_checkFiletree(projectId, projectHistoryId, entities, callback) {
|
_checkFiletree(projectId, projectHistoryId, entities, callback) {
|
||||||
const adjustPathsAfterFolderRename = (oldPath, newPath) => {
|
const adjustPathsAfterFolderRename = (oldPath, newPath) => {
|
||||||
|
@ -1759,150 +1924,6 @@ const ProjectEntityUpdateHandler = {
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
convertDocToFile: wrapWithLock({
|
|
||||||
beforeLock(next) {
|
|
||||||
return function (projectId, docId, userId, source, callback) {
|
|
||||||
DocumentUpdaterHandler.flushDocToMongo(projectId, docId, err => {
|
|
||||||
if (err) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
ProjectLocator.findElement(
|
|
||||||
{ project_id: projectId, element_id: docId, type: 'doc' },
|
|
||||||
(err, doc, path) => {
|
|
||||||
const docPath = path.fileSystem
|
|
||||||
if (err) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
DocstoreManager.getDoc(
|
|
||||||
projectId,
|
|
||||||
docId,
|
|
||||||
(err, docLines, rev, version, ranges) => {
|
|
||||||
if (err) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
if (!_.isEmpty(ranges)) {
|
|
||||||
return callback(new Errors.DocHasRangesError({}))
|
|
||||||
}
|
|
||||||
DocumentUpdaterHandler.deleteDoc(projectId, docId, err => {
|
|
||||||
if (err) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
FileWriter.writeLinesToDisk(
|
|
||||||
projectId,
|
|
||||||
docLines,
|
|
||||||
(err, fsPath) => {
|
|
||||||
if (err) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
FileStoreHandler.uploadFileFromDisk(
|
|
||||||
projectId,
|
|
||||||
{ name: doc.name, rev: rev + 1 },
|
|
||||||
fsPath,
|
|
||||||
(err, fileStoreUrl, fileRef) => {
|
|
||||||
if (err) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
fs.unlink(fsPath, err => {
|
|
||||||
if (err) {
|
|
||||||
logger.warn(
|
|
||||||
{ err, path: fsPath },
|
|
||||||
'failed to clean up temporary file'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
next(
|
|
||||||
projectId,
|
|
||||||
doc,
|
|
||||||
docPath,
|
|
||||||
fileRef,
|
|
||||||
fileStoreUrl,
|
|
||||||
userId,
|
|
||||||
source,
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
withLock(
|
|
||||||
projectId,
|
|
||||||
doc,
|
|
||||||
path,
|
|
||||||
fileRef,
|
|
||||||
fileStoreUrl,
|
|
||||||
userId,
|
|
||||||
source,
|
|
||||||
callback
|
|
||||||
) {
|
|
||||||
ProjectEntityMongoUpdateHandler.replaceDocWithFile(
|
|
||||||
projectId,
|
|
||||||
doc._id,
|
|
||||||
fileRef,
|
|
||||||
(err, project) => {
|
|
||||||
if (err) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
const projectHistoryId =
|
|
||||||
project.overleaf &&
|
|
||||||
project.overleaf.history &&
|
|
||||||
project.overleaf.history.id
|
|
||||||
DocumentUpdaterHandler.updateProjectStructure(
|
|
||||||
projectId,
|
|
||||||
projectHistoryId,
|
|
||||||
userId,
|
|
||||||
{
|
|
||||||
oldDocs: [{ doc, path }],
|
|
||||||
newFiles: [{ file: fileRef, path, url: fileStoreUrl }],
|
|
||||||
newProject: project,
|
|
||||||
},
|
|
||||||
source,
|
|
||||||
err => {
|
|
||||||
if (err) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
ProjectLocator.findElement(
|
|
||||||
{
|
|
||||||
project_id: projectId,
|
|
||||||
element_id: fileRef._id,
|
|
||||||
type: 'file',
|
|
||||||
},
|
|
||||||
(err, element, path, folder) => {
|
|
||||||
if (err) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
EditorRealTimeController.emitToRoom(
|
|
||||||
projectId,
|
|
||||||
'removeEntity',
|
|
||||||
doc._id,
|
|
||||||
'convertDocToFile'
|
|
||||||
)
|
|
||||||
EditorRealTimeController.emitToRoom(
|
|
||||||
projectId,
|
|
||||||
'reciveNewFile',
|
|
||||||
folder._id,
|
|
||||||
fileRef,
|
|
||||||
'convertDocToFile',
|
|
||||||
null,
|
|
||||||
userId
|
|
||||||
)
|
|
||||||
callback(null, fileRef)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue