2020-09-23 04:49:26 -04:00
|
|
|
const { ObjectId } = require('mongodb')
|
2019-05-29 05:21:06 -04:00
|
|
|
const SandboxedModule = require('sandboxed-module')
|
2020-05-19 17:17:45 -04:00
|
|
|
const chai = require('chai')
|
|
|
|
const path = require('path')
|
|
|
|
const sinon = require('sinon')
|
|
|
|
|
|
|
|
chai.should()
|
|
|
|
|
|
|
|
const modulePath = path.join(
|
2019-05-29 05:21:06 -04:00
|
|
|
__dirname,
|
|
|
|
'../../../../app/src/Features/ThirdPartyDataStore/TpdsUpdateSender.js'
|
|
|
|
)
|
2020-05-19 17:17:45 -04:00
|
|
|
|
|
|
|
const projectId = 'project_id_here'
|
2020-06-15 10:52:50 -04:00
|
|
|
const userId = ObjectId()
|
|
|
|
const readOnlyRef = ObjectId()
|
|
|
|
const collaberatorRef = ObjectId()
|
2020-05-19 17:17:45 -04:00
|
|
|
const projectName = 'project_name_here'
|
2019-05-29 05:21:06 -04:00
|
|
|
|
|
|
|
const thirdPartyDataStoreApiUrl = 'http://third-party-json-store.herokuapp.com'
|
|
|
|
const httpUsername = 'user'
|
|
|
|
const httpPass = 'pass'
|
|
|
|
const siteUrl = 'http://www.localhost:3000'
|
|
|
|
const httpAuthSiteUrl = `http://${httpUsername}:${httpPass}@www.localhost:3000`
|
|
|
|
const filestoreUrl = 'filestore.sharelatex.com'
|
|
|
|
|
|
|
|
describe('TpdsUpdateSender', function() {
|
|
|
|
beforeEach(function() {
|
2020-06-02 10:02:06 -04:00
|
|
|
this.fakeUser = {
|
|
|
|
_id: '12390i'
|
|
|
|
}
|
2019-05-29 05:21:06 -04:00
|
|
|
this.requestQueuer = function(queue, meth, opts, callback) {}
|
2020-05-19 17:17:45 -04:00
|
|
|
const memberIds = [userId, collaberatorRef, readOnlyRef]
|
2019-10-07 04:30:51 -04:00
|
|
|
this.CollaboratorsGetter = {
|
2020-05-19 17:17:45 -04:00
|
|
|
promises: {
|
|
|
|
getInvitedMemberIds: sinon.stub().resolves(memberIds)
|
|
|
|
}
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
|
|
|
this.docstoreUrl = 'docstore.sharelatex.env'
|
2020-05-19 17:17:45 -04:00
|
|
|
this.request = sinon.stub().resolves()
|
2019-05-29 05:21:06 -04:00
|
|
|
this.settings = {
|
|
|
|
siteUrl,
|
|
|
|
httpAuthSiteUrl,
|
|
|
|
apis: {
|
|
|
|
thirdPartyDataStore: { url: thirdPartyDataStoreApiUrl },
|
|
|
|
filestore: {
|
|
|
|
url: filestoreUrl
|
|
|
|
},
|
|
|
|
docstore: {
|
|
|
|
pubUrl: this.docstoreUrl
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-02 10:02:06 -04:00
|
|
|
const getUsers = sinon.stub().resolves(
|
2020-06-11 09:55:52 -04:00
|
|
|
memberIds.slice(1).map(userId => {
|
2020-06-02 10:02:06 -04:00
|
|
|
return { _id: userId }
|
|
|
|
})
|
|
|
|
)
|
|
|
|
this.UserGetter = {
|
|
|
|
promises: { getUsers }
|
|
|
|
}
|
2020-05-19 17:17:45 -04:00
|
|
|
this.updateSender = SandboxedModule.require(modulePath, {
|
2019-07-15 06:33:47 -04:00
|
|
|
globals: {
|
|
|
|
console: console
|
|
|
|
},
|
2019-05-29 05:21:06 -04:00
|
|
|
requires: {
|
2020-10-05 04:23:21 -04:00
|
|
|
mongodb: { ObjectId },
|
2019-05-29 05:21:06 -04:00
|
|
|
'settings-sharelatex': this.settings,
|
|
|
|
'logger-sharelatex': { log() {} },
|
2020-05-19 17:17:45 -04:00
|
|
|
'request-promise-native': this.request,
|
2019-10-07 04:30:51 -04:00
|
|
|
'../Collaborators/CollaboratorsGetter': this.CollaboratorsGetter,
|
2020-06-02 10:02:06 -04:00
|
|
|
'../User/UserGetter.js': this.UserGetter,
|
2020-10-30 04:10:50 -04:00
|
|
|
'@overleaf/metrics': {
|
2019-05-29 05:21:06 -04:00
|
|
|
inc() {}
|
|
|
|
}
|
|
|
|
}
|
2020-05-19 17:17:45 -04:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2020-05-19 17:17:45 -04:00
|
|
|
describe('enqueue', function() {
|
|
|
|
it('should not call request if there is no tpdsworker url', async function() {
|
|
|
|
await this.updateSender.promises.enqueue(null, null, null)
|
|
|
|
this.request.should.not.have.been.called
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2020-05-19 17:17:45 -04:00
|
|
|
it('should post the message to the tpdsworker', async function() {
|
2019-05-29 05:21:06 -04:00
|
|
|
this.settings.apis.tpdsworker = { url: 'www.tpdsworker.env' }
|
2020-06-02 10:02:06 -04:00
|
|
|
const group0 = 'myproject'
|
|
|
|
const method0 = 'somemethod0'
|
|
|
|
const job0 = 'do something'
|
|
|
|
await this.updateSender.promises.enqueue(group0, method0, job0)
|
2020-05-19 17:17:45 -04:00
|
|
|
const args = this.request.firstCall.args[0]
|
2020-06-02 10:02:06 -04:00
|
|
|
args.json.group.should.equal(group0)
|
|
|
|
args.json.job.should.equal(job0)
|
|
|
|
args.json.method.should.equal(method0)
|
2020-05-19 17:17:45 -04:00
|
|
|
args.uri.should.equal(
|
|
|
|
'www.tpdsworker.env/enqueue/web_to_tpds_http_requests'
|
|
|
|
)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2019-06-21 09:46:09 -04:00
|
|
|
describe('sending updates', function() {
|
2020-05-19 17:17:45 -04:00
|
|
|
beforeEach(function() {
|
|
|
|
this.settings.apis.tpdsworker = { url: 'www.tpdsworker.env' }
|
|
|
|
})
|
|
|
|
|
|
|
|
it('queues a post the file with user and file id', async function() {
|
|
|
|
const fileId = '4545345'
|
2019-05-29 05:21:06 -04:00
|
|
|
const path = '/some/path/here.jpg'
|
2020-05-19 17:17:45 -04:00
|
|
|
|
|
|
|
await this.updateSender.promises.addFile({
|
|
|
|
project_id: projectId,
|
|
|
|
file_id: fileId,
|
|
|
|
path,
|
|
|
|
project_name: projectName
|
|
|
|
})
|
|
|
|
|
2020-06-02 10:02:06 -04:00
|
|
|
const {
|
|
|
|
group: group0,
|
|
|
|
job: job0,
|
|
|
|
method: method0
|
|
|
|
} = this.request.firstCall.args[0].json
|
|
|
|
group0.should.equal(userId)
|
|
|
|
method0.should.equal('pipeStreamFrom')
|
|
|
|
job0.method.should.equal('post')
|
|
|
|
job0.streamOrigin.should.equal(
|
2020-05-19 17:17:45 -04:00
|
|
|
`${filestoreUrl}/project/${projectId}/file/${fileId}`
|
|
|
|
)
|
|
|
|
const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${userId}/entity/${encodeURIComponent(
|
|
|
|
projectName
|
|
|
|
)}${encodeURIComponent(path)}`
|
2020-06-02 10:02:06 -04:00
|
|
|
job0.uri.should.equal(expectedUrl)
|
|
|
|
job0.headers.sl_all_user_ids.should.equal(JSON.stringify([userId]))
|
2020-09-16 04:51:25 -04:00
|
|
|
job0.headers.sl_project_owner_user_id.should.equal(userId)
|
2020-06-02 10:02:06 -04:00
|
|
|
|
|
|
|
const { group: group1, job: job1 } = this.request.secondCall.args[0].json
|
2020-06-15 10:52:50 -04:00
|
|
|
group1.should.equal(collaberatorRef)
|
2020-06-02 10:02:06 -04:00
|
|
|
job1.headers.sl_all_user_ids.should.equal(
|
2020-06-15 10:52:50 -04:00
|
|
|
JSON.stringify([collaberatorRef])
|
2020-06-02 10:02:06 -04:00
|
|
|
)
|
2020-09-16 04:51:25 -04:00
|
|
|
job1.headers.sl_project_owner_user_id.should.equal(userId)
|
2020-06-02 10:02:06 -04:00
|
|
|
|
|
|
|
const { group: group2, job: job2 } = this.request.thirdCall.args[0].json
|
2020-06-15 10:52:50 -04:00
|
|
|
group2.should.equal(readOnlyRef)
|
|
|
|
job2.headers.sl_all_user_ids.should.equal(JSON.stringify([readOnlyRef]))
|
2020-09-16 04:51:25 -04:00
|
|
|
job2.headers.sl_project_owner_user_id.should.equal(userId)
|
2020-06-05 00:10:46 -04:00
|
|
|
|
|
|
|
this.UserGetter.promises.getUsers.should.have.been.calledOnce.and.calledWith(
|
|
|
|
{
|
|
|
|
_id: {
|
2020-06-15 10:52:50 -04:00
|
|
|
$in: [collaberatorRef, readOnlyRef]
|
2020-06-05 00:10:46 -04:00
|
|
|
},
|
|
|
|
'dropbox.access_token.uid': { $ne: null }
|
|
|
|
},
|
|
|
|
{ _id: 1 }
|
|
|
|
)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2020-05-19 17:17:45 -04:00
|
|
|
it('post doc with stream origin of docstore', async function() {
|
|
|
|
const docId = '4545345'
|
2019-05-29 05:21:06 -04:00
|
|
|
const path = '/some/path/here.tex'
|
|
|
|
const lines = ['line1', 'line2', 'line3']
|
|
|
|
|
2020-05-19 17:17:45 -04:00
|
|
|
await this.updateSender.promises.addDoc({
|
|
|
|
project_id: projectId,
|
|
|
|
doc_id: docId,
|
2019-05-29 05:21:06 -04:00
|
|
|
path,
|
|
|
|
docLines: lines,
|
2020-05-19 17:17:45 -04:00
|
|
|
project_name: projectName
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
2020-05-19 17:17:45 -04:00
|
|
|
|
2020-06-02 10:02:06 -04:00
|
|
|
const {
|
|
|
|
group: group0,
|
|
|
|
job: job0,
|
|
|
|
method: method0
|
|
|
|
} = this.request.firstCall.args[0].json
|
2020-05-19 17:17:45 -04:00
|
|
|
|
2020-06-02 10:02:06 -04:00
|
|
|
group0.should.equal(userId)
|
|
|
|
method0.should.equal('pipeStreamFrom')
|
|
|
|
job0.method.should.equal('post')
|
2020-05-19 17:17:45 -04:00
|
|
|
const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${userId}/entity/${encodeURIComponent(
|
|
|
|
projectName
|
|
|
|
)}${encodeURIComponent(path)}`
|
2020-06-02 10:02:06 -04:00
|
|
|
job0.uri.should.equal(expectedUrl)
|
|
|
|
job0.streamOrigin.should.equal(
|
2020-05-19 17:17:45 -04:00
|
|
|
`${this.docstoreUrl}/project/${projectId}/doc/${docId}/raw`
|
|
|
|
)
|
2020-06-02 10:02:06 -04:00
|
|
|
job0.headers.sl_all_user_ids.should.eql(JSON.stringify([userId]))
|
|
|
|
|
|
|
|
const { group: group1, job: job1 } = this.request.secondCall.args[0].json
|
2020-06-15 10:52:50 -04:00
|
|
|
group1.should.equal(collaberatorRef)
|
2020-06-02 10:02:06 -04:00
|
|
|
job1.headers.sl_all_user_ids.should.equal(
|
2020-06-15 10:52:50 -04:00
|
|
|
JSON.stringify([collaberatorRef])
|
2020-06-02 10:02:06 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
const { group: group2, job: job2 } = this.request.thirdCall.args[0].json
|
2020-06-15 10:52:50 -04:00
|
|
|
group2.should.equal(readOnlyRef)
|
|
|
|
job2.headers.sl_all_user_ids.should.equal(JSON.stringify([readOnlyRef]))
|
2020-06-05 00:10:46 -04:00
|
|
|
|
|
|
|
this.UserGetter.promises.getUsers.should.have.been.calledOnce.and.calledWith(
|
|
|
|
{
|
|
|
|
_id: {
|
2020-06-15 10:52:50 -04:00
|
|
|
$in: [collaberatorRef, readOnlyRef]
|
2020-06-05 00:10:46 -04:00
|
|
|
},
|
|
|
|
'dropbox.access_token.uid': { $ne: null }
|
|
|
|
},
|
|
|
|
{ _id: 1 }
|
|
|
|
)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2020-05-19 17:17:45 -04:00
|
|
|
it('deleting entity', async function() {
|
2019-05-29 05:21:06 -04:00
|
|
|
const path = '/path/here/t.tex'
|
2020-05-19 17:17:45 -04:00
|
|
|
|
|
|
|
await this.updateSender.promises.deleteEntity({
|
|
|
|
project_id: projectId,
|
|
|
|
path,
|
|
|
|
project_name: projectName
|
|
|
|
})
|
|
|
|
|
2020-06-02 10:02:06 -04:00
|
|
|
const {
|
|
|
|
group: group0,
|
|
|
|
job: job0,
|
|
|
|
method: method0
|
|
|
|
} = this.request.firstCall.args[0].json
|
2020-05-19 17:17:45 -04:00
|
|
|
|
2020-06-02 10:02:06 -04:00
|
|
|
group0.should.equal(userId)
|
|
|
|
method0.should.equal('standardHttpRequest')
|
|
|
|
job0.method.should.equal('delete')
|
2020-05-19 17:17:45 -04:00
|
|
|
const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${userId}/entity/${encodeURIComponent(
|
|
|
|
projectName
|
|
|
|
)}${encodeURIComponent(path)}`
|
2020-06-02 10:02:06 -04:00
|
|
|
job0.headers.sl_all_user_ids.should.eql(JSON.stringify([userId]))
|
|
|
|
job0.uri.should.equal(expectedUrl)
|
|
|
|
|
|
|
|
const { group: group1, job: job1 } = this.request.secondCall.args[0].json
|
2020-06-15 10:52:50 -04:00
|
|
|
group1.should.equal(collaberatorRef)
|
2020-06-02 10:02:06 -04:00
|
|
|
job1.headers.sl_all_user_ids.should.equal(
|
2020-06-15 10:52:50 -04:00
|
|
|
JSON.stringify([collaberatorRef])
|
2020-06-02 10:02:06 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
const { group: group2, job: job2 } = this.request.thirdCall.args[0].json
|
2020-06-15 10:52:50 -04:00
|
|
|
group2.should.equal(readOnlyRef)
|
|
|
|
job2.headers.sl_all_user_ids.should.equal(JSON.stringify([readOnlyRef]))
|
2020-06-05 00:10:46 -04:00
|
|
|
|
|
|
|
this.UserGetter.promises.getUsers.should.have.been.calledOnce.and.calledWith(
|
|
|
|
{
|
|
|
|
_id: {
|
2020-06-15 10:52:50 -04:00
|
|
|
$in: [collaberatorRef, readOnlyRef]
|
2020-06-05 00:10:46 -04:00
|
|
|
},
|
|
|
|
'dropbox.access_token.uid': { $ne: null }
|
|
|
|
},
|
|
|
|
{ _id: 1 }
|
|
|
|
)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2020-05-19 17:17:45 -04:00
|
|
|
it('moving entity', async function() {
|
2019-05-29 05:21:06 -04:00
|
|
|
const startPath = 'staring/here/file.tex'
|
|
|
|
const endPath = 'ending/here/file.tex'
|
2020-05-19 17:17:45 -04:00
|
|
|
|
|
|
|
await this.updateSender.promises.moveEntity({
|
|
|
|
project_id: projectId,
|
2019-05-29 05:21:06 -04:00
|
|
|
startPath,
|
|
|
|
endPath,
|
2020-05-19 17:17:45 -04:00
|
|
|
project_name: projectName
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
2020-05-19 17:17:45 -04:00
|
|
|
|
2020-06-02 10:02:06 -04:00
|
|
|
const {
|
|
|
|
group: group0,
|
|
|
|
job: job0,
|
|
|
|
method: method0
|
|
|
|
} = this.request.firstCall.args[0].json
|
|
|
|
|
|
|
|
group0.should.equal(userId)
|
|
|
|
method0.should.equal('standardHttpRequest')
|
|
|
|
job0.method.should.equal('put')
|
|
|
|
job0.uri.should.equal(
|
|
|
|
`${thirdPartyDataStoreApiUrl}/user/${userId}/entity`
|
|
|
|
)
|
|
|
|
job0.json.startPath.should.equal(`/${projectName}/${startPath}`)
|
|
|
|
job0.json.endPath.should.equal(`/${projectName}/${endPath}`)
|
|
|
|
job0.headers.sl_all_user_ids.should.eql(JSON.stringify([userId]))
|
|
|
|
|
|
|
|
const { group: group1, job: job1 } = this.request.secondCall.args[0].json
|
2020-06-15 10:52:50 -04:00
|
|
|
group1.should.equal(collaberatorRef)
|
2020-06-02 10:02:06 -04:00
|
|
|
job1.headers.sl_all_user_ids.should.equal(
|
2020-06-15 10:52:50 -04:00
|
|
|
JSON.stringify([collaberatorRef])
|
2020-06-02 10:02:06 -04:00
|
|
|
)
|
2020-05-19 17:17:45 -04:00
|
|
|
|
2020-06-02 10:02:06 -04:00
|
|
|
const { group: group2, job: job2 } = this.request.thirdCall.args[0].json
|
2020-06-15 10:52:50 -04:00
|
|
|
group2.should.equal(readOnlyRef)
|
|
|
|
job2.headers.sl_all_user_ids.should.equal(JSON.stringify([readOnlyRef]))
|
2020-06-05 00:10:46 -04:00
|
|
|
|
|
|
|
this.UserGetter.promises.getUsers.should.have.been.calledOnce.and.calledWith(
|
|
|
|
{
|
|
|
|
_id: {
|
2020-06-15 10:52:50 -04:00
|
|
|
$in: [collaberatorRef, readOnlyRef]
|
2020-06-05 00:10:46 -04:00
|
|
|
},
|
|
|
|
'dropbox.access_token.uid': { $ne: null }
|
|
|
|
},
|
|
|
|
{ _id: 1 }
|
|
|
|
)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2020-05-19 17:17:45 -04:00
|
|
|
it('should be able to rename a project using the move entity func', async function() {
|
2019-05-29 05:21:06 -04:00
|
|
|
const oldProjectName = '/oldProjectName/'
|
|
|
|
const newProjectName = '/newProjectName/'
|
2020-05-19 17:17:45 -04:00
|
|
|
|
|
|
|
await this.updateSender.promises.moveEntity({
|
|
|
|
project_id: projectId,
|
2019-05-29 05:21:06 -04:00
|
|
|
project_name: oldProjectName,
|
|
|
|
newProjectName
|
|
|
|
})
|
2020-05-19 17:17:45 -04:00
|
|
|
|
2020-06-02 10:02:06 -04:00
|
|
|
const {
|
|
|
|
group: group0,
|
|
|
|
job: job0,
|
|
|
|
method: method0
|
|
|
|
} = this.request.firstCall.args[0].json
|
|
|
|
|
|
|
|
group0.should.equal(userId)
|
|
|
|
method0.should.equal('standardHttpRequest')
|
|
|
|
job0.method.should.equal('put')
|
|
|
|
job0.uri.should.equal(
|
|
|
|
`${thirdPartyDataStoreApiUrl}/user/${userId}/entity`
|
|
|
|
)
|
|
|
|
job0.json.startPath.should.equal(oldProjectName)
|
|
|
|
job0.json.endPath.should.equal(newProjectName)
|
|
|
|
job0.headers.sl_all_user_ids.should.eql(JSON.stringify([userId]))
|
|
|
|
|
|
|
|
const { group: group1, job: job1 } = this.request.secondCall.args[0].json
|
2020-06-15 10:52:50 -04:00
|
|
|
group1.should.equal(collaberatorRef)
|
2020-06-02 10:02:06 -04:00
|
|
|
job1.headers.sl_all_user_ids.should.equal(
|
2020-06-15 10:52:50 -04:00
|
|
|
JSON.stringify([collaberatorRef])
|
2020-06-02 10:02:06 -04:00
|
|
|
)
|
2020-05-19 17:17:45 -04:00
|
|
|
|
2020-06-02 10:02:06 -04:00
|
|
|
const { group: group2, job: job2 } = this.request.thirdCall.args[0].json
|
2020-06-15 10:52:50 -04:00
|
|
|
group2.should.equal(readOnlyRef)
|
|
|
|
job2.headers.sl_all_user_ids.should.equal(JSON.stringify([readOnlyRef]))
|
2020-06-05 00:10:46 -04:00
|
|
|
|
|
|
|
this.UserGetter.promises.getUsers.should.have.been.calledOnce.and.calledWith(
|
|
|
|
{
|
|
|
|
_id: {
|
2020-06-15 10:52:50 -04:00
|
|
|
$in: [collaberatorRef, readOnlyRef]
|
2020-06-05 00:10:46 -04:00
|
|
|
},
|
|
|
|
'dropbox.access_token.uid': { $ne: null }
|
|
|
|
},
|
|
|
|
{ _id: 1 }
|
|
|
|
)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2020-05-19 17:17:45 -04:00
|
|
|
it('pollDropboxForUser', async function() {
|
|
|
|
await this.updateSender.promises.pollDropboxForUser(userId)
|
|
|
|
|
2020-06-02 10:02:06 -04:00
|
|
|
const {
|
|
|
|
group: group0,
|
|
|
|
job: job0,
|
|
|
|
method: method0
|
|
|
|
} = this.request.firstCall.args[0].json
|
2020-05-19 17:17:45 -04:00
|
|
|
|
2020-06-02 10:02:06 -04:00
|
|
|
group0.should.equal(`poll-dropbox:${userId}`)
|
|
|
|
method0.should.equal('standardHttpRequest')
|
2020-05-19 17:17:45 -04:00
|
|
|
|
2020-06-02 10:02:06 -04:00
|
|
|
job0.method.should.equal('post')
|
|
|
|
job0.uri.should.equal(`${thirdPartyDataStoreApiUrl}/user/poll`)
|
|
|
|
job0.json.user_ids[0].should.equal(userId)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|