mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Add ExportsHander for project exports performed via v1
This commit is contained in:
parent
859858c02c
commit
a661084485
2 changed files with 295 additions and 0 deletions
|
@ -0,0 +1,93 @@
|
|||
ProjectGetter = require('../Project/ProjectGetter')
|
||||
ProjectLocator = require('../Project/ProjectLocator')
|
||||
UserGetter = require('../User/UserGetter')
|
||||
logger = require('logger-sharelatex')
|
||||
settings = require 'settings-sharelatex'
|
||||
async = require 'async'
|
||||
request = require 'request'
|
||||
request = request.defaults()
|
||||
settings = require 'settings-sharelatex'
|
||||
|
||||
module.exports = ExportsHandler = self =
|
||||
|
||||
exportProject: (project_id, user_id, brand_variation_id, callback=(error, export_data) ->) ->
|
||||
self._buildExport project_id, user_id, brand_variation_id, (err, export_data) ->
|
||||
return callback(err) if err?
|
||||
self._requestExport export_data, (err, export_v1_id) ->
|
||||
return callback(err) if err?
|
||||
export_data.v1_id = export_v1_id
|
||||
# TODO: possibly store the export data in Mongo
|
||||
callback null, export_data
|
||||
|
||||
_buildExport: (project_id, user_id, brand_variation_id, callback=(err, export_data) ->) ->
|
||||
jobs =
|
||||
project: (cb) ->
|
||||
ProjectGetter.getProject project_id, cb
|
||||
# TODO: when we update async, signature will change from (cb, results) to (results, cb)
|
||||
rootDoc: [ 'project', (cb, results) ->
|
||||
ProjectLocator.findRootDoc {project: results.project, project_id: project_id}, cb
|
||||
]
|
||||
user: (cb) ->
|
||||
UserGetter.getUser user_id, {first_name: 1, last_name: 1, email: 1}, cb
|
||||
historyVersion: (cb) ->
|
||||
self._requestVersion project_id, cb
|
||||
|
||||
async.auto jobs, (err, results) ->
|
||||
if err?
|
||||
logger.err err:err, project_id:project_id, user_id:user_id, brand_variation_id:brand_variation_id, "error building project export"
|
||||
return callback(err)
|
||||
|
||||
{project, rootDoc, user, historyVersion} = results
|
||||
if !rootDoc[1]?
|
||||
err = new Error("cannot export project without root doc")
|
||||
logger.err err:err, project_id: project_id
|
||||
return callback(err)
|
||||
|
||||
export_data =
|
||||
project:
|
||||
id: project_id
|
||||
rootDocPath: rootDoc[1]?.fileSystem
|
||||
historyId: project.overleaf?.history?.id
|
||||
historyVersion: historyVersion
|
||||
user:
|
||||
id: user_id
|
||||
firstName: user.first_name
|
||||
lastName: user.last_name
|
||||
email: user.email
|
||||
orcidId: null # until v2 gets ORCID
|
||||
destination:
|
||||
brandVariationId: brand_variation_id
|
||||
options:
|
||||
callbackUrl: null # for now, until we want v1 to call us back
|
||||
callback null, export_data
|
||||
|
||||
_requestExport: (export_data, callback=(err, export_v1_id) ->) ->
|
||||
request.post {
|
||||
url: "#{settings.apis.v1.url}/api/v1/sharelatex/exports"
|
||||
auth: {user: settings.apis.v1.user, pass: settings.apis.v1.pass }
|
||||
json: export_data
|
||||
}, (err, res, body) ->
|
||||
if err?
|
||||
logger.err err:err, export:export_data, "error making request to v1 export"
|
||||
callback err
|
||||
else if 200 <= res.statusCode < 300
|
||||
callback null, body.exportId
|
||||
else
|
||||
err = new Error("v1 export returned a failure status code: #{res.statusCode}")
|
||||
logger.err err:err, export:export_data, "v1 export returned failure status code: #{res.statusCode}"
|
||||
callback err
|
||||
|
||||
_requestVersion: (project_id, callback=(err, export_v1_id) ->) ->
|
||||
request.get {
|
||||
url: "#{settings.apis.project_history.url}/project/#{project_id}/version"
|
||||
json: true
|
||||
}, (err, res, body) ->
|
||||
if err?
|
||||
logger.err err:err, project_id:project_id, "error making request to project history"
|
||||
callback err
|
||||
else if res.statusCode >= 200 and res.statusCode < 300
|
||||
callback null, body.version
|
||||
else
|
||||
err = new Error("project history version returned a failure status code: #{res.statusCode}")
|
||||
logger.err err:err, project_id:project_id, "project history version returned failure status code: #{res.statusCode}"
|
||||
callback err
|
202
services/web/test/unit/coffee/Exports/ExportsHandlerTests.coffee
Normal file
202
services/web/test/unit/coffee/Exports/ExportsHandlerTests.coffee
Normal file
|
@ -0,0 +1,202 @@
|
|||
sinon = require('sinon')
|
||||
chai = require('chai')
|
||||
should = chai.should()
|
||||
expect = chai.expect
|
||||
modulePath = '../../../../app/js/Features/Exports/ExportsHandler.js'
|
||||
SandboxedModule = require('sandboxed-module')
|
||||
|
||||
describe 'ExportsHandler', ->
|
||||
|
||||
beforeEach ->
|
||||
@ProjectGetter = {}
|
||||
@ProjectLocator = {}
|
||||
@UserGetter = {}
|
||||
@settings = {}
|
||||
@stubRequest = {}
|
||||
@request = defaults: => return @stubRequest
|
||||
@ExportsHandler = SandboxedModule.require modulePath, requires:
|
||||
'logger-sharelatex':
|
||||
log: ->
|
||||
err: ->
|
||||
'../Project/ProjectGetter': @ProjectGetter
|
||||
'../Project/ProjectLocator': @ProjectLocator
|
||||
'../User/UserGetter': @UserGetter
|
||||
'settings-sharelatex': @settings
|
||||
'request': @request
|
||||
@project_id = "project-id-123"
|
||||
@project_history_id = 987
|
||||
@user_id = "user-id-456"
|
||||
@brand_variation_id = 789
|
||||
@callback = sinon.stub()
|
||||
|
||||
describe 'exportProject', ->
|
||||
beforeEach (done) ->
|
||||
@export_data = {iAmAnExport: true}
|
||||
@response_body = {iAmAResponseBody: true}
|
||||
@ExportsHandler._buildExport = sinon.stub().yields(null, @export_data)
|
||||
@ExportsHandler._requestExport = sinon.stub().yields(null, @response_body)
|
||||
@ExportsHandler.exportProject @project_id, @user_id, @brand_variation_id, (error, export_data) =>
|
||||
@callback(error, export_data)
|
||||
done()
|
||||
|
||||
it "should build the export", ->
|
||||
@ExportsHandler._buildExport
|
||||
.calledWith(@project_id, @user_id, @brand_variation_id)
|
||||
.should.equal true
|
||||
|
||||
it "should request the export", ->
|
||||
@ExportsHandler._requestExport
|
||||
.calledWith(@export_data)
|
||||
.should.equal true
|
||||
|
||||
it "should return the export", ->
|
||||
@callback
|
||||
.calledWith(null, @export_data)
|
||||
.should.equal true
|
||||
|
||||
describe '_buildExport', ->
|
||||
beforeEach (done) ->
|
||||
@project =
|
||||
id: @project_id
|
||||
overleaf:
|
||||
history:
|
||||
id: @project_history_id
|
||||
@user =
|
||||
id: @user_id
|
||||
first_name: 'Arthur'
|
||||
last_name: 'Author'
|
||||
email: 'arthur.author@arthurauthoring.org'
|
||||
@rootDocPath = 'main.tex'
|
||||
@historyVersion = 777
|
||||
@ProjectGetter.getProject = sinon.stub().yields(null, @project)
|
||||
@ProjectLocator.findRootDoc = sinon.stub().yields(null, [null, {fileSystem: 'main.tex'}])
|
||||
@UserGetter.getUser = sinon.stub().yields(null, @user)
|
||||
@ExportsHandler._requestVersion = sinon.stub().yields(null, @historyVersion)
|
||||
done()
|
||||
|
||||
describe "when all goes well", ->
|
||||
beforeEach (done) ->
|
||||
@ExportsHandler._buildExport @project_id, @user_id, @brand_variation_id, (error, export_data) =>
|
||||
@callback(error, export_data)
|
||||
done()
|
||||
|
||||
it "should request the project history version", ->
|
||||
@ExportsHandler._requestVersion.called
|
||||
.should.equal true
|
||||
|
||||
it "should return export data", ->
|
||||
expected_export_data =
|
||||
project:
|
||||
id: @project_id
|
||||
rootDocPath: @rootDocPath
|
||||
historyId: @project_history_id
|
||||
historyVersion: @historyVersion
|
||||
user:
|
||||
id: @user_id
|
||||
firstName: @user.first_name
|
||||
lastName: @user.last_name
|
||||
email: @user.email
|
||||
orcidId: null
|
||||
destination:
|
||||
brandVariationId: @brand_variation_id
|
||||
options:
|
||||
callbackUrl: null
|
||||
@callback.calledWith(null, expected_export_data)
|
||||
.should.equal true
|
||||
|
||||
describe "when project is not found", ->
|
||||
beforeEach (done) ->
|
||||
@ProjectGetter.getProject = sinon.stub().yields(new Error("project not found"))
|
||||
@ExportsHandler._buildExport @project_id, @user_id, @brand_variation_id, (error, export_data) =>
|
||||
@callback(error, export_data)
|
||||
done()
|
||||
|
||||
it "should return an error", ->
|
||||
(@callback.args[0][0] instanceof Error)
|
||||
.should.equal true
|
||||
|
||||
describe "when project has no root doc", ->
|
||||
beforeEach (done) ->
|
||||
@ProjectLocator.findRootDoc = sinon.stub().yields(null, [null, null])
|
||||
@ExportsHandler._buildExport @project_id, @user_id, @brand_variation_id, (error, export_data) =>
|
||||
@callback(error, export_data)
|
||||
done()
|
||||
|
||||
it "should return an error", ->
|
||||
(@callback.args[0][0] instanceof Error)
|
||||
.should.equal true
|
||||
|
||||
describe "when user is not found", ->
|
||||
beforeEach (done) ->
|
||||
@UserGetter.getUser = sinon.stub().yields(new Error("user not found"))
|
||||
@ExportsHandler._buildExport @project_id, @user_id, @brand_variation_id, (error, export_data) =>
|
||||
@callback(error, export_data)
|
||||
done()
|
||||
|
||||
it "should return an error", ->
|
||||
(@callback.args[0][0] instanceof Error)
|
||||
.should.equal true
|
||||
|
||||
describe "when project history request fails", ->
|
||||
beforeEach (done) ->
|
||||
@ExportsHandler._requestVersion = sinon.stub().yields(new Error("project history call failed"))
|
||||
@ExportsHandler._buildExport @project_id, @user_id, @brand_variation_id, (error, export_data) =>
|
||||
@callback(error, export_data)
|
||||
done()
|
||||
|
||||
it "should return an error", ->
|
||||
(@callback.args[0][0] instanceof Error)
|
||||
.should.equal true
|
||||
|
||||
describe '_requestExport', ->
|
||||
beforeEach (done) ->
|
||||
@settings.apis =
|
||||
v1:
|
||||
url: 'http://localhost:5000'
|
||||
user: 'overleaf'
|
||||
pass: 'pass'
|
||||
@export_data = {iAmAnExport: true}
|
||||
@export_id = 4096
|
||||
@stubPost = sinon.stub().yields(null, {statusCode: 200}, { exportId: @export_id })
|
||||
done()
|
||||
|
||||
describe "when all goes well", ->
|
||||
beforeEach (done) ->
|
||||
@stubRequest.post = @stubPost
|
||||
@ExportsHandler._requestExport @export_data, (error, export_v1_id) =>
|
||||
@callback(error, export_v1_id)
|
||||
done()
|
||||
|
||||
it 'should issue the request', ->
|
||||
expect(@stubPost.getCall(0).args[0]).to.deep.equal
|
||||
url: @settings.apis.v1.url + '/api/v1/sharelatex/exports'
|
||||
auth:
|
||||
user: @settings.apis.v1.user
|
||||
pass: @settings.apis.v1.pass
|
||||
json: @export_data
|
||||
|
||||
it 'should return the v1 export id', ->
|
||||
@callback.calledWith(null, @export_id)
|
||||
.should.equal true
|
||||
|
||||
describe "when the request fails", ->
|
||||
beforeEach (done) ->
|
||||
@stubRequest.post = sinon.stub().yields(new Error("export request failed"))
|
||||
@ExportsHandler._requestExport @export_data, (error, export_v1_id) =>
|
||||
@callback(error, export_v1_id)
|
||||
done()
|
||||
|
||||
it "should return an error", ->
|
||||
(@callback.args[0][0] instanceof Error)
|
||||
.should.equal true
|
||||
|
||||
describe "when the request returns an error code", ->
|
||||
beforeEach (done) ->
|
||||
@stubRequest.post = sinon.stub().yields(null, {statusCode: 401}, { })
|
||||
@ExportsHandler._requestExport @export_data, (error, export_v1_id) =>
|
||||
@callback(error, export_v1_id)
|
||||
done()
|
||||
|
||||
it "should return the error", ->
|
||||
(@callback.args[0][0] instanceof Error)
|
||||
.should.equal true
|
Loading…
Reference in a new issue