Implement restore end point with acceptance tests

This commit is contained in:
James Allen
2018-03-09 16:36:10 +00:00
parent beee86f1ce
commit 3832850be6
4 changed files with 143 additions and 16 deletions

View File

@@ -3,6 +3,8 @@ Path = require 'path'
FileWriter = require '../../infrastructure/FileWriter'
FileSystemImportManager = require '../Uploads/FileSystemImportManager'
ProjectLocator = require '../Project/ProjectLocator'
Errors = require '../Errors/Errors'
moment = require 'moment'
module.exports = RestoreManager =
restoreFile: (user_id, project_id, version, pathname, callback = (error) ->) ->
@@ -12,18 +14,41 @@ module.exports = RestoreManager =
dirname = Path.dirname(pathname)
if dirname == '.' # no directory
dirname = ''
ProjectLocator.findElementByPath {project_id, path: dirname}, (error, element, type) ->
RestoreManager._findFolderOrRootFolderId project_id, dirname, (error, parent_folder_id) ->
return callback(error) if error?
# We're going to try to recover the file into the folder it was in previously,
# but this is historical, so the folder may not exist anymore. Fallback to the
# root folder if not (parent_folder_id == null will default to this)
if type == 'folder' and element?
parent_folder_id = element._id
RestoreManager._addEntityWithUniqueName user_id, project_id, parent_folder_id, basename, fsPath, callback
_findFolderOrRootFolderId: (project_id, dirname, callback = (error, folder_id) ->) ->
# We're going to try to recover the file into the folder it was in previously,
# but this is historical, so the folder may not exist anymore. Fallback to the
# root folder if not (folder_id == null)
ProjectLocator.findElementByPath {project_id, path: dirname}, (error, element, type) ->
if error? and not error instanceof Errors.NotFoundError
return callback(error)
if type == 'folder' and element?
return callback(null, element._id)
else
return callback(null, null)
_addEntityWithUniqueName: (user_id, project_id, parent_folder_id, basename, fsPath, callback = (error) ->) ->
FileSystemImportManager.addEntity user_id, project_id, parent_folder_id, basename, fsPath, false, (error, entity) ->
if error?
console.log "ERROR", error, error instanceof Errors.InvalidNameError
if error instanceof Errors.InvalidNameError
# likely a duplicate name, so try with a prefix
date = moment(new Date()).format('Do MMM YY H:mm:ss')
# Move extension to the end so the file type is preserved
extension = Path.extname(basename)
basename = Path.basename(basename, extension)
basename = "#{basename} (Restored on #{date})"
if extension != ''
basename = "#{basename}#{extension}"
FileSystemImportManager.addEntity user_id, project_id, parent_folder_id, basename, fsPath, false, callback
else
parent_folder_id = null
# TODO if we get a name conflict error from here, then retry with a timestamp appended
FileSystemImportManager.addEntity user_id, project_id, parent_folder_id, basename, fsPath, false, callback
callback(error)
else
callback()
_writeFileVersionToDisk: (project_id, version, pathname, callback = (error, fsPath) ->) ->
url = "#{Settings.apis.project_history.url}/project/#{project_id}/version/#{version}/#{pathname}"
url = "#{Settings.apis.project_history.url}/project/#{project_id}/version/#{version}/#{encodeURIComponent(pathname)}"
FileWriter.writeUrlToDisk project_id, url, callback

View File

@@ -21,7 +21,7 @@ describe "LinkedFiles", ->
before (done) ->
LinkedUrlProxy.listen 6543, (error) =>
return done(error) if error?
@owner = new User()
@owner = new User()
@owner.login done
describe "creating a URL based linked file", ->

View File

@@ -1,11 +1,13 @@
async = require "async"
expect = require("chai").expect
_ = require 'underscore'
ProjectGetter = require "../../../app/js/Features/Project/ProjectGetter.js"
User = require "./helpers/User"
MockProjectHistoryApi = require "./helpers/MockProjectHistoryApi"
MockDocstoreApi = require "./helpers/MockDocstoreApi"
MockFileStoreApi = require "./helpers/MockFileStoreApi"
describe "RestoringFiles", ->
before (done) ->
@@ -30,7 +32,7 @@ describe "RestoringFiles", ->
expect(response.statusCode).to.equal 204
done()
it "should have created a doc", ->
it "should have created a doc", (done) ->
@owner.getProject @project_id, (error, project) =>
throw error if error?
doc = _.find project.rootFolder[0].docs, (doc) ->
@@ -42,10 +44,111 @@ describe "RestoringFiles", ->
done()
describe "restoring a binary file", ->
it "should have created a file"
beforeEach (done) ->
MockProjectHistoryApi.addOldFile(@project_id, 42, "image.png", "Mock image.png content")
@owner.request {
method: "POST",
url: "/project/#{@project_id}/restore_file",
json:
pathname: "image.png"
version: 42
}, (error, response, body) ->
throw error if error?
expect(response.statusCode).to.equal 204
done()
it "should have created a file", (done) ->
@owner.getProject @project_id, (error, project) =>
throw error if error?
file = _.find project.rootFolder[0].fileRefs, (file) ->
file.name == 'image.png'
file = MockFileStoreApi.files[@project_id][file._id]
expect(file.content).to.equal "Mock image.png content"
done()
describe "restoring to a directory that exists", ->
beforeEach (done) ->
MockProjectHistoryApi.addOldFile(@project_id, 42, "foldername/foo2.tex", "hello world, this is foo-2.tex!")
@owner.request.post {
uri: "project/#{@project_id}/folder",
json:
name: 'foldername'
}, (error, response, body) =>
throw error if error?
expect(response.statusCode).to.equal 200
@owner.request {
method: "POST",
url: "/project/#{@project_id}/restore_file",
json:
pathname: "foldername/foo2.tex"
version: 42
}, (error, response, body) ->
throw error if error?
expect(response.statusCode).to.equal 204
done()
it "should have created the doc in the named folder", (done) ->
@owner.getProject @project_id, (error, project) =>
throw error if error?
folder = _.find project.rootFolder[0].folders, (folder) ->
folder.name == 'foldername'
doc = _.find folder.docs, (doc) ->
doc.name == 'foo2.tex'
doc = MockDocstoreApi.docs[@project_id][doc._id]
expect(doc.lines).to.deep.equal [
"hello world, this is foo-2.tex!"
]
done()
describe "restoring to a directory that no longer exists", ->
it "should have created the file in the root folder"
beforeEach (done) ->
MockProjectHistoryApi.addOldFile(@project_id, 42, "nothere/foo3.tex", "hello world, this is foo-3.tex!")
@owner.request {
method: "POST",
url: "/project/#{@project_id}/restore_file",
json:
pathname: "nothere/foo3.tex"
version: 42
}, (error, response, body) ->
throw error if error?
expect(response.statusCode).to.equal 204
done()
it "should have created the doc in the root folder", (done) ->
@owner.getProject @project_id, (error, project) =>
throw error if error?
doc = _.find project.rootFolder[0].docs, (doc) ->
doc.name == 'foo3.tex'
doc = MockDocstoreApi.docs[@project_id][doc._id]
expect(doc.lines).to.deep.equal [
"hello world, this is foo-3.tex!"
]
done()
describe "restoring to a filename that already exists", ->
it "should have created the file with a timestamp appended"
it "should have created the file with a timestamp appended", ->
beforeEach (done) ->
MockProjectHistoryApi.addOldFile(@project_id, 42, "main.tex", "hello world, this is main.tex!")
@owner.request {
method: "POST",
url: "/project/#{@project_id}/restore_file",
json:
pathname: "main.tex"
version: 42
}, (error, response, body) ->
throw error if error?
expect(response.statusCode).to.equal 204
done()
it "should have created the doc in the root folder", (done) ->
@owner.getProject @project_id, (error, project) =>
throw error if error?
doc = _.find project.rootFolder[0].docs, (doc) ->
doc.name.match(/main \(Restored on/)
expect(doc).to.exist
doc = MockDocstoreApi.docs[@project_id][doc._id]
expect(doc.lines).to.deep.equal [
"hello world, this is main.tex!"
]
done()

View File

@@ -16,7 +16,6 @@ module.exports = MockProjectHistoryApi =
app.get "/project/:project_id/version/:version/:pathname", (req, res, next) =>
{project_id, version, pathname} = req.params
key = "#{project_id}:#{version}:#{pathname}"
console.log key, @oldFiles, @oldFiles[key]
if @oldFiles[key]?
res.send @oldFiles[key]
else