convert TpdsUpdateSender to async and cleanup

GitOrigin-RevId: a19830134a13a23775c604a05a7e093d00bbb2de
This commit is contained in:
Ersun Warncke 2020-05-19 17:17:45 -04:00 committed by Copybot
parent 419100d167
commit 9c87ad9801
4 changed files with 349 additions and 463 deletions

View file

@ -1194,13 +1194,18 @@ const ProjectEntityUpdateHandler = {
project.overleaf && project.overleaf &&
project.overleaf.history && project.overleaf.history &&
project.overleaf.history.id project.overleaf.history.id
TpdsUpdateSender.moveEntity({ // do not wait
project_id: projectId, TpdsUpdateSender.promises
project_name: project.name, .moveEntity({
startPath, project_id: projectId,
endPath, project_name: project.name,
rev startPath,
}) endPath,
rev
})
.catch(err => {
logger.error({ err }, 'error sending tpds update')
})
DocumentUpdaterHandler.updateProjectStructure( DocumentUpdaterHandler.updateProjectStructure(
projectId, projectId,
projectHistoryId, projectHistoryId,
@ -1243,13 +1248,18 @@ const ProjectEntityUpdateHandler = {
project.overleaf && project.overleaf &&
project.overleaf.history && project.overleaf.history &&
project.overleaf.history.id project.overleaf.history.id
TpdsUpdateSender.moveEntity({ // do not wait
project_id: projectId, TpdsUpdateSender.promises
project_name: project.name, .moveEntity({
startPath, project_id: projectId,
endPath, project_name: project.name,
rev startPath,
}) endPath,
rev
})
.catch(err => {
logger.error({ err }, 'error sending tpds update')
})
DocumentUpdaterHandler.updateProjectStructure( DocumentUpdaterHandler.updateProjectStructure(
projectId, projectId,
projectHistoryId, projectHistoryId,

View file

@ -1,306 +1,187 @@
/* eslint-disable const _ = require('lodash')
camelcase, const { callbackify } = require('util')
handle-callback-err,
max-len,
no-irregular-whitespace,
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
let tpdsUrl
const settings = require('settings-sharelatex')
const logger = require('logger-sharelatex') const logger = require('logger-sharelatex')
const path = require('path')
const ProjectGetter = require('../Project/ProjectGetter')
const keys = require('../../infrastructure/Keys')
const metrics = require('metrics-sharelatex') const metrics = require('metrics-sharelatex')
const request = require('request') const path = require('path')
const request = require('request-promise-native')
const settings = require('settings-sharelatex')
const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter') const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter')
const { promisifyAll } = require('../../util/promises') .promises
const buildPath = function(user_id, project_name, filePath) { const tpdsUrl = _.get(settings, ['apis', 'thirdPartyDataStore', 'url'])
let projectPath = path.join(project_name, '/', filePath)
projectPath = encodeURIComponent(projectPath) async function addDoc(options) {
const fullPath = path.join('/user/', `${user_id}`, '/entity/', projectPath) metrics.inc('tpds.add-doc')
return fullPath
options.streamOrigin =
settings.apis.docstore.pubUrl +
path.join(
`/project/${options.project_id}`,
`/doc/${options.doc_id}`,
'/raw'
)
return addEntity(options)
} }
const tpdsworkerEnabled = () => async function addEntity(options) {
(settings.apis.tpdsworker != null const projectUserIds = await getProjectUsersIds(options.project_id)
? settings.apis.tpdsworker.url if (!projectUserIds.length) {
: undefined) != null return
if (!tpdsworkerEnabled()) { }
logger.log('tpdsworker is not enabled, request will not be sent to it')
const job = {
method: 'post',
headers: {
sl_entity_rev: options.rev,
sl_project_id: options.project_id,
sl_all_user_ids: JSON.stringify(projectUserIds)
},
uri: buildTpdsUrl(projectUserIds[0], options.project_name, options.path),
title: 'addFile',
streamOrigin: options.streamOrigin
}
return enqueue(options.project_id, 'pipeStreamFrom', job)
} }
if (settings.apis.thirdPartyDataStore.linode_url != null) { async function addFile(options) {
tpdsUrl = settings.apis.thirdPartyDataStore.linode_url metrics.inc('tpds.add-file')
} else {
tpdsUrl = settings.apis.thirdPartyDataStore.url options.streamOrigin =
settings.apis.filestore.url +
path.join(`/project/${options.project_id}`, `/file/${options.file_id}`)
return addEntity(options)
}
function buildMovePaths(options) {
if (options.newProjectName) {
return {
startPath: path.join('/', options.project_name, '/'),
endPath: path.join('/', options.newProjectName, '/')
}
} else {
return {
startPath: path.join('/', options.project_name, '/', options.startPath),
endPath: path.join('/', options.project_name, '/', options.endPath)
}
}
}
function buildTpdsUrl(userId, projectName, filePath) {
const projectPath = encodeURIComponent(path.join(projectName, '/', filePath))
return `${tpdsUrl}/user/${userId}/entity/${projectPath}`
}
async function deleteEntity(options) {
metrics.inc('tpds.delete-entity')
const projectUserIds = await getProjectUsersIds(options.project_id)
if (!projectUserIds.length) {
return
}
const job = {
method: 'delete',
headers: {
sl_project_id: options.project_id,
sl_all_user_ids: JSON.stringify(projectUserIds)
},
uri: buildTpdsUrl(projectUserIds[0], options.project_name, options.path),
title: 'deleteEntity',
sl_all_user_ids: JSON.stringify(projectUserIds)
}
return enqueue(options.project_id, 'standardHttpRequest', job)
}
async function enqueue(group, method, job) {
const tpdsWorkerUrl = _.get(settings, ['apis', 'tpdsworker', 'url'])
// silently do nothing if worker url is not in settings
if (!tpdsWorkerUrl) {
return
}
try {
return request({
uri: `${tpdsWorkerUrl}/enqueue/web_to_tpds_http_requests`,
json: { group, job, method },
method: 'post',
timeout: 5 * 1000
})
} catch (err) {
// log error and continue
logger.error({ err, group, job, method }, 'error enqueueing tpdsworker job')
}
}
async function getProjectUsersIds(projectId) {
// get list of all user ids with access to project. project owner
// will always be the first entry in the list.
// TODO: filter this list to only return users with dropbox linked
return CollaboratorsGetter.getInvitedMemberIds(projectId)
}
async function moveEntity(options) {
metrics.inc('tpds.move-entity')
const projectUserIds = await getProjectUsersIds(options.project_id)
if (!projectUserIds.length) {
return
}
const { endPath, startPath } = buildMovePaths(options)
const job = {
method: 'put',
title: 'moveEntity',
uri: `${tpdsUrl}/user/${projectUserIds[0]}/entity`,
headers: {
sl_project_id: options.project_id,
sl_entity_rev: options.rev,
sl_all_user_ids: JSON.stringify(projectUserIds)
},
json: {
user_id: projectUserIds[0],
endPath,
startPath
}
}
return enqueue(options.project_id, 'standardHttpRequest', job)
}
async function pollDropboxForUser(userId) {
metrics.inc('tpds.poll-dropbox')
const job = {
method: 'post',
uri: `${tpdsUrl}/user/poll`,
json: {
user_ids: [userId]
}
}
return enqueue(`poll-dropbox:${userId}`, 'standardHttpRequest', job)
} }
const TpdsUpdateSender = { const TpdsUpdateSender = {
_enqueue(group, method, job, callback) { addDoc: callbackify(addDoc),
if (!tpdsworkerEnabled()) { addEntity: callbackify(addEntity),
return callback() addFile: callbackify(addFile),
} deleteEntity: callbackify(deleteEntity),
const opts = { enqueue: callbackify(enqueue),
uri: `${settings.apis.tpdsworker.url}/enqueue/web_to_tpds_http_requests`, moveEntity: callbackify(moveEntity),
json: { pollDropboxForUser: callbackify(pollDropboxForUser),
group, promises: {
method, addDoc,
job addEntity,
}, addFile,
method: 'post', deleteEntity,
timeout: 5 * 1000 enqueue,
} moveEntity,
return request(opts, function(err) { pollDropboxForUser
if (err != null) {
logger.err(
{ err },
'error queuing something in the tpdsworker, continuing anyway'
)
return callback()
} else {
return callback()
}
})
},
_addEntity(options, callback) {
if (callback == null) {
callback = function(err) {}
}
return getProjectsUsersIds(options.project_id, function(
err,
user_id,
allUserIds
) {
if (err != null) {
logger.warn({ err, options }, 'error getting projects user ids')
return callback(err)
}
logger.log(
{
project_id: options.project_id,
user_id,
path: options.path,
uri: options.uri,
rev: options.rev
},
'sending file to third party data store'
)
const postOptions = {
method: 'post',
headers: {
sl_entity_rev: options.rev,
sl_project_id: options.project_id,
sl_all_user_ids: JSON.stringify(allUserIds)
},
uri: `${tpdsUrl}${buildPath(
user_id,
options.project_name,
options.path
)}`,
title: 'addFile',
streamOrigin: options.streamOrigin
}
return TpdsUpdateSender._enqueue(
options.project_id,
'pipeStreamFrom',
postOptions,
function(err) {
if (err != null) {
logger.warn(
{
err,
project_id: options.project_id,
user_id,
path: options.path,
uri: options.uri,
rev: options.rev
},
'error sending file to third party data store queued up for processing'
)
return callback(err)
}
logger.log(
{
project_id: options.project_id,
user_id,
path: options.path,
uri: options.uri,
rev: options.rev
},
'sending file to third party data store queued up for processing'
)
return callback(err)
}
)
})
},
addFile(options, callback) {
if (callback == null) {
callback = function(err) {}
}
metrics.inc('tpds.add-file')
options.streamOrigin =
(settings.apis.filestore.linode_url || settings.apis.filestore.url) +
path.join(`/project/${options.project_id}/file/`, `${options.file_id}`)
return this._addEntity(options, callback)
},
addDoc(options, callback) {
if (callback == null) {
callback = function(err) {}
}
metrics.inc('tpds.add-doc')
options.streamOrigin =
(settings.apis.docstore.linode_url || settings.apis.docstore.pubUrl) +
path.join(`/project/${options.project_id}/doc/`, `${options.doc_id}/raw`)
return this._addEntity(options, callback)
},
moveEntity(options, callback) {
let endPath, startPath
if (callback == null) {
callback = function(err) {}
}
metrics.inc('tpds.move-entity')
if (options.newProjectName != null) {
startPath = path.join(`/${options.project_name}/`)
endPath = path.join(`/${options.newProjectName}/`)
} else {
startPath = mergeProjectNameAndPath(
options.project_name,
options.startPath
)
endPath = mergeProjectNameAndPath(options.project_name, options.endPath)
}
return getProjectsUsersIds(options.project_id, function(
err,
user_id,
allUserIds
) {
const moveOptions = {
method: 'put',
title: 'moveEntity',
uri: `${tpdsUrl}/user/${user_id}/entity`,
headers: {
sl_project_id: options.project_id,
sl_entity_rev: options.rev,
sl_all_user_ids: JSON.stringify(allUserIds)
},
json: {
user_id,
endPath,
startPath
}
}
return TpdsUpdateSender._enqueue(
options.project_id,
'standardHttpRequest',
moveOptions,
callback
)
})
},
deleteEntity(options, callback) {
if (callback == null) {
callback = function(err) {}
}
metrics.inc('tpds.delete-entity')
return getProjectsUsersIds(options.project_id, function(
err,
user_id,
allUserIds
) {
const deleteOptions = {
method: 'DELETE',
headers: {
sl_project_id: options.project_id,
sl_all_user_ids: JSON.stringify(allUserIds)
},
uri: `${tpdsUrl}${buildPath(
user_id,
options.project_name,
options.path
)}`,
title: 'deleteEntity',
sl_all_user_ids: JSON.stringify(allUserIds)
}
return TpdsUpdateSender._enqueue(
options.project_id,
'standardHttpRequest',
deleteOptions,
callback
)
})
},
pollDropboxForUser(user_id, callback) {
if (callback == null) {
callback = function(err) {}
}
metrics.inc('tpds.poll-dropbox')
const options = {
method: 'POST',
uri: `${tpdsUrl}/user/poll`,
json: {
user_ids: [user_id]
}
}
return TpdsUpdateSender._enqueue(
`poll-dropbox:${user_id}`,
'standardHttpRequest',
options,
callback
)
} }
} }
var getProjectsUsersIds = function(project_id, callback) {
if (callback == null) {
callback = function(err, owner_id, allUserIds) {}
}
return ProjectGetter.getProject(
project_id,
{ _id: true, owner_ref: true },
function(err, project) {
if (err != null) {
return callback(err)
}
return CollaboratorsGetter.getInvitedMemberIds(project_id, function(
err,
member_ids
) {
if (err != null) {
return callback(err)
}
return callback(
err,
project != null ? project.owner_ref : undefined,
member_ids
)
})
}
)
}
var mergeProjectNameAndPath = function(project_name, path) {
if (path.indexOf('/') === 0) {
path = path.substring(1)
}
const fullPath = `/${project_name}/${path}`
return fullPath
}
TpdsUpdateSender.promises = promisifyAll(TpdsUpdateSender)
module.exports = TpdsUpdateSender module.exports = TpdsUpdateSender

View file

@ -133,7 +133,10 @@ describe('ProjectEntityUpdateHandler', function() {
addFile: sinon.stub().yields(), addFile: sinon.stub().yields(),
addDoc: sinon.stub(), addDoc: sinon.stub(),
deleteEntity: sinon.stub().yields(), deleteEntity: sinon.stub().yields(),
moveEntity: sinon.stub() moveEntity: sinon.stub(),
promises: {
moveEntity: sinon.stub().resolves()
}
} }
this.FileStoreHandler = { this.FileStoreHandler = {
copyFile: sinon.stub(), copyFile: sinon.stub(),
@ -1672,7 +1675,7 @@ describe('ProjectEntityUpdateHandler', function() {
}) })
it('notifies tpds', function() { it('notifies tpds', function() {
this.TpdsUpdateSender.moveEntity this.TpdsUpdateSender.promises.moveEntity
.calledWith({ .calledWith({
project_id: projectId, project_id: projectId,
project_name: this.project_name, project_name: this.project_name,
@ -1731,7 +1734,7 @@ describe('ProjectEntityUpdateHandler', function() {
}) })
it('notifies tpds', function() { it('notifies tpds', function() {
this.TpdsUpdateSender.moveEntity this.TpdsUpdateSender.promises.moveEntity
.calledWith({ .calledWith({
project_id: projectId, project_id: projectId,
project_name: this.project_name, project_name: this.project_name,

View file

@ -1,31 +1,20 @@
/* eslint-disable
camelcase,
handle-callback-err,
max-len,
no-return-assign,
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
const SandboxedModule = require('sandboxed-module') const SandboxedModule = require('sandboxed-module')
const assert = require('assert') const chai = require('chai')
require('chai').should() const path = require('path')
const modulePath = require('path').join( const sinon = require('sinon')
chai.should()
const modulePath = path.join(
__dirname, __dirname,
'../../../../app/src/Features/ThirdPartyDataStore/TpdsUpdateSender.js' '../../../../app/src/Features/ThirdPartyDataStore/TpdsUpdateSender.js'
) )
const sinon = require('sinon')
const ath = require('path') const projectId = 'project_id_here'
const project_id = 'project_id_here' const userId = 'user_id_here'
const user_id = 'user_id_here' const readOnlyRef = 'read_only_ref_1_id_here'
const read_only_ref_1 = 'read_only_ref_1_id_here' const collaberatorRef = 'collaberator_ref_1_here'
const collaberator_ref_1 = 'collaberator_ref_1_here' const projectName = 'project_name_here'
const project_name = 'project_name_here'
const thirdPartyDataStoreApiUrl = 'http://third-party-json-store.herokuapp.com' const thirdPartyDataStoreApiUrl = 'http://third-party-json-store.herokuapp.com'
const httpUsername = 'user' const httpUsername = 'user'
@ -37,16 +26,14 @@ const filestoreUrl = 'filestore.sharelatex.com'
describe('TpdsUpdateSender', function() { describe('TpdsUpdateSender', function() {
beforeEach(function() { beforeEach(function() {
this.requestQueuer = function(queue, meth, opts, callback) {} this.requestQueuer = function(queue, meth, opts, callback) {}
const project = { owner_ref: user_id } const memberIds = [userId, collaberatorRef, readOnlyRef]
const member_ids = [collaberator_ref_1, read_only_ref_1, user_id]
this.CollaboratorsGetter = { this.CollaboratorsGetter = {
getInvitedMemberIds: sinon.stub().yields(null, member_ids) promises: {
} getInvitedMemberIds: sinon.stub().resolves(memberIds)
this.ProjectGetter = { }
getProject: sinon.stub().callsArgWith(2, null, project)
} }
this.docstoreUrl = 'docstore.sharelatex.env' this.docstoreUrl = 'docstore.sharelatex.env'
this.request = sinon.stub().returns({ pipe() {} }) this.request = sinon.stub().resolves()
this.settings = { this.settings = {
siteUrl, siteUrl,
httpAuthSiteUrl, httpAuthSiteUrl,
@ -60,182 +47,187 @@ describe('TpdsUpdateSender', function() {
} }
} }
} }
return (this.updateSender = SandboxedModule.require(modulePath, { this.updateSender = SandboxedModule.require(modulePath, {
globals: { globals: {
console: console console: console
}, },
requires: { requires: {
'settings-sharelatex': this.settings, 'settings-sharelatex': this.settings,
'logger-sharelatex': { log() {} }, 'logger-sharelatex': { log() {} },
'../Project/ProjectGetter': this.ProjectGetter, 'request-promise-native': this.request,
request: this.request,
'../Collaborators/CollaboratorsGetter': this.CollaboratorsGetter, '../Collaborators/CollaboratorsGetter': this.CollaboratorsGetter,
'metrics-sharelatex': { 'metrics-sharelatex': {
inc() {} inc() {}
} }
} }
})) })
}) })
describe('_enqueue', function() { describe('enqueue', function() {
it('should not call request if there is no tpdsworker url', function(done) { it('should not call request if there is no tpdsworker url', async function() {
return this.updateSender._enqueue(null, null, null, err => { await this.updateSender.promises.enqueue(null, null, null)
this.request.called.should.equal(false) this.request.should.not.have.been.called
return done()
})
}) })
it('should post the message to the tpdsworker', function(done) { it('should post the message to the tpdsworker', async function() {
this.settings.apis.tpdsworker = { url: 'www.tpdsworker.env' } this.settings.apis.tpdsworker = { url: 'www.tpdsworker.env' }
const group = 'myproject' const group = 'myproject'
const method = 'somemethod' const method = 'somemethod'
const job = 'do something' const job = 'do something'
this.request.callsArgWith(1) await this.updateSender.promises.enqueue(group, method, job)
return this.updateSender._enqueue(group, method, job, err => { const args = this.request.firstCall.args[0]
const args = this.request.args[0][0] args.json.group.should.equal(group)
args.json.group.should.equal(group) args.json.job.should.equal(job)
args.json.job.should.equal(job) args.json.method.should.equal(method)
args.json.method.should.equal(method) args.uri.should.equal(
args.uri.should.equal( 'www.tpdsworker.env/enqueue/web_to_tpds_http_requests'
'www.tpdsworker.env/enqueue/web_to_tpds_http_requests' )
)
return done()
})
}) })
}) })
describe('sending updates', function() { describe('sending updates', function() {
it('queues a post the file with user and file id', function(done) { beforeEach(function() {
const file_id = '4545345' this.settings.apis.tpdsworker = { url: 'www.tpdsworker.env' }
})
it('queues a post the file with user and file id', async function() {
const fileId = '4545345'
const path = '/some/path/here.jpg' const path = '/some/path/here.jpg'
this.updateSender._enqueue = function(uid, method, job, callback) {
uid.should.equal(project_id) await this.updateSender.promises.addFile({
job.method.should.equal('post') project_id: projectId,
job.streamOrigin.should.equal( file_id: fileId,
`${filestoreUrl}/project/${project_id}/file/${file_id}` path,
) project_name: projectName
const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${user_id}/entity/${encodeURIComponent( })
project_name
)}${encodeURIComponent(path)}` const { group, job, method } = this.request.firstCall.args[0].json
job.uri.should.equal(expectedUrl) group.should.equal(projectId)
job.headers.sl_all_user_ids.should.eql( method.should.equal('pipeStreamFrom')
JSON.stringify([collaberator_ref_1, read_only_ref_1, user_id]) job.method.should.equal('post')
) job.streamOrigin.should.equal(
return done() `${filestoreUrl}/project/${projectId}/file/${fileId}`
} )
return this.updateSender.addFile( const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${userId}/entity/${encodeURIComponent(
{ project_id, file_id, path, project_name }, projectName
() => {} )}${encodeURIComponent(path)}`
job.uri.should.equal(expectedUrl)
job.headers.sl_all_user_ids.should.equal(
JSON.stringify([userId, collaberatorRef, readOnlyRef])
) )
}) })
it('post doc with stream origin of docstore', function(done) { it('post doc with stream origin of docstore', async function() {
const doc_id = '4545345' const docId = '4545345'
const path = '/some/path/here.tex' const path = '/some/path/here.tex'
const lines = ['line1', 'line2', 'line3'] const lines = ['line1', 'line2', 'line3']
this.updateSender._enqueue = (uid, method, job, callback) => { await this.updateSender.promises.addDoc({
uid.should.equal(project_id) project_id: projectId,
job.method.should.equal('post') doc_id: docId,
const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${user_id}/entity/${encodeURIComponent(
project_name
)}${encodeURIComponent(path)}`
job.uri.should.equal(expectedUrl)
job.streamOrigin.should.equal(
`${this.docstoreUrl}/project/${project_id}/doc/${doc_id}/raw`
)
job.headers.sl_all_user_ids.should.eql(
JSON.stringify([collaberator_ref_1, read_only_ref_1, user_id])
)
return done()
}
return this.updateSender.addDoc({
project_id,
doc_id,
path, path,
docLines: lines, docLines: lines,
project_name project_name: projectName
}) })
const { group, job, method } = this.request.firstCall.args[0].json
group.should.equal(projectId)
method.should.equal('pipeStreamFrom')
job.method.should.equal('post')
const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${userId}/entity/${encodeURIComponent(
projectName
)}${encodeURIComponent(path)}`
job.uri.should.equal(expectedUrl)
job.streamOrigin.should.equal(
`${this.docstoreUrl}/project/${projectId}/doc/${docId}/raw`
)
job.headers.sl_all_user_ids.should.eql(
JSON.stringify([userId, collaberatorRef, readOnlyRef])
)
}) })
it('deleting entity', function(done) { it('deleting entity', async function() {
const path = '/path/here/t.tex' const path = '/path/here/t.tex'
this.updateSender._enqueue = function(uid, method, job, callback) {
uid.should.equal(project_id) await this.updateSender.promises.deleteEntity({
job.method.should.equal('DELETE') project_id: projectId,
const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${user_id}/entity/${encodeURIComponent( path,
project_name project_name: projectName
)}${encodeURIComponent(path)}` })
job.headers.sl_all_user_ids.should.eql(
JSON.stringify([collaberator_ref_1, read_only_ref_1, user_id]) const { group, job, method } = this.request.firstCall.args[0].json
)
job.uri.should.equal(expectedUrl) group.should.equal(projectId)
return done() method.should.equal('standardHttpRequest')
} job.method.should.equal('delete')
return this.updateSender.deleteEntity({ project_id, path, project_name }) const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${userId}/entity/${encodeURIComponent(
projectName
)}${encodeURIComponent(path)}`
job.headers.sl_all_user_ids.should.eql(
JSON.stringify([userId, collaberatorRef, readOnlyRef])
)
job.uri.should.equal(expectedUrl)
}) })
it('moving entity', function(done) { it('moving entity', async function() {
const startPath = 'staring/here/file.tex' const startPath = 'staring/here/file.tex'
const endPath = 'ending/here/file.tex' const endPath = 'ending/here/file.tex'
this.updateSender._enqueue = function(uid, method, job, callback) {
uid.should.equal(project_id) await this.updateSender.promises.moveEntity({
job.method.should.equal('put') project_id: projectId,
job.uri.should.equal(
`${thirdPartyDataStoreApiUrl}/user/${user_id}/entity`
)
job.json.startPath.should.equal(`/${project_name}/${startPath}`)
job.json.endPath.should.equal(`/${project_name}/${endPath}`)
job.headers.sl_all_user_ids.should.eql(
JSON.stringify([collaberator_ref_1, read_only_ref_1, user_id])
)
return done()
}
return this.updateSender.moveEntity({
project_id,
startPath, startPath,
endPath, endPath,
project_name project_name: projectName
}) })
const { group, job, method } = this.request.firstCall.args[0].json
group.should.equal(projectId)
method.should.equal('standardHttpRequest')
job.method.should.equal('put')
job.uri.should.equal(`${thirdPartyDataStoreApiUrl}/user/${userId}/entity`)
job.json.startPath.should.equal(`/${projectName}/${startPath}`)
job.json.endPath.should.equal(`/${projectName}/${endPath}`)
job.headers.sl_all_user_ids.should.eql(
JSON.stringify([userId, collaberatorRef, readOnlyRef])
)
}) })
it('should be able to rename a project using the move entity func', function(done) { it('should be able to rename a project using the move entity func', async function() {
const oldProjectName = '/oldProjectName/' const oldProjectName = '/oldProjectName/'
const newProjectName = '/newProjectName/' const newProjectName = '/newProjectName/'
this.updateSender._enqueue = function(uid, method, job, callback) {
uid.should.equal(project_id) await this.updateSender.promises.moveEntity({
job.method.should.equal('put') project_id: projectId,
job.uri.should.equal(
`${thirdPartyDataStoreApiUrl}/user/${user_id}/entity`
)
job.json.startPath.should.equal(oldProjectName)
job.json.endPath.should.equal(newProjectName)
job.headers.sl_all_user_ids.should.eql(
JSON.stringify([collaberator_ref_1, read_only_ref_1, user_id])
)
return done()
}
return this.updateSender.moveEntity({
project_id,
project_name: oldProjectName, project_name: oldProjectName,
newProjectName newProjectName
}) })
const { group, job, method } = this.request.firstCall.args[0].json
group.should.equal(projectId)
method.should.equal('standardHttpRequest')
job.method.should.equal('put')
job.uri.should.equal(`${thirdPartyDataStoreApiUrl}/user/${userId}/entity`)
job.json.startPath.should.equal(oldProjectName)
job.json.endPath.should.equal(newProjectName)
job.headers.sl_all_user_ids.should.eql(
JSON.stringify([userId, collaberatorRef, readOnlyRef])
)
}) })
it('pollDropboxForUser', function(done) { it('pollDropboxForUser', async function() {
this.updateSender._enqueue = sinon.stub().callsArg(3) await this.updateSender.promises.pollDropboxForUser(userId)
return this.updateSender.pollDropboxForUser(user_id, error => {
this.updateSender._enqueue const { group, job, method } = this.request.firstCall.args[0].json
.calledWith(`poll-dropbox:${user_id}`, 'standardHttpRequest', {
method: 'POST', group.should.equal(`poll-dropbox:${userId}`)
uri: `${thirdPartyDataStoreApiUrl}/user/poll`, method.should.equal('standardHttpRequest')
json: {
user_ids: [user_id] job.method.should.equal('post')
} job.uri.should.equal(`${thirdPartyDataStoreApiUrl}/user/poll`)
}) job.json.user_ids[0].should.equal(userId)
.should.equal(true)
return done()
})
}) })
}) })
}) })