overleaf/services/docstore/test/acceptance/coffee/ArchiveDocsTests.coffee

388 lines
30 KiB
CoffeeScript
Raw Normal View History

2015-06-01 17:24:40 -04:00
sinon = require "sinon"
chai = require("chai")
2015-06-02 18:24:45 -04:00
should = chai.should()
2017-03-30 12:13:43 -04:00
{db, ObjectId, ISODate} = require "../../../app/js/mongojs"
2015-06-01 17:24:40 -04:00
async = require "async"
2015-06-02 15:29:32 -04:00
Settings = require("settings-sharelatex")
2017-03-30 12:13:43 -04:00
DocArchiveManager = require("../../../app/js/DocArchiveManager.js")
request = require "request"
2015-06-01 17:24:40 -04:00
DocstoreClient = require "./helpers/DocstoreClient"
2015-08-13 17:48:17 -04:00
2016-12-05 09:21:49 -05:00
describe "Archiving", ->
2017-03-30 12:13:43 -04:00
describe "multiple docs in a project", ->
before (done) ->
@project_id = ObjectId()
@docs = [{
_id: ObjectId()
lines: ["one", "two", "three"]
ranges: {}
version: 2
}, {
_id: ObjectId()
lines: ["aaa", "bbb", "ccc"]
ranges: {}
version: 4
}]
jobs = for doc in @docs
do (doc) =>
(callback) =>
DocstoreClient.createDoc @project_id, doc._id, doc.lines, doc.version, doc.ranges, callback
async.series jobs, (error) =>
throw error if error?
DocstoreClient.archiveAllDoc @project_id, (error, @res) =>
done()
2015-08-13 17:48:17 -04:00
it "should archive all the docs", (done) ->
@res.statusCode.should.equal 204
done()
2015-06-02 19:08:50 -04:00
2017-03-30 12:13:43 -04:00
it "should set inS3 and unset lines and ranges in each doc", (done) ->
jobs = for doc in @docs
do (doc) =>
2015-08-13 17:48:17 -04:00
(callback) =>
2017-03-30 12:13:43 -04:00
db.docs.findOne _id: doc._id, (error, doc) =>
2015-08-13 17:48:17 -04:00
should.not.exist doc.lines
2017-03-30 12:13:43 -04:00
should.not.exist doc.ranges
2015-08-13 17:48:17 -04:00
doc.inS3.should.equal true
callback()
async.series jobs, done
2017-03-30 12:13:43 -04:00
it "should set the docs in s3 correctly", (done) ->
jobs = for doc in @docs
do (doc) =>
2015-08-13 17:48:17 -04:00
(callback) =>
2017-03-30 12:13:43 -04:00
DocstoreClient.getS3Doc @project_id, doc._id, (error, res, s3_doc) =>
s3_doc.lines.should.deep.equal doc.lines
s3_doc.ranges.should.deep.equal doc.ranges
2015-08-13 17:48:17 -04:00
callback()
async.series jobs, done
2017-03-30 12:13:43 -04:00
describe "after unarchiving from a request for the project", ->
before (done) ->
DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) =>
throw error if error?
done()
it "should return the docs", (done) ->
for doc, i in @fetched_docs
doc.lines.should.deep.equal @docs[i].lines
done()
it "should restore the docs to mongo", (done) ->
jobs = for doc, i in @docs
do (doc, i) =>
(callback) =>
db.docs.findOne _id: doc._id, (error, doc) =>
doc.lines.should.deep.equal @docs[i].lines
doc.ranges.should.deep.equal @docs[i].ranges
should.not.exist doc.inS3
callback()
async.series jobs, done
describe "a deleted doc", ->
before (done) ->
@project_id = ObjectId()
@doc = {
_id: ObjectId()
lines: ["one", "two", "three"]
ranges: {}
version: 2
}
DocstoreClient.createDoc @project_id, @doc._id, @doc.lines, @doc.version, @doc.ranges, (error) =>
throw error if error?
DocstoreClient.deleteDoc @project_id, @doc._id, (error) =>
throw error if error?
DocstoreClient.archiveAllDoc @project_id, (error, @res) =>
throw error if error?
done()
it "should successully archive the docs", (done) ->
@res.statusCode.should.equal 204
done()
2015-08-13 17:48:17 -04:00
2017-03-30 12:13:43 -04:00
it "should set inS3 and unset lines and ranges in each doc", (done) ->
db.docs.findOne _id: @doc._id, (error, doc) =>
throw error if error?
should.not.exist doc.lines
should.not.exist doc.ranges
doc.inS3.should.equal true
doc.deleted.should.equal true
done()
it "should set the doc in s3 correctly", (done) ->
DocstoreClient.getS3Doc @project_id, @doc._id, (error, res, s3_doc) =>
throw error if error?
s3_doc.lines.should.deep.equal @doc.lines
s3_doc.ranges.should.deep.equal @doc.ranges
done()
describe "after unarchiving from a request for the project", ->
before (done) ->
DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) =>
throw error if error?
done()
it "should not included the deleted", (done) ->
@fetched_docs.length.should.equal 0
done()
it "should restore the doc to mongo", (done) ->
db.docs.findOne _id: @doc._id, (error, doc) =>
throw error if error?
doc.lines.should.deep.equal @doc.lines
doc.ranges.should.deep.equal @doc.ranges
should.not.exist doc.inS3
doc.deleted.should.equal true
done()
describe "a doc with large lines", ->
before (done) ->
@project_id = ObjectId()
@timeout 1000 * 30
quarterMegInBytes = 250000
big_line = require("crypto").randomBytes(quarterMegInBytes).toString("hex")
@doc = {
_id: ObjectId()
lines: [big_line, big_line, big_line, big_line]
ranges: {}
version: 2
}
DocstoreClient.createDoc @project_id, @doc._id, @doc.lines, @doc.version, @doc.ranges, (error) =>
throw error if error?
2015-08-13 17:48:17 -04:00
DocstoreClient.archiveAllDoc @project_id, (error, @res) =>
2017-03-30 12:13:43 -04:00
throw error if error?
2015-08-13 17:48:17 -04:00
done()
2017-03-30 12:13:43 -04:00
it "should successully archive the docs", (done) ->
2015-08-13 17:48:17 -04:00
@res.statusCode.should.equal 204
done()
2017-03-30 12:13:43 -04:00
it "should set inS3 and unset lines and ranges in each doc", (done) ->
db.docs.findOne _id: @doc._id, (error, doc) =>
throw error if error?
should.not.exist doc.lines
should.not.exist doc.ranges
doc.inS3.should.equal true
done()
2015-08-13 17:48:17 -04:00
2017-03-30 12:13:43 -04:00
it "should set the doc in s3 correctly", (done) ->
DocstoreClient.getS3Doc @project_id, @doc._id, (error, res, s3_doc) =>
throw error if error?
s3_doc.lines.should.deep.equal @doc.lines
s3_doc.ranges.should.deep.equal @doc.ranges
done()
describe "after unarchiving from a request for the project", ->
before (done) ->
DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) =>
throw error if error?
done()
it "should restore the doc to mongo", (done) ->
db.docs.findOne _id: @doc._id, (error, doc) =>
throw error if error?
doc.lines.should.deep.equal @doc.lines
doc.ranges.should.deep.equal @doc.ranges
should.not.exist doc.inS3
done()
describe "a doc with naughty strings", ->
before (done) ->
@project_id = ObjectId()
@doc = {
_id: ObjectId()
lines: [ "", "undefined", "undef", "null", "NULL", "(null)", "nil", "NIL", "true", "false", "True", "False", "None", "\\", "\\\\", "0", "1", "1.00", "$1.00", "1/2", "1E2", "1E02", "1E+02", "-1", "-1.00", "-$1.00", "-1/2", "-1E2", "-1E02", "-1E+02", "1/0", "0/0", "-2147483648/-1", "-9223372036854775808/-1", "0.00", "0..0", ".", "0.0.0", "0,00", "0,,0", ",", "0,0,0", "0.0/0", "1.0/0.0", "0.0/0.0", "1,0/0,0", "0,0/0,0", "--1", "-", "-.", "-,", "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", "NaN", "Infinity", "-Infinity", "0x0", "0xffffffff", "0xffffffffffffffff", "0xabad1dea", "123456789012345678901234567890123456789", "1,000.00", "1 000.00", "1'000.00", "1,000,000.00", "1 000 000.00", "1'000'000.00", "1.000,00", "1 000,00", "1'000,00", "1.000.000,00", "1 000i̳̞v̢͇ḙ͎͟-҉̭̩̼͔m̤̭̫i͕͇̝̦n̗͙ḍ̟ ̯̲͕͞ǫ̟̯̰̲͙̻̝f ̪̰̰̗̖̭̘͘c̦͍̲̞͍̩̙ḥ͚a̮͎̟̙͜ơ̩̹͎s̤.̝̝ ҉Z̡̖̜͖̰̣͉̜a͖̰͙̬͡l̲̫̳͍̩g̡̟̼̱͚̞̬ͅo̗͜.̟", "̦H̬̤̗̤͝e͜ ̜̥̝̻͍̟́w̕h̖̯͓o̝͙̖͎̱̮ ҉̺̙̞̟͈W̷̼̭a̺̪͍į͈͕̭͙̯̜t̶̼̮s̘͙͖̕ ̠̫̠B̻͍͙͉̳ͅe̵h̵̬͇̫͙i̹͓̳̳̮͎̫̕n͟d̴̪̜̖ ̰͉̩͇͙̲͞ͅT͖̼͓̪͢h͏͓̮̻e̬̝̟ͅ ̤̹̝W͙̞̝͔͇͝ͅa͏͓͔̹̼̣l̴͔̰̤̟͔ḽ̫.͕", "Z̮̞̠͙͔ͅḀ̗̞͈̻̗Ḷ͙͎̯̹̞͓G̻O̭̗̮", "˙ɐnbᴉlɐ ɐuƃɐɯ ǝɹolop ʇǝ ǝɹoqɐl ʇn ʇunpᴉpᴉɔuᴉ ɹodɯǝʇ poɯsnᴉǝ op pǝs 'ʇᴉlǝ ƃuᴉɔsᴉdᴉpɐ ɹnʇǝʇɔǝsuoɔ 'ʇǝɯɐ ʇᴉs ɹolop ɯnsdᴉ ɯǝɹo˥", "00˙Ɩ$-", " ", "𝐓𝐡𝐞 𝐪𝐮𝐢𝐜𝐤 𝐛𝐫𝐨𝐰𝐧 𝐟𝐨𝐱 𝐣𝐮𝐦𝐩𝐬 𝐨𝐯𝐞𝐫 𝐭𝐡𝐞 𝐥𝐚𝐳𝐲 𝐝𝐨𝐠", "𝕿𝖍𝖊 𝖖𝖚𝖎𝖈𝖐 𝖇𝖗𝖔𝖜𝖓 𝖋𝖔𝖝 𝖏𝖚𝖒𝖕𝖘 𝖔𝖛𝖊𝖗 𝖙𝖍𝖊 𝖑𝖆𝖟𝖞 𝖉𝖔𝖌", "𝑻𝒉𝒆 𝒒𝒖𝒊𝒄𝒌 𝒃𝒓𝒐𝒘𝒏 𝒇𝒐𝒙 𝒋𝒖𝒎𝒑𝒔 𝒐𝒗𝒆𝒓 𝒕𝒉𝒆 𝒍𝒂𝒛𝒚 𝒅𝒐𝒈", "𝓣𝓱𝓮 𝓺𝓾𝓲𝓬𝓴 𝓫𝓻𝓸𝔀𝓷 𝓯𝓸𝔁 𝓳𝓾𝓶𝓹𝓼 𝓸𝓿𝓮𝓻 𝓽𝓱𝓮 𝓵𝓪𝔃𝔂 𝓭𝓸𝓰", "𝕋𝕙𝕖 𝕢𝕦𝕚𝕔𝕜 𝕓𝕣𝕠𝕨𝕟 𝕗𝕠𝕩 𝕛𝕦𝕞𝕡𝕤 𝕠𝕧𝕖𝕣 𝕥𝕙𝕖 𝕝𝕒𝕫𝕪 𝕕𝕠𝕘", "𝚃𝚑𝚎 𝚚𝚞𝚒𝚌𝚔 𝚋𝚛𝚘𝚠𝚗 𝚏𝚘𝚡 𝚓𝚞𝚖𝚙𝚜 𝚘𝚟𝚎𝚛 𝚝𝚑𝚎 𝚕𝚊𝚣𝚢 𝚍𝚘𝚐", "⒯⒣⒠ ⒬⒰⒤⒞⒦ ⒝⒭⒪⒲⒩ ⒡⒪⒳ ⒥⒰⒨⒫⒮ ⒪⒱⒠⒭ ⒯⒣⒠ ⒧⒜⒵⒴ ⒟⒪⒢", "<script>alert(123)</script>", "&lt;script&gt;alert(&#39;123&#39;);&lt;/script&gt;", "<img src=x onerror=alert(123) />", "<svg><script>123<1>alert(123)</script> ", "\"><script>alert(123)</script>", "'><script>alert(123)</script>", "><script>alert(123)</script>", "</script><script>alert(123)</script>", "< / script >< script >alert(123)< / script >", " onfocus=JaVaSCript:alert(123) autofocus ", "\" onfocus=JaVaSCript:alert(123) autofocus ", "' onfocus=JaVaSCript:alert(123) autofocus ", "scriptalert(123)/script", "<sc<script>ript>alert(123)</sc</script>ript>", "--><script>alert(123)</script>", "\";alert(123);t=\"", "';alert(123);t='", "JavaSCript:alert(123)", ";alert(123);", "src=JaVaSCript:prompt(132)", "\"><script>alert(123);</script x=\"", "'><script>alert(123);</script x='", "><script>alert(123);</script x=", "\" autofocus onkeyup=\"javascript:alert(123)", "' autofocus onkeyup='javascript:alert(123)", "<script\\x20type=\"text/javascript\">javascript:alert(1);</script>", "<script\\x3Etype=\"text/javascript\">javascript:alert(1);</script>", "<script\\x0Dtype=\"text/javascript\">javascript:alert(1);</script>", "<script\\x09type=\"text/javascript\">javascript:alert(1);</script>", "<script\\x0Ctype=\"text/javascript\">javascript:alert(1);</script>", "<script\\x2Ftype=\"text/javascript\">javascript:alert(1);</script>", "<script\\x0Atype=\"t
ranges: {}
version: 2
}
DocstoreClient.createDoc @project_id, @doc._id, @doc.lines, @doc.version, @doc.ranges, (error) =>
throw error if error?
DocstoreClient.archiveAllDoc @project_id, (error, @res) =>
throw error if error?
done()
it "should successully archive the docs", (done) ->
@res.statusCode.should.equal 204
done()
2015-08-13 17:48:17 -04:00
2017-03-30 12:13:43 -04:00
it "should set inS3 and unset lines and ranges in each doc", (done) ->
db.docs.findOne _id: @doc._id, (error, doc) =>
throw error if error?
should.not.exist doc.lines
should.not.exist doc.ranges
doc.inS3.should.equal true
done()
2015-08-13 17:48:17 -04:00
2017-03-30 12:13:43 -04:00
it "should set the doc in s3 correctly", (done) ->
DocstoreClient.getS3Doc @project_id, @doc._id, (error, res, s3_doc) =>
throw error if error?
s3_doc.lines.should.deep.equal @doc.lines
s3_doc.ranges.should.deep.equal @doc.ranges
done()
describe "after unarchiving from a request for the project", ->
before (done) ->
DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) =>
throw error if error?
done()
it "should restore the doc to mongo", (done) ->
db.docs.findOne _id: @doc._id, (error, doc) =>
throw error if error?
doc.lines.should.deep.equal @doc.lines
doc.ranges.should.deep.equal @doc.ranges
should.not.exist doc.inS3
done()
2015-08-13 17:48:17 -04:00
2017-03-30 12:13:43 -04:00
describe "a doc with ranges", ->
before (done) ->
@project_id = ObjectId()
@doc = {
_id: ObjectId()
lines: ["one", "two", "three"]
ranges: {
changes:
[{
id : ObjectId(),
op : { "i" : "foo", "p" : 24 }
metadata : { "user_id" : ObjectId(), "ts" : new Date("2017-01-27T16:10:44.194Z") }
}, {
id : ObjectId(),
op : { "d" : "bar", "p" : 50 }
metadata : { "user_id" : ObjectId(), "ts" : new Date("2017-01-27T18:10:44.194Z") }
}]
comments: [{
id: ObjectId(),
op: { "c" : "comment", "p" : 284, "t" : ObjectId() },
metadata: { "user_id" : ObjectId(), "ts" : new Date("2017-01-26T14:22:04.869Z") }
}]
}
version: 2
}
DocstoreClient.createDoc @project_id, @doc._id, @doc.lines, @doc.version, @doc.ranges, (error) =>
throw error if error?
2015-08-13 17:48:17 -04:00
DocstoreClient.archiveAllDoc @project_id, (error, @res) =>
2017-03-30 12:13:43 -04:00
throw error if error?
2015-08-13 17:48:17 -04:00
done()
2017-03-30 12:13:43 -04:00
it "should successully archive the docs", (done) ->
2015-08-13 17:48:17 -04:00
@res.statusCode.should.equal 204
done()
2017-03-30 12:13:43 -04:00
it "should set inS3 and unset lines and ranges in each doc", (done) ->
db.docs.findOne _id: @doc._id, (error, doc) =>
throw error if error?
should.not.exist doc.lines
should.not.exist doc.ranges
doc.inS3.should.equal true
done()
2015-08-13 17:48:17 -04:00
2017-03-30 12:13:43 -04:00
it "should set the doc in s3 correctly", (done) ->
DocstoreClient.getS3Doc @project_id, @doc._id, (error, res, s3_doc) =>
throw error if error?
s3_doc.lines.should.deep.equal @doc.lines
ranges = JSON.parse(JSON.stringify(@doc.ranges)) # ObjectId -> String
s3_doc.ranges.should.deep.equal ranges
done()
describe "after unarchiving from a request for the project", ->
before (done) ->
DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) =>
throw error if error?
done()
it "should restore the doc to mongo", (done) ->
db.docs.findOne _id: @doc._id, (error, doc) =>
throw error if error?
doc.lines.should.deep.equal @doc.lines
doc.ranges.should.deep.equal @doc.ranges
should.not.exist doc.inS3
done()
describe "a doc that is archived twice", ->
before (done) ->
@project_id = ObjectId()
@doc = {
_id: ObjectId()
lines: ["abc", "def", "ghi"]
ranges: {}
version: 2
}
DocstoreClient.createDoc @project_id, @doc._id, @doc.lines, @doc.version, @doc.ranges, (error) =>
throw error if error?
DocstoreClient.archiveAllDoc @project_id, (error, @res) =>
throw error if error?
@res.statusCode.should.equal 204
DocstoreClient.archiveAllDoc @project_id, (error, @res) =>
throw error if error?
@res.statusCode.should.equal 204
done()
2015-08-13 17:48:17 -04:00
2017-03-30 12:13:43 -04:00
it "should set inS3 and unset lines and ranges in each doc", (done) ->
db.docs.findOne _id: @doc._id, (error, doc) =>
throw error if error?
should.not.exist doc.lines
should.not.exist doc.ranges
doc.inS3.should.equal true
done()
it "should set the doc in s3 correctly", (done) ->
DocstoreClient.getS3Doc @project_id, @doc._id, (error, res, s3_doc) =>
throw error if error?
s3_doc.lines.should.deep.equal @doc.lines
s3_doc.ranges.should.deep.equal @doc.ranges
done()
describe "after unarchiving from a request for the project", ->
before (done) ->
DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) =>
throw error if error?
done()
it "should restore the doc to mongo", (done) ->
db.docs.findOne _id: @doc._id, (error, doc) =>
2015-08-13 17:48:17 -04:00
throw error if error?
2017-03-30 12:13:43 -04:00
doc.lines.should.deep.equal @doc.lines
doc.ranges.should.deep.equal @doc.ranges
should.not.exist doc.inS3
2015-08-13 17:48:17 -04:00
done()
2017-03-30 12:13:43 -04:00
describe "a doc with the old schema (just an array of lines)", ->
before (done) ->
@project_id = ObjectId()
@doc = {
_id: ObjectId()
lines: ["abc", "def", "ghi"]
ranges: {}
version: 2
}
options = DocArchiveManager.buildS3Options("#{@project_id}/#{@doc._id}")
options.json = @doc.lines
request.put options, (error, res, body) =>
throw error if error?
res.statusCode.should.equal 200
db.docs.insert {
project_id: @project_id
_id: @doc._id
rev: @doc.version
inS3: true
}, (error) =>
throw error if error?
DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) =>
throw error if error?
done()
it "should restore the doc to mongo", (done) ->
db.docs.findOne _id: @doc._id, (error, doc) =>
throw error if error?
doc.lines.should.deep.equal @doc.lines
should.not.exist doc.inS3
done()
it "should return the doc", (done) ->
@fetched_docs[0].lines.should.deep.equal @doc.lines
done()
2017-03-09 13:18:50 -05:00