mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-06-11 15:10:48 +02:00
Merge pull request #9658 from overleaf/em-dropbox-folder-sync
Sync folder creation from Dropbox to Overleaf GitOrigin-RevId: a2749ab8d9db7dd312818b46d6e72f1dbaaaff2e
This commit is contained in:
@@ -653,5 +653,9 @@ const EditorController = {
|
||||
},
|
||||
}
|
||||
|
||||
EditorController.promises = promisifyAll(EditorController)
|
||||
EditorController.promises = promisifyAll(EditorController, {
|
||||
multiResult: {
|
||||
mkdirp: ['newFolders', 'lastFolder'],
|
||||
},
|
||||
})
|
||||
module.exports = EditorController
|
||||
|
||||
@@ -50,6 +50,7 @@ module.exports = {
|
||||
mkdirp: callbackifyMultiResult(wrapWithLock(mkdirp), [
|
||||
'newFolders',
|
||||
'folder',
|
||||
'parentFolder',
|
||||
]),
|
||||
moveEntity: callbackifyMultiResult(wrapWithLock(moveEntity), [
|
||||
'project',
|
||||
@@ -279,13 +280,14 @@ async function mkdirp(projectId, path, options = {}) {
|
||||
for (const folderName of folders) {
|
||||
builtUpPath += `/${folderName}`
|
||||
try {
|
||||
const { element: foundFolder } =
|
||||
const { element: foundFolder, folder: parentFolder } =
|
||||
await ProjectLocator.promises.findElementByPath({
|
||||
project,
|
||||
path: builtUpPath,
|
||||
exactCaseMatch: options.exactCaseMatch,
|
||||
})
|
||||
lastFolder = foundFolder
|
||||
lastFolder.parentFolder_id = parentFolder._id
|
||||
} catch (err) {
|
||||
// Folder couldn't be found. Create it.
|
||||
const parentFolderId = lastFolder && lastFolder._id
|
||||
|
||||
@@ -203,7 +203,7 @@ function _findElementByPathWithProject(
|
||||
function getEntity(folder, entityName, cb) {
|
||||
let result, type
|
||||
if (entityName == null) {
|
||||
return cb(null, folder, 'folder')
|
||||
return cb(null, folder, 'folder', null)
|
||||
}
|
||||
for (const file of iterablePaths(folder, 'fileRefs')) {
|
||||
if (matchFn(file != null ? file.name : undefined, entityName)) {
|
||||
@@ -227,7 +227,7 @@ function _findElementByPathWithProject(
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
cb(null, result, type)
|
||||
cb(null, result, type, folder)
|
||||
} else {
|
||||
cb(
|
||||
new Error(
|
||||
@@ -241,7 +241,7 @@ function _findElementByPathWithProject(
|
||||
return callback(new Error('Tried to find an element for a null project'))
|
||||
}
|
||||
if (needlePath === '' || needlePath === '/') {
|
||||
return callback(null, project.rootFolder[0], 'folder')
|
||||
return callback(null, project.rootFolder[0], 'folder', null)
|
||||
}
|
||||
|
||||
if (needlePath.indexOf('/') === 0) {
|
||||
@@ -317,6 +317,7 @@ module.exports = {
|
||||
findElementByPath: promisifyMultiResult(findElementByPath, [
|
||||
'element',
|
||||
'type',
|
||||
'folder',
|
||||
]),
|
||||
findRootDoc: promisifyMultiResult(findRootDoc, [
|
||||
'element',
|
||||
|
||||
@@ -7,6 +7,7 @@ const Path = require('path')
|
||||
const metrics = require('@overleaf/metrics')
|
||||
const NotificationsBuilder = require('../Notifications/NotificationsBuilder')
|
||||
const SessionManager = require('../Authentication/SessionManager')
|
||||
const HttpErrorHandler = require('../Errors/HttpErrorHandler')
|
||||
const TpdsQueueManager = require('./TpdsQueueManager')
|
||||
|
||||
// mergeUpdate and deleteUpdate are used by Dropbox, where the project is only
|
||||
@@ -80,6 +81,32 @@ async function deleteUpdate(req, res) {
|
||||
res.sendStatus(200)
|
||||
}
|
||||
|
||||
/**
|
||||
* Update endpoint that accepts update details as JSON
|
||||
*/
|
||||
async function updateFolder(req, res) {
|
||||
const userId = req.body.userId
|
||||
const { projectName, filePath } = splitPath(req.body.path)
|
||||
const metadata = await TpdsUpdateHandler.promises.createFolder(
|
||||
userId,
|
||||
projectName,
|
||||
filePath
|
||||
)
|
||||
if (metadata == null) {
|
||||
return HttpErrorHandler.conflict(req, res, 'Could not create folder', {
|
||||
userId,
|
||||
projectName,
|
||||
filePath,
|
||||
})
|
||||
}
|
||||
res.json({
|
||||
entityId: metadata.folderId.toString(),
|
||||
projectId: metadata.projectId.toString(),
|
||||
path: metadata.path,
|
||||
folderId: metadata.parentFolderId.toString(),
|
||||
})
|
||||
}
|
||||
|
||||
// updateProjectContents and deleteProjectContents are used by GitHub. The
|
||||
// project_id is known so we can skip right ahead to creating/updating/deleting
|
||||
// the file. These methods will not ignore noisy files like .DS_Store,
|
||||
@@ -118,10 +145,13 @@ async function getQueues(req, res, next) {
|
||||
}
|
||||
|
||||
function parseParams(req) {
|
||||
let filePath, projectName
|
||||
let path = req.params[0]
|
||||
const userId = req.params.user_id
|
||||
const { projectName, filePath } = splitPath(req.params[0])
|
||||
return { filePath, userId, projectName }
|
||||
}
|
||||
|
||||
function splitPath(path) {
|
||||
let filePath, projectName
|
||||
path = Path.join('/', path)
|
||||
if (path.substring(1).indexOf('/') === -1) {
|
||||
filePath = '/'
|
||||
@@ -132,12 +162,13 @@ function parseParams(req) {
|
||||
projectName = projectName.replace('/', '')
|
||||
}
|
||||
|
||||
return { filePath, userId, projectName }
|
||||
return { projectName, filePath }
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
mergeUpdate: expressify(mergeUpdate),
|
||||
deleteUpdate: expressify(deleteUpdate),
|
||||
updateFolder: expressify(updateFolder),
|
||||
updateProjectContents: expressify(updateProjectContents),
|
||||
deleteProjectContents: expressify(deleteProjectContents),
|
||||
getQueues: expressify(getQueues),
|
||||
|
||||
@@ -144,11 +144,39 @@ async function handleDuplicateProjects(userId, projectName) {
|
||||
.create(projectName)
|
||||
}
|
||||
|
||||
async function createFolder(userId, projectName, path) {
|
||||
const project = await getOrCreateProject(userId, projectName)
|
||||
if (project == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
const projectIsOnCooldown =
|
||||
await CooldownManager.promises.isProjectOnCooldown(project._id)
|
||||
if (projectIsOnCooldown) {
|
||||
throw new Errors.TooManyRequestsError('project on cooldown')
|
||||
}
|
||||
|
||||
const shouldIgnore = await FileTypeManager.promises.shouldIgnore(path)
|
||||
if (shouldIgnore) {
|
||||
return null
|
||||
}
|
||||
|
||||
const folder = await UpdateMerger.promises.createFolder(project._id, path)
|
||||
return {
|
||||
folderId: folder._id,
|
||||
parentFolderId: folder.parentFolder_id,
|
||||
projectId: project._id,
|
||||
path,
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
newUpdate: callbackify(newUpdate),
|
||||
deleteUpdate: callbackify(deleteUpdate),
|
||||
createFolder: callbackify(createFolder),
|
||||
promises: {
|
||||
newUpdate,
|
||||
deleteUpdate,
|
||||
createFolder,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -157,13 +157,23 @@ async function _readFileIntoTextArray(path) {
|
||||
return lines
|
||||
}
|
||||
|
||||
async function createFolder(projectId, path) {
|
||||
const { lastFolder: folder } = await EditorController.promises.mkdirp(
|
||||
projectId,
|
||||
path
|
||||
)
|
||||
return folder
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
mergeUpdate: callbackify(mergeUpdate),
|
||||
_mergeUpdate: callbackify(_mergeUpdate),
|
||||
deleteUpdate: callbackify(deleteUpdate),
|
||||
createFolder: callbackify(createFolder),
|
||||
promises: {
|
||||
mergeUpdate,
|
||||
_mergeUpdate, // called by GitBridgeHandler
|
||||
deleteUpdate,
|
||||
createFolder,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -908,6 +908,11 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
|
||||
DocumentController.setDocument
|
||||
)
|
||||
|
||||
privateApiRouter.post(
|
||||
'/tpds/folder-update',
|
||||
AuthenticationController.requirePrivateApiAuth(),
|
||||
TpdsController.updateFolder
|
||||
)
|
||||
privateApiRouter.post(
|
||||
'/user/:user_id/update/*',
|
||||
AuthenticationController.requirePrivateApiAuth(),
|
||||
|
||||
Reference in New Issue
Block a user