mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Merge pull request #9316 from overleaf/jpa-dropbox-sync-detached-from-project-name
[misc] detach dropbox sync from project names GitOrigin-RevId: 57b3a131aec81bc97ff4da57497950d6658eaeff
This commit is contained in:
parent
7517f4c005
commit
ac91f40c08
5 changed files with 219 additions and 24 deletions
|
@ -17,13 +17,14 @@ const TpdsQueueManager = require('./TpdsQueueManager')
|
|||
|
||||
async function mergeUpdate(req, res) {
|
||||
metrics.inc('tpds.merge-update')
|
||||
const { filePath, userId, projectName } = parseParams(req)
|
||||
const { filePath, userId, projectId, projectName } = parseParams(req)
|
||||
const source = req.headers['x-sl-update-source'] || 'unknown'
|
||||
|
||||
let metadata
|
||||
try {
|
||||
metadata = await TpdsUpdateHandler.promises.newUpdate(
|
||||
userId,
|
||||
projectId,
|
||||
projectName,
|
||||
filePath,
|
||||
req,
|
||||
|
@ -70,11 +71,12 @@ async function mergeUpdate(req, res) {
|
|||
|
||||
async function deleteUpdate(req, res) {
|
||||
metrics.inc('tpds.delete-update')
|
||||
const { filePath, userId, projectName } = parseParams(req)
|
||||
const { filePath, userId, projectId, projectName } = parseParams(req)
|
||||
const source = req.headers['x-sl-update-source'] || 'unknown'
|
||||
|
||||
await TpdsUpdateHandler.promises.deleteUpdate(
|
||||
userId,
|
||||
projectId,
|
||||
projectName,
|
||||
filePath,
|
||||
source
|
||||
|
@ -87,9 +89,11 @@ async function deleteUpdate(req, res) {
|
|||
*/
|
||||
async function updateFolder(req, res) {
|
||||
const userId = req.body.userId
|
||||
const { projectName, filePath } = splitPath(req.body.path)
|
||||
const projectId = req.body.projectId
|
||||
const { projectName, filePath } = splitPath(projectId, req.body.path)
|
||||
const metadata = await TpdsUpdateHandler.promises.createFolder(
|
||||
userId,
|
||||
projectId,
|
||||
projectName,
|
||||
filePath
|
||||
)
|
||||
|
@ -147,14 +151,18 @@ async function getQueues(req, res, next) {
|
|||
|
||||
function parseParams(req) {
|
||||
const userId = req.params.user_id
|
||||
const { projectName, filePath } = splitPath(req.params[0])
|
||||
return { filePath, userId, projectName }
|
||||
const projectId = req.params.project_id
|
||||
const { projectName, filePath } = splitPath(projectId, req.params[0])
|
||||
return { filePath, userId, projectName, projectId }
|
||||
}
|
||||
|
||||
function splitPath(path) {
|
||||
function splitPath(projectId, path) {
|
||||
let filePath, projectName
|
||||
path = Path.join('/', path)
|
||||
if (path.substring(1).indexOf('/') === -1) {
|
||||
if (projectId) {
|
||||
filePath = path
|
||||
projectName = ''
|
||||
} else if (path.substring(1).indexOf('/') === -1) {
|
||||
filePath = '/'
|
||||
projectName = path.substring(1)
|
||||
} else {
|
||||
|
@ -163,7 +171,7 @@ function splitPath(path) {
|
|||
projectName = projectName.replace('/', '')
|
||||
}
|
||||
|
||||
return { projectName, filePath }
|
||||
return { filePath, projectName }
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -19,8 +19,15 @@ const ROOT_DOC_TIMEOUT_LENGTH = 30 * 1000
|
|||
|
||||
const rootDocResets = new BackgroundTaskTracker('root doc resets')
|
||||
|
||||
async function newUpdate(userId, projectName, path, updateRequest, source) {
|
||||
const project = await getOrCreateProject(userId, projectName)
|
||||
async function newUpdate(
|
||||
userId,
|
||||
projectId,
|
||||
projectName,
|
||||
path,
|
||||
updateRequest,
|
||||
source
|
||||
) {
|
||||
const project = await getOrCreateProject(userId, projectId, projectName)
|
||||
if (project == null) {
|
||||
return null
|
||||
}
|
||||
|
@ -46,13 +53,20 @@ async function newUpdate(userId, projectName, path, updateRequest, source) {
|
|||
return metadata
|
||||
}
|
||||
|
||||
async function deleteUpdate(userId, projectName, path, source) {
|
||||
async function deleteUpdate(userId, projectId, projectName, path, source) {
|
||||
logger.debug({ userId, filePath: path }, 'handling delete update from tpds')
|
||||
|
||||
const projects = await ProjectGetter.promises.findUsersProjectsByName(
|
||||
userId,
|
||||
projectName
|
||||
)
|
||||
let projects = []
|
||||
if (projectId) {
|
||||
const project = await findProjectByIdWithRWAccess(userId, projectId)
|
||||
if (project) {
|
||||
projects = [project]
|
||||
}
|
||||
} else {
|
||||
projects = await ProjectGetter.promises.findUsersProjectsByName(
|
||||
userId,
|
||||
projectName
|
||||
)
|
||||
}
|
||||
const activeProjects = projects.filter(
|
||||
project => !ProjectHelper.isArchivedOrTrashed(project, userId)
|
||||
)
|
||||
|
@ -84,7 +98,29 @@ async function deleteUpdate(userId, projectName, path, source) {
|
|||
}
|
||||
}
|
||||
|
||||
async function getOrCreateProject(userId, projectName) {
|
||||
async function getOrCreateProject(userId, projectId, projectName) {
|
||||
if (projectId) {
|
||||
return findProjectByIdWithRWAccess(userId, projectId)
|
||||
} else {
|
||||
return getOrCreateProjectByName(userId, projectName)
|
||||
}
|
||||
}
|
||||
|
||||
async function findProjectByIdWithRWAccess(userId, projectId) {
|
||||
const allProjects = await ProjectGetter.promises.findAllUsersProjects(
|
||||
userId,
|
||||
'name archived trashed'
|
||||
)
|
||||
for (const projects of [allProjects.owned, allProjects.readAndWrite]) {
|
||||
for (const project of projects) {
|
||||
if (project._id.toString() === projectId) {
|
||||
return project
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getOrCreateProjectByName(userId, projectName) {
|
||||
const projects = await ProjectGetter.promises.findUsersProjectsByName(
|
||||
userId,
|
||||
projectName
|
||||
|
@ -144,8 +180,8 @@ async function handleDuplicateProjects(userId, projectName) {
|
|||
.create(projectName)
|
||||
}
|
||||
|
||||
async function createFolder(userId, projectName, path) {
|
||||
const project = await getOrCreateProject(userId, projectName)
|
||||
async function createFolder(userId, projectId, projectName, path) {
|
||||
const project = await getOrCreateProject(userId, projectId, projectName)
|
||||
if (project == null) {
|
||||
return null
|
||||
}
|
||||
|
|
|
@ -923,6 +923,16 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
|
|||
AuthenticationController.requirePrivateApiAuth(),
|
||||
TpdsController.deleteUpdate
|
||||
)
|
||||
privateApiRouter.post(
|
||||
'/project/:project_id/user/:user_id/update/*',
|
||||
AuthenticationController.requirePrivateApiAuth(),
|
||||
TpdsController.mergeUpdate
|
||||
)
|
||||
privateApiRouter.delete(
|
||||
'/project/:project_id/user/:user_id/update/*',
|
||||
AuthenticationController.requirePrivateApiAuth(),
|
||||
TpdsController.deleteUpdate
|
||||
)
|
||||
|
||||
privateApiRouter.post(
|
||||
'/project/:project_id/contents/*',
|
||||
|
|
|
@ -63,14 +63,18 @@ describe('TpdsController', function () {
|
|||
this.projectName = 'projectName'
|
||||
this.path = '/here.txt'
|
||||
this.req = {
|
||||
params: { 0: `${this.projectName}${this.path}`, user_id: this.user_id },
|
||||
params: {
|
||||
0: `${this.projectName}${this.path}`,
|
||||
user_id: this.user_id,
|
||||
project_id: '',
|
||||
},
|
||||
headers: {
|
||||
'x-sl-update-source': (this.source = 'dropbox'),
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
it('should process the update with the update receiver', function (done) {
|
||||
it('should process the update with the update receiver by name', function (done) {
|
||||
const res = {
|
||||
json: payload => {
|
||||
expect(payload).to.deep.equal({
|
||||
|
@ -84,6 +88,7 @@ describe('TpdsController', function () {
|
|||
this.TpdsUpdateHandler.promises.newUpdate
|
||||
.calledWith(
|
||||
this.user_id,
|
||||
'', // projectId
|
||||
this.projectName,
|
||||
this.path,
|
||||
this.req,
|
||||
|
@ -107,6 +112,34 @@ describe('TpdsController', function () {
|
|||
this.TpdsController.mergeUpdate(this.req, res)
|
||||
})
|
||||
|
||||
it('should process the update with the update receiver by id', function (done) {
|
||||
const path = '/here.txt'
|
||||
const req = {
|
||||
pause() {},
|
||||
params: { 0: path, user_id: this.user_id, project_id: '123' },
|
||||
session: {
|
||||
destroy() {},
|
||||
},
|
||||
headers: {
|
||||
'x-sl-update-source': (this.source = 'dropbox'),
|
||||
},
|
||||
}
|
||||
const res = {
|
||||
json: () => {
|
||||
this.TpdsUpdateHandler.promises.newUpdate.should.have.been.calledWith(
|
||||
this.user_id,
|
||||
'123',
|
||||
'', // projectName
|
||||
'/here.txt',
|
||||
req,
|
||||
this.source
|
||||
)
|
||||
done()
|
||||
},
|
||||
}
|
||||
this.TpdsController.mergeUpdate(req, res)
|
||||
})
|
||||
|
||||
it('should return a 500 error when the update receiver fails', function (done) {
|
||||
this.TpdsUpdateHandler.promises.newUpdate.rejects(new Error())
|
||||
const res = {
|
||||
|
@ -150,10 +183,10 @@ describe('TpdsController', function () {
|
|||
})
|
||||
|
||||
describe('getting a delete update', function () {
|
||||
it('should process the delete with the update receiver', function (done) {
|
||||
it('should process the delete with the update receiver by name', function (done) {
|
||||
const path = '/projectName/here.txt'
|
||||
const req = {
|
||||
params: { 0: path, user_id: this.user_id },
|
||||
params: { 0: path, user_id: this.user_id, project_id: '' },
|
||||
session: {
|
||||
destroy() {},
|
||||
},
|
||||
|
@ -164,13 +197,45 @@ describe('TpdsController', function () {
|
|||
const res = {
|
||||
sendStatus: () => {
|
||||
this.TpdsUpdateHandler.promises.deleteUpdate
|
||||
.calledWith(this.user_id, 'projectName', '/here.txt', this.source)
|
||||
.calledWith(
|
||||
this.user_id,
|
||||
'',
|
||||
'projectName',
|
||||
'/here.txt',
|
||||
this.source
|
||||
)
|
||||
.should.equal(true)
|
||||
done()
|
||||
},
|
||||
}
|
||||
this.TpdsController.deleteUpdate(req, res)
|
||||
})
|
||||
|
||||
it('should process the delete with the update receiver by id', function (done) {
|
||||
const path = '/here.txt'
|
||||
const req = {
|
||||
params: { 0: path, user_id: this.user_id, project_id: '123' },
|
||||
session: {
|
||||
destroy() {},
|
||||
},
|
||||
headers: {
|
||||
'x-sl-update-source': (this.source = 'dropbox'),
|
||||
},
|
||||
}
|
||||
const res = {
|
||||
sendStatus: () => {
|
||||
this.TpdsUpdateHandler.promises.deleteUpdate.should.have.been.calledWith(
|
||||
this.user_id,
|
||||
'123',
|
||||
'', // projectName
|
||||
'/here.txt',
|
||||
this.source
|
||||
)
|
||||
done()
|
||||
},
|
||||
}
|
||||
this.TpdsController.deleteUpdate(req, res)
|
||||
})
|
||||
})
|
||||
|
||||
describe('updateFolder', function () {
|
||||
|
|
|
@ -78,6 +78,9 @@ describe('TpdsUpdateHandler', function () {
|
|||
this.ProjectGetter = {
|
||||
promises: {
|
||||
findUsersProjectsByName: sinon.stub(),
|
||||
findAllUsersProjects: sinon
|
||||
.stub()
|
||||
.resolves({ owned: [this.projects.active1], readAndWrite: [] }),
|
||||
},
|
||||
}
|
||||
this.ProjectHelper = {
|
||||
|
@ -119,6 +122,26 @@ describe('TpdsUpdateHandler', function () {
|
|||
})
|
||||
|
||||
describe('getting an update', function () {
|
||||
describe('byId', function () {
|
||||
describe('with no matching project', function () {
|
||||
beforeEach(function () {
|
||||
this.projectId = ObjectId().toString()
|
||||
})
|
||||
receiveUpdateById()
|
||||
expectProjectNotCreated()
|
||||
expectUpdateNotProcessed()
|
||||
})
|
||||
|
||||
describe('with one matching active project', function () {
|
||||
beforeEach(function () {
|
||||
this.projectId = this.projects.active1._id.toString()
|
||||
})
|
||||
receiveUpdateById()
|
||||
expectProjectNotCreated()
|
||||
expectUpdateProcessed()
|
||||
})
|
||||
})
|
||||
|
||||
describe('with no matching project', function () {
|
||||
setupMatchingProjects([])
|
||||
receiveUpdate()
|
||||
|
@ -183,6 +206,7 @@ describe('TpdsUpdateHandler', function () {
|
|||
await expect(
|
||||
this.TpdsUpdateHandler.promises.newUpdate(
|
||||
this.userId,
|
||||
'', // projectId
|
||||
this.projectName,
|
||||
this.path,
|
||||
this.update,
|
||||
|
@ -195,6 +219,26 @@ describe('TpdsUpdateHandler', function () {
|
|||
})
|
||||
|
||||
describe('getting a file delete', function () {
|
||||
describe('byId', function () {
|
||||
describe('with no matching project', function () {
|
||||
beforeEach(function () {
|
||||
this.projectId = ObjectId().toString()
|
||||
})
|
||||
receiveFileDeleteById()
|
||||
expectDeleteNotProcessed()
|
||||
expectProjectNotDeleted()
|
||||
})
|
||||
|
||||
describe('with one matching active project', function () {
|
||||
beforeEach(function () {
|
||||
this.projectId = this.projects.active1._id.toString()
|
||||
})
|
||||
receiveFileDeleteById()
|
||||
expectDeleteProcessed()
|
||||
expectProjectNotDeleted()
|
||||
})
|
||||
})
|
||||
|
||||
describe('with no matching project', function () {
|
||||
setupMatchingProjects([])
|
||||
receiveFileDelete()
|
||||
|
@ -342,6 +386,7 @@ describe('TpdsUpdateHandler', function () {
|
|||
await expect(
|
||||
this.TpdsUpdateHandler.promises.createFolder(
|
||||
this.userId,
|
||||
this.projectId,
|
||||
this.projectName,
|
||||
this.path
|
||||
)
|
||||
|
@ -377,6 +422,7 @@ function receiveUpdate() {
|
|||
beforeEach(async function () {
|
||||
await this.TpdsUpdateHandler.promises.newUpdate(
|
||||
this.userId,
|
||||
'', // projectId
|
||||
this.projectName,
|
||||
this.path,
|
||||
this.update,
|
||||
|
@ -385,10 +431,25 @@ function receiveUpdate() {
|
|||
})
|
||||
}
|
||||
|
||||
function receiveUpdateById() {
|
||||
beforeEach(function (done) {
|
||||
this.TpdsUpdateHandler.newUpdate(
|
||||
this.userId,
|
||||
this.projectId,
|
||||
'', // projectName
|
||||
this.path,
|
||||
this.update,
|
||||
this.source,
|
||||
done
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
function receiveFileDelete() {
|
||||
beforeEach(async function () {
|
||||
await this.TpdsUpdateHandler.promises.deleteUpdate(
|
||||
this.userId,
|
||||
'', // projectId
|
||||
this.projectName,
|
||||
this.path,
|
||||
this.source
|
||||
|
@ -396,10 +457,24 @@ function receiveFileDelete() {
|
|||
})
|
||||
}
|
||||
|
||||
function receiveFileDeleteById() {
|
||||
beforeEach(function (done) {
|
||||
this.TpdsUpdateHandler.deleteUpdate(
|
||||
this.userId,
|
||||
this.projectId,
|
||||
'', // projectName
|
||||
this.path,
|
||||
this.source,
|
||||
done
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
function receiveProjectDelete() {
|
||||
beforeEach(async function () {
|
||||
await this.TpdsUpdateHandler.promises.deleteUpdate(
|
||||
this.userId,
|
||||
'', // projectId
|
||||
this.projectName,
|
||||
'/',
|
||||
this.source
|
||||
|
@ -411,6 +486,7 @@ function receiveFolderUpdate() {
|
|||
beforeEach(async function () {
|
||||
await this.TpdsUpdateHandler.promises.createFolder(
|
||||
this.userId,
|
||||
this.projectId,
|
||||
this.projectName,
|
||||
this.folderPath
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue