mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
add in restore end point
This commit is contained in:
parent
7eb8699b93
commit
83b2aa3082
10 changed files with 229 additions and 5 deletions
|
@ -16,6 +16,8 @@ app.get "/project/:project_id/doc/:doc_id/diff", HttpController.getDiff
|
|||
|
||||
app.get "/project/:project_id/doc/:doc_id/updates", HttpController.getUpdates
|
||||
|
||||
app.post "/project/:project_id/doc/:doc_id/version/:version/restore", HttpController.restore
|
||||
|
||||
app.get "/status", (req, res, next) ->
|
||||
res.send "track-changes is alive"
|
||||
|
||||
|
|
|
@ -15,6 +15,23 @@ module.exports = DocumentUpdaterManager =
|
|||
catch error
|
||||
return callback(error)
|
||||
callback null, body.lines.join("\n"), body.version
|
||||
else
|
||||
error = new Error("doc updater returned a non-success status code: #{res.statusCode}")
|
||||
logger.error err: error, project_id:project_id, doc_id:doc_id, url: url, "error accessing doc updater"
|
||||
callback error
|
||||
|
||||
setDocument: (project_id, doc_id, content, callback = (error) ->) ->
|
||||
url = "#{Settings.apis.documentupdater.url}/project/#{project_id}/doc/#{doc_id}"
|
||||
logger.log project_id:project_id, doc_id: doc_id, "setting doc in document updater"
|
||||
request.post {
|
||||
url: url
|
||||
json:
|
||||
lines: content.split("\n")
|
||||
}, (error, res, body)->
|
||||
if error?
|
||||
return callback(error)
|
||||
if res.statusCode >= 200 and res.statusCode < 300
|
||||
callback null
|
||||
else
|
||||
error = new Error("doc updater returned a non-success status code: #{res.statusCode}")
|
||||
logger.error err: error, project_id:project_id, doc_id:doc_id, url: url, "error accessing doc updater"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
UpdatesManager = require "./UpdatesManager"
|
||||
DiffManager = require "./DiffManager"
|
||||
RestoreManager = require "./RestoreManager"
|
||||
logger = require "logger-sharelatex"
|
||||
|
||||
module.exports = HttpController =
|
||||
|
@ -45,3 +46,10 @@ module.exports = HttpController =
|
|||
v: update.v
|
||||
}
|
||||
res.send JSON.stringify updates: formattedUpdates
|
||||
|
||||
restore: (req, res, next = (error) ->) ->
|
||||
{doc_id, project_id, version} = req.params
|
||||
version = parseInt(version, 10)
|
||||
RestoreManager.restoreToBeforeVersion project_id, doc_id, version, (error) ->
|
||||
return next(error) if error?
|
||||
res.send 204
|
||||
|
|
12
services/track-changes/app/coffee/RestoreManager.coffee
Normal file
12
services/track-changes/app/coffee/RestoreManager.coffee
Normal file
|
@ -0,0 +1,12 @@
|
|||
DocumentUpdaterManager = require "./DocumentUpdaterManager"
|
||||
DiffManager = require "./DiffManager"
|
||||
logger = require "logger-sharelatex"
|
||||
|
||||
module.exports = RestoreManager =
|
||||
restoreToBeforeVersion: (project_id, doc_id, version, callback = (error) ->) ->
|
||||
logger.log project_id: project_id, doc_id: doc_id, version: version, "restoring document"
|
||||
DiffManager.getDocumentBeforeVersion project_id, doc_id, version, (error, content) ->
|
||||
return callback(error) if error?
|
||||
DocumentUpdaterManager.setDocument project_id, doc_id, content, (error) ->
|
||||
return callback(error) if error?
|
||||
callback()
|
|
@ -0,0 +1,67 @@
|
|||
sinon = require "sinon"
|
||||
chai = require("chai")
|
||||
chai.should()
|
||||
expect = chai.expect
|
||||
mongojs = require "../../../app/js/mongojs"
|
||||
db = mongojs.db
|
||||
ObjectId = mongojs.ObjectId
|
||||
Settings = require "settings-sharelatex"
|
||||
|
||||
TrackChangesClient = require "./helpers/TrackChangesClient"
|
||||
MockDocUpdaterApi = require "./helpers/MockDocUpdaterApi"
|
||||
MockWebApi = require "./helpers/MockWebApi"
|
||||
|
||||
describe "Restoring a version", ->
|
||||
before (done) ->
|
||||
sinon.spy MockDocUpdaterApi, "setDoc"
|
||||
|
||||
@now = Date.now()
|
||||
@user_id = ObjectId().toString()
|
||||
@doc_id = ObjectId().toString()
|
||||
@project_id = ObjectId().toString()
|
||||
|
||||
minutes = 60 * 1000
|
||||
|
||||
@updates = [{
|
||||
op: [{ i: "one ", p: 0 }]
|
||||
meta: { ts: @now - 6 * minutes, user_id: @user_id }
|
||||
v: 3
|
||||
}, {
|
||||
op: [{ i: "two ", p: 4 }]
|
||||
meta: { ts: @now - 4 * minutes, user_id: @user_id }
|
||||
v: 4
|
||||
}, {
|
||||
op: [{ i: "three ", p: 8 }]
|
||||
meta: { ts: @now - 2 * minutes, user_id: @user_id }
|
||||
v: 5
|
||||
}, {
|
||||
op: [{ i: "four", p: 14 }]
|
||||
meta: { ts: @now, user_id: @user_id }
|
||||
v: 6
|
||||
}]
|
||||
@lines = ["one two three four"]
|
||||
@restored_lines = ["one two "]
|
||||
@beforeVersion = 5
|
||||
|
||||
MockWebApi.users[@user_id] = @user =
|
||||
email: "user@sharelatex.com"
|
||||
first_name: "Leo"
|
||||
last_name: "Lion"
|
||||
id: @user_id
|
||||
MockDocUpdaterApi.docs[@doc_id] =
|
||||
lines: @lines
|
||||
version: 7
|
||||
|
||||
TrackChangesClient.pushRawUpdates @doc_id, @updates, (error) =>
|
||||
throw error if error?
|
||||
TrackChangesClient.restoreDoc @project_id, @doc_id, @beforeVersion, (error) =>
|
||||
throw error if error?
|
||||
done()
|
||||
|
||||
after () ->
|
||||
MockDocUpdaterApi.setDoc.restore()
|
||||
|
||||
it "should set the doc in the doc updater", ->
|
||||
MockDocUpdaterApi.setDoc
|
||||
.calledWith(@project_id, @doc_id, @restored_lines)
|
||||
.should.equal true
|
|
@ -7,6 +7,11 @@ module.exports = MockDocUpdaterApi =
|
|||
getDoc: (project_id, doc_id, callback = (error) ->) ->
|
||||
callback null, @docs[doc_id]
|
||||
|
||||
setDoc: (project_id, doc_id, lines, callback = (error) ->) ->
|
||||
@docs[doc_id] ||= {}
|
||||
@docs[doc_id].lines = lines
|
||||
callback()
|
||||
|
||||
run: () ->
|
||||
app.get "/project/:project_id/doc/:doc_id", (req, res, next) =>
|
||||
@getDoc req.params.project_id, req.params.doc_id, (error, doc) ->
|
||||
|
@ -17,6 +22,13 @@ module.exports = MockDocUpdaterApi =
|
|||
else
|
||||
res.send JSON.stringify doc
|
||||
|
||||
app.post "/project/:project_id/doc/:doc_id", express.bodyParser(), (req, res, next) =>
|
||||
@setDoc req.params.project_id, req.params.doc_id, req.body.lines, (errr, doc) ->
|
||||
if error?
|
||||
res.send 500
|
||||
else
|
||||
res.send 204
|
||||
|
||||
app.listen 3003, (error) ->
|
||||
throw error if error?
|
||||
|
||||
|
|
|
@ -28,4 +28,11 @@ module.exports = TrackChangesClient =
|
|||
url: "http://localhost:3015/project/#{project_id}/doc/#{doc_id}/updates?to=#{options.to}&limit=#{options.limit}"
|
||||
}, (error, response, body) =>
|
||||
response.statusCode.should.equal 200
|
||||
callback null, JSON.parse(body)
|
||||
callback null, JSON.parse(body)
|
||||
|
||||
restoreDoc: (project_id, doc_id, version, callback = (error) ->) ->
|
||||
request.post {
|
||||
url: "http://localhost:3015/project/#{project_id}/doc/#{doc_id}/version/#{version}/restore"
|
||||
}, (error, response, body) =>
|
||||
response.statusCode.should.equal 204
|
||||
callback null
|
|
@ -46,6 +46,45 @@ describe "DocumentUpdaterManager", ->
|
|||
@request.get = sinon.stub().callsArgWith(1, null, { statusCode: 500 }, "")
|
||||
@DocumentUpdaterManager.getDocument @project_id, @doc_id, @callback
|
||||
|
||||
it "should return the callback with an error", ->
|
||||
@callback
|
||||
.calledWith(new Error("doc updater returned failure status code: 500"))
|
||||
.should.equal true
|
||||
|
||||
describe "setDocument", ->
|
||||
beforeEach ->
|
||||
@content = "mock content"
|
||||
|
||||
describe "successfully", ->
|
||||
beforeEach ->
|
||||
@request.post = sinon.stub().callsArgWith(1, null, {statusCode: 200})
|
||||
@DocumentUpdaterManager.setDocument @project_id, @doc_id, @content, @callback
|
||||
|
||||
it 'should set the document in the document updater', ->
|
||||
url = "#{@settings.apis.documentupdater.url}/project/#{@project_id}/doc/#{@doc_id}"
|
||||
@request.post
|
||||
.calledWith({
|
||||
url: url
|
||||
json:
|
||||
lines: @content.split("\n")
|
||||
}).should.equal true
|
||||
|
||||
it "should call the callback", ->
|
||||
@callback.calledWith(null).should.equal true
|
||||
|
||||
describe "when the document updater API returns an error", ->
|
||||
beforeEach ->
|
||||
@request.post = sinon.stub().callsArgWith(1, @error = new Error("something went wrong"), null, null)
|
||||
@DocumentUpdaterManager.setDocument @project_id, @doc_id, @content, @callback
|
||||
|
||||
it "should return an error to the callback", ->
|
||||
@callback.calledWith(@error).should.equal true
|
||||
|
||||
describe "when the document updater returns a failure error code", ->
|
||||
beforeEach ->
|
||||
@request.post = sinon.stub().callsArgWith(1, null, { statusCode: 500 }, "")
|
||||
@DocumentUpdaterManager.setDocument @project_id, @doc_id, @content, @callback
|
||||
|
||||
it "should return the callback with an error", ->
|
||||
@callback
|
||||
.calledWith(new Error("doc updater returned failure status code: 500"))
|
||||
|
|
|
@ -11,9 +11,9 @@ describe "HttpController", ->
|
|||
"logger-sharelatex": { log: sinon.stub() }
|
||||
"./UpdatesManager": @UpdatesManager = {}
|
||||
"./DiffManager": @DiffManager = {}
|
||||
"./RestoreManager": @RestoreManager = {}
|
||||
@doc_id = "doc-id-123"
|
||||
@project_id = "project-id-123"
|
||||
@version = 42
|
||||
@next = sinon.stub()
|
||||
|
||||
describe "flushUpdatesWithLock", ->
|
||||
|
@ -36,8 +36,8 @@ describe "HttpController", ->
|
|||
|
||||
describe "getDiff", ->
|
||||
beforeEach ->
|
||||
@from = Date.now() - 10000
|
||||
@to = Date.now()
|
||||
@from = 42
|
||||
@to = 45
|
||||
@req =
|
||||
params:
|
||||
doc_id: @doc_id
|
||||
|
@ -61,7 +61,7 @@ describe "HttpController", ->
|
|||
|
||||
describe "getUpdates", ->
|
||||
beforeEach ->
|
||||
@to = Date.now()
|
||||
@to = 42
|
||||
@limit = 10
|
||||
@req =
|
||||
params:
|
||||
|
@ -93,3 +93,25 @@ describe "HttpController", ->
|
|||
v: @v
|
||||
}
|
||||
@res.send.calledWith(JSON.stringify(updates: updates)).should.equal true
|
||||
|
||||
describe "RestoreManager", ->
|
||||
beforeEach ->
|
||||
@version = "42"
|
||||
@req =
|
||||
params:
|
||||
doc_id: @doc_id
|
||||
project_id: @project_id
|
||||
version: @version
|
||||
@res =
|
||||
send: sinon.stub()
|
||||
|
||||
@RestoreManager.restoreToBeforeVersion = sinon.stub().callsArg(3)
|
||||
@HttpController.restore @req, @res, @next
|
||||
|
||||
it "should restore the document", ->
|
||||
@RestoreManager.restoreToBeforeVersion
|
||||
.calledWith(@project_id, @doc_id, parseInt(@version, 10))
|
||||
.should.equal true
|
||||
|
||||
it "should return a success code", ->
|
||||
@res.send.calledWith(204).should.equal true
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
sinon = require('sinon')
|
||||
chai = require('chai')
|
||||
should = chai.should()
|
||||
expect = chai.expect
|
||||
modulePath = "../../../../app/js/RestoreManager.js"
|
||||
SandboxedModule = require('sandboxed-module')
|
||||
|
||||
describe "RestoreManager", ->
|
||||
beforeEach ->
|
||||
@RestoreManager = SandboxedModule.require modulePath, requires:
|
||||
"logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub() }
|
||||
"./DocumentUpdaterManager": @DocumentUpdaterManager = {}
|
||||
"./DiffManager": @DiffManager = {}
|
||||
@callback = sinon.stub()
|
||||
@project_id = "mock-project-id"
|
||||
@doc_id = "mock-doc-id"
|
||||
@version = 42
|
||||
|
||||
describe "restoreToBeforeVersion", ->
|
||||
beforeEach ->
|
||||
@content = "mock content"
|
||||
@DocumentUpdaterManager.setDocument = sinon.stub().callsArg(3)
|
||||
@DiffManager.getDocumentBeforeVersion = sinon.stub().callsArgWith(3, null, @content)
|
||||
@RestoreManager.restoreToBeforeVersion @project_id, @doc_id, @version, @callback
|
||||
|
||||
it "should get the content before the requested version", ->
|
||||
@DiffManager.getDocumentBeforeVersion
|
||||
.calledWith(@project_id, @doc_id, @version)
|
||||
.should.equal true
|
||||
|
||||
it "should set the document in the document updater", ->
|
||||
@DocumentUpdaterManager.setDocument
|
||||
.calledWith(@project_id, @doc_id, @content)
|
||||
.should.equal true
|
||||
|
||||
it "should call the callback", ->
|
||||
@callback.called.should.equal true
|
||||
|
Loading…
Reference in a new issue