mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-29 20:11:32 +02:00
Sync folder creation from Dropbox to Overleaf GitOrigin-RevId: a2749ab8d9db7dd312818b46d6e72f1dbaaaff2e
662 lines
15 KiB
JavaScript
662 lines
15 KiB
JavaScript
const logger = require('@overleaf/logger')
|
|
const OError = require('@overleaf/o-error')
|
|
const Metrics = require('@overleaf/metrics')
|
|
const ProjectEntityUpdateHandler = require('../Project/ProjectEntityUpdateHandler')
|
|
const ProjectOptionsHandler = require('../Project/ProjectOptionsHandler')
|
|
const ProjectDetailsHandler = require('../Project/ProjectDetailsHandler')
|
|
const ProjectDeleter = require('../Project/ProjectDeleter')
|
|
const EditorRealTimeController = require('./EditorRealTimeController')
|
|
const async = require('async')
|
|
const PublicAccessLevels = require('../Authorization/PublicAccessLevels')
|
|
const { promisifyAll } = require('../../util/promises')
|
|
|
|
const EditorController = {
|
|
addDoc(projectId, folderId, docName, docLines, source, userId, callback) {
|
|
EditorController.addDocWithRanges(
|
|
projectId,
|
|
folderId,
|
|
docName,
|
|
docLines,
|
|
{},
|
|
source,
|
|
userId,
|
|
callback
|
|
)
|
|
},
|
|
|
|
addDocWithRanges(
|
|
projectId,
|
|
folderId,
|
|
docName,
|
|
docLines,
|
|
docRanges,
|
|
source,
|
|
userId,
|
|
callback
|
|
) {
|
|
docName = docName.trim()
|
|
Metrics.inc('editor.add-doc')
|
|
ProjectEntityUpdateHandler.addDocWithRanges(
|
|
projectId,
|
|
folderId,
|
|
docName,
|
|
docLines,
|
|
docRanges,
|
|
userId,
|
|
source,
|
|
(err, doc, folderId) => {
|
|
if (err) {
|
|
OError.tag(err, 'error adding doc without lock', {
|
|
projectId,
|
|
docName,
|
|
})
|
|
return callback(err)
|
|
}
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'reciveNewDoc',
|
|
folderId,
|
|
doc,
|
|
source,
|
|
userId
|
|
)
|
|
callback(err, doc)
|
|
}
|
|
)
|
|
},
|
|
|
|
addFile(
|
|
projectId,
|
|
folderId,
|
|
fileName,
|
|
fsPath,
|
|
linkedFileData,
|
|
source,
|
|
userId,
|
|
callback
|
|
) {
|
|
fileName = fileName.trim()
|
|
Metrics.inc('editor.add-file')
|
|
ProjectEntityUpdateHandler.addFile(
|
|
projectId,
|
|
folderId,
|
|
fileName,
|
|
fsPath,
|
|
linkedFileData,
|
|
userId,
|
|
source,
|
|
(err, fileRef, folderId) => {
|
|
if (err) {
|
|
OError.tag(err, 'error adding file without lock', {
|
|
projectId,
|
|
folderId,
|
|
fileName,
|
|
})
|
|
return callback(err)
|
|
}
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'reciveNewFile',
|
|
folderId,
|
|
fileRef,
|
|
source,
|
|
linkedFileData,
|
|
userId
|
|
)
|
|
callback(err, fileRef)
|
|
}
|
|
)
|
|
},
|
|
|
|
upsertDoc(projectId, folderId, docName, docLines, source, userId, callback) {
|
|
ProjectEntityUpdateHandler.upsertDoc(
|
|
projectId,
|
|
folderId,
|
|
docName,
|
|
docLines,
|
|
source,
|
|
userId,
|
|
function (err, doc, didAddNewDoc) {
|
|
if (didAddNewDoc) {
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'reciveNewDoc',
|
|
folderId,
|
|
doc,
|
|
source,
|
|
userId
|
|
)
|
|
}
|
|
callback(err, doc)
|
|
}
|
|
)
|
|
},
|
|
|
|
upsertFile(
|
|
projectId,
|
|
folderId,
|
|
fileName,
|
|
fsPath,
|
|
linkedFileData,
|
|
source,
|
|
userId,
|
|
callback
|
|
) {
|
|
ProjectEntityUpdateHandler.upsertFile(
|
|
projectId,
|
|
folderId,
|
|
fileName,
|
|
fsPath,
|
|
linkedFileData,
|
|
userId,
|
|
source,
|
|
function (err, newFile, didAddFile, existingFile) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
if (!didAddFile) {
|
|
// replacement, so remove the existing file from the client
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'removeEntity',
|
|
existingFile._id,
|
|
source
|
|
)
|
|
}
|
|
// now add the new file on the client
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'reciveNewFile',
|
|
folderId,
|
|
newFile,
|
|
source,
|
|
linkedFileData,
|
|
userId
|
|
)
|
|
callback(null, newFile)
|
|
}
|
|
)
|
|
},
|
|
|
|
upsertDocWithPath(
|
|
projectId,
|
|
elementPath,
|
|
docLines,
|
|
source,
|
|
userId,
|
|
callback
|
|
) {
|
|
ProjectEntityUpdateHandler.upsertDocWithPath(
|
|
projectId,
|
|
elementPath,
|
|
docLines,
|
|
source,
|
|
userId,
|
|
function (err, doc, didAddNewDoc, newFolders, lastFolder) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
EditorController._notifyProjectUsersOfNewFolders(
|
|
projectId,
|
|
newFolders,
|
|
function (err) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
if (didAddNewDoc) {
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'reciveNewDoc',
|
|
lastFolder._id,
|
|
doc,
|
|
source,
|
|
userId
|
|
)
|
|
}
|
|
callback(null, { doc, folder: lastFolder })
|
|
}
|
|
)
|
|
}
|
|
)
|
|
},
|
|
|
|
upsertFileWithPath(
|
|
projectId,
|
|
elementPath,
|
|
fsPath,
|
|
linkedFileData,
|
|
source,
|
|
userId,
|
|
callback
|
|
) {
|
|
ProjectEntityUpdateHandler.upsertFileWithPath(
|
|
projectId,
|
|
elementPath,
|
|
fsPath,
|
|
linkedFileData,
|
|
userId,
|
|
source,
|
|
function (
|
|
err,
|
|
newFile,
|
|
didAddFile,
|
|
existingFile,
|
|
newFolders,
|
|
lastFolder
|
|
) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
EditorController._notifyProjectUsersOfNewFolders(
|
|
projectId,
|
|
newFolders,
|
|
function (err) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
if (!didAddFile) {
|
|
// replacement, so remove the existing file from the client
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'removeEntity',
|
|
existingFile._id,
|
|
source
|
|
)
|
|
}
|
|
// now add the new file on the client
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'reciveNewFile',
|
|
lastFolder._id,
|
|
newFile,
|
|
source,
|
|
linkedFileData,
|
|
userId
|
|
)
|
|
callback(null, { file: newFile, folder: lastFolder })
|
|
}
|
|
)
|
|
}
|
|
)
|
|
},
|
|
|
|
addFolder(projectId, folderId, folderName, source, userId, callback) {
|
|
folderName = folderName.trim()
|
|
Metrics.inc('editor.add-folder')
|
|
ProjectEntityUpdateHandler.addFolder(
|
|
projectId,
|
|
folderId,
|
|
folderName,
|
|
(err, folder, folderId) => {
|
|
if (err) {
|
|
OError.tag(err, 'could not add folder', {
|
|
projectId,
|
|
folderId,
|
|
folderName,
|
|
source,
|
|
})
|
|
return callback(err)
|
|
}
|
|
EditorController._notifyProjectUsersOfNewFolder(
|
|
projectId,
|
|
folderId,
|
|
folder,
|
|
userId,
|
|
function (err) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
callback(null, folder)
|
|
}
|
|
)
|
|
}
|
|
)
|
|
},
|
|
|
|
mkdirp(projectId, path, callback) {
|
|
logger.debug({ projectId, path }, "making directories if they don't exist")
|
|
ProjectEntityUpdateHandler.mkdirp(
|
|
projectId,
|
|
path,
|
|
(err, newFolders, lastFolder) => {
|
|
if (err) {
|
|
OError.tag(err, 'could not mkdirp', {
|
|
projectId,
|
|
path,
|
|
})
|
|
return callback(err)
|
|
}
|
|
|
|
EditorController._notifyProjectUsersOfNewFolders(
|
|
projectId,
|
|
newFolders,
|
|
function (err) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
callback(null, newFolders, lastFolder)
|
|
}
|
|
)
|
|
}
|
|
)
|
|
},
|
|
|
|
deleteEntity(projectId, entityId, entityType, source, userId, callback) {
|
|
Metrics.inc('editor.delete-entity')
|
|
ProjectEntityUpdateHandler.deleteEntity(
|
|
projectId,
|
|
entityId,
|
|
entityType,
|
|
userId,
|
|
source,
|
|
function (err) {
|
|
if (err) {
|
|
OError.tag(err, 'could not delete entity', {
|
|
projectId,
|
|
entityId,
|
|
entityType,
|
|
})
|
|
return callback(err)
|
|
}
|
|
logger.debug(
|
|
{ projectId, entityId, entityType },
|
|
'telling users entity has been deleted'
|
|
)
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'removeEntity',
|
|
entityId,
|
|
source
|
|
)
|
|
callback()
|
|
}
|
|
)
|
|
},
|
|
|
|
deleteEntityWithPath(projectId, path, source, userId, callback) {
|
|
ProjectEntityUpdateHandler.deleteEntityWithPath(
|
|
projectId,
|
|
path,
|
|
userId,
|
|
source,
|
|
function (err, entityId) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'removeEntity',
|
|
entityId,
|
|
source
|
|
)
|
|
callback(null, entityId)
|
|
}
|
|
)
|
|
},
|
|
|
|
updateProjectDescription(projectId, description, callback) {
|
|
logger.debug({ projectId, description }, 'updating project description')
|
|
ProjectDetailsHandler.setProjectDescription(
|
|
projectId,
|
|
description,
|
|
function (err) {
|
|
if (err) {
|
|
OError.tag(
|
|
err,
|
|
'something went wrong setting the project description',
|
|
{
|
|
projectId,
|
|
description,
|
|
}
|
|
)
|
|
return callback(err)
|
|
}
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'projectDescriptionUpdated',
|
|
description
|
|
)
|
|
callback()
|
|
}
|
|
)
|
|
},
|
|
|
|
deleteProject(projectId, callback) {
|
|
Metrics.inc('editor.delete-project')
|
|
ProjectDeleter.deleteProject(projectId, callback)
|
|
},
|
|
|
|
renameEntity(
|
|
projectId,
|
|
entityId,
|
|
entityType,
|
|
newName,
|
|
userId,
|
|
source,
|
|
callback
|
|
) {
|
|
Metrics.inc('editor.rename-entity')
|
|
ProjectEntityUpdateHandler.renameEntity(
|
|
projectId,
|
|
entityId,
|
|
entityType,
|
|
newName,
|
|
userId,
|
|
source,
|
|
function (err) {
|
|
if (err) {
|
|
OError.tag(err, 'error renaming entity', {
|
|
projectId,
|
|
entityId,
|
|
entityType,
|
|
newName,
|
|
})
|
|
return callback(err)
|
|
}
|
|
if (newName.length > 0) {
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'reciveEntityRename',
|
|
entityId,
|
|
newName
|
|
)
|
|
}
|
|
callback()
|
|
}
|
|
)
|
|
},
|
|
|
|
moveEntity(
|
|
projectId,
|
|
entityId,
|
|
folderId,
|
|
entityType,
|
|
userId,
|
|
source,
|
|
callback
|
|
) {
|
|
Metrics.inc('editor.move-entity')
|
|
ProjectEntityUpdateHandler.moveEntity(
|
|
projectId,
|
|
entityId,
|
|
folderId,
|
|
entityType,
|
|
userId,
|
|
source,
|
|
function (err) {
|
|
if (err) {
|
|
OError.tag(err, 'error moving entity', {
|
|
projectId,
|
|
entityId,
|
|
folderId,
|
|
})
|
|
return callback(err)
|
|
}
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'reciveEntityMove',
|
|
entityId,
|
|
folderId
|
|
)
|
|
callback()
|
|
}
|
|
)
|
|
},
|
|
|
|
renameProject(projectId, newName, callback) {
|
|
ProjectDetailsHandler.renameProject(projectId, newName, function (err) {
|
|
if (err) {
|
|
OError.tag(err, 'error renaming project', {
|
|
projectId,
|
|
newName,
|
|
})
|
|
return callback(err)
|
|
}
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'projectNameUpdated',
|
|
newName
|
|
)
|
|
callback()
|
|
})
|
|
},
|
|
|
|
setCompiler(projectId, compiler, callback) {
|
|
ProjectOptionsHandler.setCompiler(projectId, compiler, function (err) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'compilerUpdated',
|
|
compiler
|
|
)
|
|
callback()
|
|
})
|
|
},
|
|
|
|
setImageName(projectId, imageName, callback) {
|
|
ProjectOptionsHandler.setImageName(projectId, imageName, function (err) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'imageNameUpdated',
|
|
imageName
|
|
)
|
|
callback()
|
|
})
|
|
},
|
|
|
|
setSpellCheckLanguage(projectId, languageCode, callback) {
|
|
ProjectOptionsHandler.setSpellCheckLanguage(
|
|
projectId,
|
|
languageCode,
|
|
function (err) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'spellCheckLanguageUpdated',
|
|
languageCode
|
|
)
|
|
callback()
|
|
}
|
|
)
|
|
},
|
|
|
|
setPublicAccessLevel(projectId, newAccessLevel, callback) {
|
|
ProjectDetailsHandler.setPublicAccessLevel(
|
|
projectId,
|
|
newAccessLevel,
|
|
function (err) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'project:publicAccessLevel:changed',
|
|
{ newAccessLevel }
|
|
)
|
|
if (newAccessLevel === PublicAccessLevels.TOKEN_BASED) {
|
|
ProjectDetailsHandler.ensureTokensArePresent(
|
|
projectId,
|
|
function (err, tokens) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'project:tokens:changed',
|
|
{ tokens }
|
|
)
|
|
callback()
|
|
}
|
|
)
|
|
} else {
|
|
callback()
|
|
}
|
|
}
|
|
)
|
|
},
|
|
|
|
setRootDoc(projectId, newRootDocID, callback) {
|
|
ProjectEntityUpdateHandler.setRootDoc(
|
|
projectId,
|
|
newRootDocID,
|
|
function (err) {
|
|
if (err) {
|
|
return callback(err)
|
|
}
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'rootDocUpdated',
|
|
newRootDocID
|
|
)
|
|
callback()
|
|
}
|
|
)
|
|
},
|
|
|
|
_notifyProjectUsersOfNewFolders(projectId, folders, callback) {
|
|
async.eachSeries(
|
|
folders,
|
|
(folder, cb) =>
|
|
EditorController._notifyProjectUsersOfNewFolder(
|
|
projectId,
|
|
folder.parentFolder_id,
|
|
folder,
|
|
null,
|
|
cb
|
|
),
|
|
callback
|
|
)
|
|
},
|
|
|
|
_notifyProjectUsersOfNewFolder(
|
|
projectId,
|
|
folderId,
|
|
folder,
|
|
userId,
|
|
callback
|
|
) {
|
|
EditorRealTimeController.emitToRoom(
|
|
projectId,
|
|
'reciveNewFolder',
|
|
folderId,
|
|
folder,
|
|
userId
|
|
)
|
|
callback()
|
|
},
|
|
}
|
|
|
|
EditorController.promises = promisifyAll(EditorController, {
|
|
multiResult: {
|
|
mkdirp: ['newFolders', 'lastFolder'],
|
|
},
|
|
})
|
|
module.exports = EditorController
|