2019-05-29 05:21:06 -04:00
|
|
|
/* eslint-disable
|
|
|
|
camelcase,
|
|
|
|
handle-callback-err,
|
|
|
|
max-len,
|
|
|
|
no-unused-vars,
|
|
|
|
*/
|
|
|
|
// TODO: This file was created by bulk-decaffeinate.
|
|
|
|
// Fix any style issues and re-enable lint.
|
|
|
|
/*
|
|
|
|
* decaffeinate suggestions:
|
|
|
|
* DS101: Remove unnecessary use of Array.from
|
|
|
|
* DS102: Remove unnecessary code created because of implicit returns
|
|
|
|
* DS205: Consider reworking code to avoid use of IIFEs
|
|
|
|
* DS207: Consider shorter variations of null checks
|
|
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
|
|
*/
|
|
|
|
const _ = require('underscore')
|
|
|
|
const async = require('async')
|
|
|
|
const path = require('path')
|
|
|
|
const logger = require('logger-sharelatex')
|
|
|
|
const DocstoreManager = require('../Docstore/DocstoreManager')
|
|
|
|
const DocumentUpdaterHandler = require('../../Features/DocumentUpdater/DocumentUpdaterHandler')
|
|
|
|
const Errors = require('../Errors/Errors')
|
|
|
|
const { Project } = require('../../models/Project')
|
|
|
|
const ProjectGetter = require('./ProjectGetter')
|
|
|
|
const TpdsUpdateSender = require('../ThirdPartyDataStore/TpdsUpdateSender')
|
2019-09-09 07:52:25 -04:00
|
|
|
const { promisifyAll } = require('../../util/promises')
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2019-09-09 07:52:25 -04:00
|
|
|
const ProjectEntityHandler = {
|
2019-05-29 05:21:06 -04:00
|
|
|
getAllDocs(project_id, callback) {
|
|
|
|
logger.log({ project_id }, 'getting all docs for project')
|
|
|
|
|
|
|
|
// We get the path and name info from the project, and the lines and
|
|
|
|
// version info from the doc store.
|
|
|
|
return DocstoreManager.getAllDocs(project_id, function(
|
|
|
|
error,
|
|
|
|
docContentsArray
|
|
|
|
) {
|
|
|
|
if (error != null) {
|
|
|
|
return callback(error)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn array from docstore into a dictionary based on doc id
|
|
|
|
const docContents = {}
|
|
|
|
for (let docContent of Array.from(docContentsArray)) {
|
|
|
|
docContents[docContent._id] = docContent
|
|
|
|
}
|
|
|
|
|
2019-09-09 07:52:25 -04:00
|
|
|
return ProjectEntityHandler._getAllFolders(project_id, function(
|
|
|
|
error,
|
|
|
|
folders
|
|
|
|
) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (folders == null) {
|
|
|
|
folders = {}
|
|
|
|
}
|
|
|
|
if (error != null) {
|
|
|
|
return callback(error)
|
|
|
|
}
|
|
|
|
const docs = {}
|
|
|
|
for (let folderPath in folders) {
|
|
|
|
const folder = folders[folderPath]
|
|
|
|
for (let doc of Array.from(folder.docs || [])) {
|
|
|
|
const content = docContents[doc._id.toString()]
|
|
|
|
if (content != null) {
|
|
|
|
docs[path.join(folderPath, doc.name)] = {
|
|
|
|
_id: doc._id,
|
|
|
|
name: doc.name,
|
|
|
|
lines: content.lines,
|
|
|
|
rev: content.rev
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
logger.log(
|
|
|
|
{ count: _.keys(docs).length, project_id },
|
|
|
|
'returning docs for project'
|
|
|
|
)
|
|
|
|
return callback(null, docs)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
getAllFiles(project_id, callback) {
|
|
|
|
logger.log({ project_id }, 'getting all files for project')
|
2019-09-09 07:52:25 -04:00
|
|
|
return ProjectEntityHandler._getAllFolders(project_id, function(
|
|
|
|
err,
|
|
|
|
folders
|
|
|
|
) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (folders == null) {
|
|
|
|
folders = {}
|
|
|
|
}
|
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
const files = {}
|
|
|
|
for (let folderPath in folders) {
|
|
|
|
const folder = folders[folderPath]
|
|
|
|
for (let file of Array.from(folder.fileRefs || [])) {
|
|
|
|
if (file != null) {
|
|
|
|
files[path.join(folderPath, file.name)] = file
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return callback(null, files)
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
getAllEntities(project_id, callback) {
|
|
|
|
return ProjectGetter.getProject(project_id, function(err, project) {
|
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
2019-09-11 07:05:30 -04:00
|
|
|
if (project == null) {
|
|
|
|
return callback(new Errors.NotFoundError('project not found'))
|
|
|
|
}
|
|
|
|
|
2019-09-09 07:52:25 -04:00
|
|
|
return ProjectEntityHandler.getAllEntitiesFromProject(project, callback)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
getAllEntitiesFromProject(project, callback) {
|
|
|
|
logger.log({ project }, 'getting all entities for project')
|
2019-09-09 07:52:25 -04:00
|
|
|
return ProjectEntityHandler._getAllFoldersFromProject(project, function(
|
|
|
|
err,
|
|
|
|
folders
|
|
|
|
) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (folders == null) {
|
|
|
|
folders = {}
|
|
|
|
}
|
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
const docs = []
|
|
|
|
const files = []
|
|
|
|
for (let folderPath in folders) {
|
|
|
|
const folder = folders[folderPath]
|
|
|
|
for (let doc of Array.from(folder.docs || [])) {
|
|
|
|
if (doc != null) {
|
|
|
|
docs.push({ path: path.join(folderPath, doc.name), doc })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (let file of Array.from(folder.fileRefs || [])) {
|
|
|
|
if (file != null) {
|
|
|
|
files.push({ path: path.join(folderPath, file.name), file })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return callback(null, docs, files)
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
getAllDocPathsFromProjectById(project_id, callback) {
|
|
|
|
return ProjectGetter.getProjectWithoutDocLines(project_id, function(
|
|
|
|
err,
|
|
|
|
project
|
|
|
|
) {
|
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
if (project == null) {
|
|
|
|
return callback(Errors.NotFoundError('no project'))
|
|
|
|
}
|
2019-09-09 07:52:25 -04:00
|
|
|
return ProjectEntityHandler.getAllDocPathsFromProject(project, callback)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
getAllDocPathsFromProject(project, callback) {
|
|
|
|
logger.log({ project }, 'getting all docs for project')
|
2019-09-09 07:52:25 -04:00
|
|
|
return ProjectEntityHandler._getAllFoldersFromProject(project, function(
|
|
|
|
err,
|
|
|
|
folders
|
|
|
|
) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (folders == null) {
|
|
|
|
folders = {}
|
|
|
|
}
|
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
const docPath = {}
|
|
|
|
for (let folderPath in folders) {
|
|
|
|
const folder = folders[folderPath]
|
|
|
|
for (let doc of Array.from(folder.docs || [])) {
|
|
|
|
docPath[doc._id] = path.join(folderPath, doc.name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
logger.log(
|
|
|
|
{ count: _.keys(docPath).length, project_id: project._id },
|
|
|
|
'returning docPaths for project'
|
|
|
|
)
|
|
|
|
return callback(null, docPath)
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
flushProjectToThirdPartyDataStore(project_id, callback) {
|
|
|
|
logger.log({ project_id }, 'flushing project to tpds')
|
|
|
|
return DocumentUpdaterHandler.flushProjectToMongo(project_id, function(
|
|
|
|
error
|
|
|
|
) {
|
|
|
|
if (error != null) {
|
|
|
|
return callback(error)
|
|
|
|
}
|
|
|
|
return ProjectGetter.getProject(project_id, { name: true }, function(
|
|
|
|
error,
|
|
|
|
project
|
|
|
|
) {
|
|
|
|
if (error != null) {
|
|
|
|
return callback(error)
|
|
|
|
}
|
|
|
|
const requests = []
|
2019-09-09 07:52:25 -04:00
|
|
|
return ProjectEntityHandler.getAllDocs(project_id, function(
|
|
|
|
error,
|
|
|
|
docs
|
|
|
|
) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (error != null) {
|
|
|
|
return callback(error)
|
|
|
|
}
|
|
|
|
for (let docPath in docs) {
|
|
|
|
const doc = docs[docPath]
|
|
|
|
;((docPath, doc) =>
|
|
|
|
requests.push(cb =>
|
|
|
|
TpdsUpdateSender.addDoc(
|
|
|
|
{
|
|
|
|
project_id,
|
|
|
|
doc_id: doc._id,
|
|
|
|
path: docPath,
|
|
|
|
project_name: project.name,
|
|
|
|
rev: doc.rev || 0
|
|
|
|
},
|
|
|
|
cb
|
|
|
|
)
|
|
|
|
))(docPath, doc)
|
|
|
|
}
|
2019-09-09 07:52:25 -04:00
|
|
|
return ProjectEntityHandler.getAllFiles(project_id, function(
|
|
|
|
error,
|
|
|
|
files
|
|
|
|
) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (error != null) {
|
|
|
|
return callback(error)
|
|
|
|
}
|
|
|
|
for (let filePath in files) {
|
|
|
|
const file = files[filePath]
|
|
|
|
;((filePath, file) =>
|
|
|
|
requests.push(cb =>
|
|
|
|
TpdsUpdateSender.addFile(
|
|
|
|
{
|
|
|
|
project_id,
|
|
|
|
file_id: file._id,
|
|
|
|
path: filePath,
|
|
|
|
project_name: project.name,
|
|
|
|
rev: file.rev
|
|
|
|
},
|
|
|
|
cb
|
|
|
|
)
|
|
|
|
))(filePath, file)
|
|
|
|
}
|
|
|
|
return async.series(requests, function(err) {
|
|
|
|
logger.log({ project_id }, 'finished flushing project to tpds')
|
|
|
|
return callback(err)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
getDoc(project_id, doc_id, options, callback) {
|
|
|
|
if (options == null) {
|
|
|
|
options = {}
|
|
|
|
}
|
|
|
|
if (callback == null) {
|
|
|
|
callback = function(error, lines, rev) {}
|
|
|
|
}
|
|
|
|
if (typeof options === 'function') {
|
|
|
|
callback = options
|
|
|
|
options = {}
|
|
|
|
}
|
|
|
|
|
|
|
|
return DocstoreManager.getDoc(project_id, doc_id, options, callback)
|
|
|
|
},
|
|
|
|
|
2019-10-03 10:10:00 -04:00
|
|
|
getDocPathByProjectIdAndDocId(project_id, doc_id, callback) {
|
|
|
|
logger.log({ project_id, doc_id }, 'getting path for doc and project')
|
|
|
|
return ProjectGetter.getProjectWithoutDocLines(project_id, function(
|
|
|
|
err,
|
|
|
|
project
|
|
|
|
) {
|
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
if (project == null) {
|
|
|
|
return callback(new Errors.NotFoundError('no project'))
|
|
|
|
}
|
|
|
|
function recursivelyFindDocInFolder(basePath, doc_id, folder) {
|
|
|
|
let docInCurrentFolder = Array.from(folder.docs || []).find(
|
|
|
|
currentDoc => currentDoc._id.toString() === doc_id.toString()
|
|
|
|
)
|
|
|
|
if (docInCurrentFolder != null) {
|
|
|
|
return path.join(basePath, docInCurrentFolder.name)
|
|
|
|
} else {
|
|
|
|
let docPath, childFolder
|
|
|
|
for (childFolder of Array.from(folder.folders || [])) {
|
|
|
|
docPath = recursivelyFindDocInFolder(
|
|
|
|
path.join(basePath, childFolder.name),
|
|
|
|
doc_id,
|
|
|
|
childFolder
|
|
|
|
)
|
|
|
|
if (docPath != null) {
|
|
|
|
return docPath
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const docPath = recursivelyFindDocInFolder(
|
|
|
|
'/',
|
|
|
|
doc_id,
|
|
|
|
project.rootFolder[0]
|
|
|
|
)
|
|
|
|
if (docPath == null) {
|
|
|
|
return callback(new Errors.NotFoundError('no doc'))
|
|
|
|
}
|
|
|
|
return callback(null, docPath)
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
2019-05-29 05:21:06 -04:00
|
|
|
_getAllFolders(project_id, callback) {
|
|
|
|
logger.log({ project_id }, 'getting all folders for project')
|
|
|
|
return ProjectGetter.getProjectWithoutDocLines(project_id, function(
|
|
|
|
err,
|
|
|
|
project
|
|
|
|
) {
|
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
if (project == null) {
|
2019-10-07 11:21:04 -04:00
|
|
|
return callback(new Errors.NotFoundError('no project'))
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2019-09-09 07:52:25 -04:00
|
|
|
return ProjectEntityHandler._getAllFoldersFromProject(project, callback)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
_getAllFoldersFromProject(project, callback) {
|
|
|
|
const folders = {}
|
|
|
|
var processFolder = function(basePath, folder) {
|
|
|
|
folders[basePath] = folder
|
|
|
|
return (() => {
|
|
|
|
const result = []
|
|
|
|
for (let childFolder of Array.from(folder.folders || [])) {
|
|
|
|
if (childFolder.name != null) {
|
|
|
|
result.push(
|
|
|
|
processFolder(path.join(basePath, childFolder.name), childFolder)
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
result.push(undefined)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
})()
|
|
|
|
}
|
|
|
|
|
|
|
|
processFolder('/', project.rootFolder[0])
|
|
|
|
return callback(null, folders)
|
|
|
|
}
|
|
|
|
}
|
2019-09-09 07:52:25 -04:00
|
|
|
|
|
|
|
module.exports = ProjectEntityHandler
|
2019-11-12 03:56:58 -05:00
|
|
|
module.exports.promises = promisifyAll(ProjectEntityHandler, {
|
|
|
|
multiResult: {
|
|
|
|
getAllEntities: ['docs', 'files'],
|
|
|
|
getAllEntitiesFromProject: ['docs', 'files']
|
|
|
|
}
|
|
|
|
})
|