ArchiveDocsTests.js 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239
  1. /* eslint-disable
  2. no-unused-vars,
  3. */
  4. // TODO: This file was created by bulk-decaffeinate.
  5. // Fix any style issues and re-enable lint.
  6. /*
  7. * decaffeinate suggestions:
  8. * DS101: Remove unnecessary use of Array.from
  9. * DS102: Remove unnecessary code created because of implicit returns
  10. * DS207: Consider shorter variations of null checks
  11. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  12. */
  13. const Settings = require('@overleaf/settings')
  14. const { expect } = require('chai')
  15. const { db, ObjectId } = require('../../../app/js/mongodb')
  16. const async = require('async')
  17. const DocstoreApp = require('./helpers/DocstoreApp')
  18. const DocstoreClient = require('./helpers/DocstoreClient')
  19. const { Storage } = require('@google-cloud/storage')
  20. const Persistor = require('../../../app/js/PersistorManager')
  21. const { ReadableString } = require('@overleaf/stream-utils')
  22. function uploadContent(path, json, callback) {
  23. const stream = new ReadableString(JSON.stringify(json))
  24. Persistor.sendStream(Settings.docstore.bucket, path, stream)
  25. .then(() => callback())
  26. .catch(callback)
  27. }
  28. describe('Archiving', function () {
  29. before(function (done) {
  30. return DocstoreApp.ensureRunning(done)
  31. })
  32. before(async function () {
  33. const storage = new Storage(Settings.docstore.gcs.endpoint)
  34. await storage.createBucket(Settings.docstore.bucket)
  35. await storage.createBucket(`${Settings.docstore.bucket}-deleted`)
  36. })
  37. after(async function () {
  38. // Tear down the buckets created above
  39. const storage = new Storage(Settings.docstore.gcs.endpoint)
  40. await storage.bucket(Settings.docstore.bucket).deleteFiles()
  41. await storage.bucket(Settings.docstore.bucket).delete()
  42. await storage.bucket(`${Settings.docstore.bucket}-deleted`).deleteFiles()
  43. await storage.bucket(`${Settings.docstore.bucket}-deleted`).delete()
  44. })
  45. describe('multiple docs in a project', function () {
  46. before(function (done) {
  47. this.project_id = new ObjectId()
  48. this.docs = [
  49. {
  50. _id: new ObjectId(),
  51. lines: ['one', 'two', 'three'],
  52. ranges: {},
  53. version: 2,
  54. },
  55. {
  56. _id: new ObjectId(),
  57. lines: ['aaa', 'bbb', 'ccc'],
  58. ranges: {},
  59. version: 4,
  60. },
  61. ]
  62. const jobs = Array.from(this.docs).map(doc =>
  63. (doc => {
  64. return callback => {
  65. return DocstoreClient.createDoc(
  66. this.project_id,
  67. doc._id,
  68. doc.lines,
  69. doc.version,
  70. doc.ranges,
  71. callback
  72. )
  73. }
  74. })(doc)
  75. )
  76. return async.series(jobs, error => {
  77. if (error != null) {
  78. throw error
  79. }
  80. return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => {
  81. if (error) return done(error)
  82. this.res = res
  83. return done()
  84. })
  85. })
  86. })
  87. it('should archive all the docs', function (done) {
  88. this.res.statusCode.should.equal(204)
  89. return done()
  90. })
  91. it('should set inS3 and unset lines and ranges in each doc', function (done) {
  92. const jobs = Array.from(this.docs).map(doc =>
  93. (doc => {
  94. return callback => {
  95. return db.docs.findOne({ _id: doc._id }, (error, doc) => {
  96. if (error) return callback(error)
  97. expect(doc.lines).not.to.exist
  98. expect(doc.ranges).not.to.exist
  99. doc.inS3.should.equal(true)
  100. return callback()
  101. })
  102. }
  103. })(doc)
  104. )
  105. return async.series(jobs, done)
  106. })
  107. it('should set the docs in s3 correctly', function (done) {
  108. const jobs = Array.from(this.docs).map(doc =>
  109. (doc => {
  110. return callback => {
  111. return DocstoreClient.getS3Doc(
  112. this.project_id,
  113. doc._id,
  114. (error, s3Doc) => {
  115. if (error) return callback(error)
  116. s3Doc.lines.should.deep.equal(doc.lines)
  117. s3Doc.ranges.should.deep.equal(doc.ranges)
  118. callback()
  119. }
  120. )
  121. }
  122. })(doc)
  123. )
  124. return async.series(jobs, done)
  125. })
  126. return describe('after unarchiving from a request for the project', function () {
  127. before(function (done) {
  128. return DocstoreClient.getAllDocs(
  129. this.project_id,
  130. (error, res, fetchedDocs) => {
  131. this.fetched_docs = fetchedDocs
  132. if (error != null) {
  133. throw error
  134. }
  135. return done()
  136. }
  137. )
  138. })
  139. it('should return the docs', function (done) {
  140. for (let i = 0; i < this.fetched_docs.length; i++) {
  141. const doc = this.fetched_docs[i]
  142. doc.lines.should.deep.equal(this.docs[i].lines)
  143. }
  144. return done()
  145. })
  146. return it('should restore the docs to mongo', function (done) {
  147. const jobs = Array.from(this.docs).map((doc, i) =>
  148. ((doc, i) => {
  149. return callback => {
  150. return db.docs.findOne({ _id: doc._id }, (error, doc) => {
  151. if (error) return callback(error)
  152. doc.lines.should.deep.equal(this.docs[i].lines)
  153. doc.ranges.should.deep.equal(this.docs[i].ranges)
  154. expect(doc.inS3).not.to.exist
  155. return callback()
  156. })
  157. }
  158. })(doc, i)
  159. )
  160. return async.series(jobs, done)
  161. })
  162. })
  163. })
  164. describe('a deleted doc', function () {
  165. beforeEach(function (done) {
  166. this.project_id = new ObjectId()
  167. this.doc = {
  168. _id: new ObjectId(),
  169. lines: ['one', 'two', 'three'],
  170. ranges: {},
  171. version: 2,
  172. }
  173. return DocstoreClient.createDoc(
  174. this.project_id,
  175. this.doc._id,
  176. this.doc.lines,
  177. this.doc.version,
  178. this.doc.ranges,
  179. error => {
  180. if (error != null) {
  181. throw error
  182. }
  183. return DocstoreClient.deleteDoc(
  184. this.project_id,
  185. this.doc._id,
  186. error => {
  187. if (error != null) {
  188. throw error
  189. }
  190. return DocstoreClient.archiveAllDoc(
  191. this.project_id,
  192. (error, res) => {
  193. this.res = res
  194. if (error != null) {
  195. throw error
  196. }
  197. return done()
  198. }
  199. )
  200. }
  201. )
  202. }
  203. )
  204. })
  205. it('should successully archive the docs', function (done) {
  206. this.res.statusCode.should.equal(204)
  207. return done()
  208. })
  209. it('should set inS3 and unset lines and ranges in each doc', function (done) {
  210. return db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
  211. if (error != null) {
  212. throw error
  213. }
  214. expect(doc.lines).not.to.exist
  215. expect(doc.ranges).not.to.exist
  216. doc.inS3.should.equal(true)
  217. doc.deleted.should.equal(true)
  218. return done()
  219. })
  220. })
  221. it('should set the doc in s3 correctly', function (done) {
  222. return DocstoreClient.getS3Doc(
  223. this.project_id,
  224. this.doc._id,
  225. (error, s3Doc) => {
  226. if (error != null) {
  227. throw error
  228. }
  229. s3Doc.lines.should.deep.equal(this.doc.lines)
  230. s3Doc.ranges.should.deep.equal(this.doc.ranges)
  231. return done()
  232. }
  233. )
  234. })
  235. describe('after unarchiving from a request for the project', function () {
  236. beforeEach(function (done) {
  237. return DocstoreClient.getAllDocs(
  238. this.project_id,
  239. (error, res, fetchedDocs) => {
  240. this.fetched_docs = fetchedDocs
  241. if (error != null) {
  242. throw error
  243. }
  244. return done()
  245. }
  246. )
  247. })
  248. it('should not included the deleted', function (done) {
  249. this.fetched_docs.length.should.equal(0)
  250. return done()
  251. })
  252. return it('should restore the doc to mongo', function (done) {
  253. return db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
  254. if (error != null) {
  255. throw error
  256. }
  257. doc.lines.should.deep.equal(this.doc.lines)
  258. doc.ranges.should.deep.equal(this.doc.ranges)
  259. expect(doc.inS3).not.to.exist
  260. doc.deleted.should.equal(true)
  261. return done()
  262. })
  263. })
  264. })
  265. describe('when keepSoftDeletedDocsArchived is enabled', function () {
  266. let keepSoftDeletedDocsArchived
  267. beforeEach(function overwriteSetting() {
  268. keepSoftDeletedDocsArchived =
  269. Settings.docstore.keepSoftDeletedDocsArchived
  270. Settings.docstore.keepSoftDeletedDocsArchived = true
  271. })
  272. afterEach(function restoreSetting() {
  273. Settings.docstore.keepSoftDeletedDocsArchived =
  274. keepSoftDeletedDocsArchived
  275. })
  276. describe('after unarchiving from a request for the project', function () {
  277. beforeEach(function (done) {
  278. DocstoreClient.getAllDocs(
  279. this.project_id,
  280. (error, res, fetchedDocs) => {
  281. this.fetched_docs = fetchedDocs
  282. if (error) {
  283. return done(error)
  284. }
  285. done()
  286. }
  287. )
  288. })
  289. it('should not included the deleted', function (done) {
  290. this.fetched_docs.length.should.equal(0)
  291. done()
  292. })
  293. it('should not have restored the deleted doc to mongo', function (done) {
  294. db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
  295. if (error) {
  296. return done(error)
  297. }
  298. expect(doc.lines).to.not.exist
  299. expect(doc.ranges).to.not.exist
  300. expect(doc.inS3).to.equal(true)
  301. expect(doc.deleted).to.equal(true)
  302. done()
  303. })
  304. })
  305. })
  306. })
  307. })
  308. describe('archiving a single doc', function () {
  309. before(function (done) {
  310. this.project_id = new ObjectId()
  311. this.timeout(1000 * 30)
  312. this.doc = {
  313. _id: new ObjectId(),
  314. lines: ['foo', 'bar'],
  315. ranges: {},
  316. version: 2,
  317. }
  318. DocstoreClient.createDoc(
  319. this.project_id,
  320. this.doc._id,
  321. this.doc.lines,
  322. this.doc.version,
  323. this.doc.ranges,
  324. error => {
  325. if (error) {
  326. return done(error)
  327. }
  328. DocstoreClient.archiveDoc(
  329. this.project_id,
  330. this.doc._id,
  331. (error, res) => {
  332. this.res = res
  333. if (error) {
  334. return done(error)
  335. }
  336. done()
  337. }
  338. )
  339. }
  340. )
  341. })
  342. it('should successully archive the doc', function (done) {
  343. this.res.statusCode.should.equal(204)
  344. done()
  345. })
  346. it('should set inS3 and unset lines and ranges in the doc', function (done) {
  347. db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
  348. if (error) {
  349. return done(error)
  350. }
  351. expect(doc.lines).not.to.exist
  352. expect(doc.ranges).not.to.exist
  353. doc.inS3.should.equal(true)
  354. done()
  355. })
  356. })
  357. it('should set the doc in s3 correctly', function (done) {
  358. DocstoreClient.getS3Doc(this.project_id, this.doc._id, (error, s3Doc) => {
  359. if (error) {
  360. return done(error)
  361. }
  362. s3Doc.lines.should.deep.equal(this.doc.lines)
  363. s3Doc.ranges.should.deep.equal(this.doc.ranges)
  364. done()
  365. })
  366. })
  367. })
  368. describe('a doc with large lines', function () {
  369. before(function (done) {
  370. this.project_id = new ObjectId()
  371. this.timeout(1000 * 30)
  372. const quarterMegInBytes = 250000
  373. const bigLine = require('crypto')
  374. .randomBytes(quarterMegInBytes)
  375. .toString('hex')
  376. this.doc = {
  377. _id: new ObjectId(),
  378. lines: [bigLine, bigLine, bigLine, bigLine],
  379. ranges: {},
  380. version: 2,
  381. }
  382. return DocstoreClient.createDoc(
  383. this.project_id,
  384. this.doc._id,
  385. this.doc.lines,
  386. this.doc.version,
  387. this.doc.ranges,
  388. error => {
  389. if (error != null) {
  390. throw error
  391. }
  392. return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => {
  393. this.res = res
  394. if (error != null) {
  395. throw error
  396. }
  397. return done()
  398. })
  399. }
  400. )
  401. })
  402. it('should successully archive the docs', function (done) {
  403. this.res.statusCode.should.equal(204)
  404. return done()
  405. })
  406. it('should set inS3 and unset lines and ranges in each doc', function (done) {
  407. return db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
  408. if (error != null) {
  409. throw error
  410. }
  411. expect(doc.lines).not.to.exist
  412. expect(doc.ranges).not.to.exist
  413. doc.inS3.should.equal(true)
  414. return done()
  415. })
  416. })
  417. it('should set the doc in s3 correctly', function (done) {
  418. return DocstoreClient.getS3Doc(
  419. this.project_id,
  420. this.doc._id,
  421. (error, s3Doc) => {
  422. if (error != null) {
  423. throw error
  424. }
  425. s3Doc.lines.should.deep.equal(this.doc.lines)
  426. s3Doc.ranges.should.deep.equal(this.doc.ranges)
  427. return done()
  428. }
  429. )
  430. })
  431. return describe('after unarchiving from a request for the project', function () {
  432. before(function (done) {
  433. return DocstoreClient.getAllDocs(
  434. this.project_id,
  435. (error, res, fetchedDocs) => {
  436. this.fetched_docs = fetchedDocs
  437. if (error != null) {
  438. throw error
  439. }
  440. return done()
  441. }
  442. )
  443. })
  444. return it('should restore the doc to mongo', function (done) {
  445. return db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
  446. if (error != null) {
  447. throw error
  448. }
  449. doc.lines.should.deep.equal(this.doc.lines)
  450. doc.ranges.should.deep.equal(this.doc.ranges)
  451. expect(doc.inS3).not.to.exist
  452. return done()
  453. })
  454. })
  455. })
  456. })
  457. describe('a doc with naughty strings', function () {
  458. before(function (done) {
  459. this.project_id = new ObjectId()
  460. this.doc = {
  461. _id: new ObjectId(),
  462. lines: [
  463. '',
  464. 'undefined',
  465. 'undef',
  466. 'null',
  467. 'NULL',
  468. '(null)',
  469. 'nil',
  470. 'NIL',
  471. 'true',
  472. 'false',
  473. 'True',
  474. 'False',
  475. 'None',
  476. '\\',
  477. '\\\\',
  478. '0',
  479. '1',
  480. '1.00',
  481. '$1.00',
  482. '1/2',
  483. '1E2',
  484. '1E02',
  485. '1E+02',
  486. '-1',
  487. '-1.00',
  488. '-$1.00',
  489. '-1/2',
  490. '-1E2',
  491. '-1E02',
  492. '-1E+02',
  493. '1/0',
  494. '0/0',
  495. '-2147483648/-1',
  496. '-9223372036854775808/-1',
  497. '0.00',
  498. '0..0',
  499. '.',
  500. '0.0.0',
  501. '0,00',
  502. '0,,0',
  503. ',',
  504. '0,0,0',
  505. '0.0/0',
  506. '1.0/0.0',
  507. '0.0/0.0',
  508. '1,0/0,0',
  509. '0,0/0,0',
  510. '--1',
  511. '-',
  512. '-.',
  513. '-,',
  514. '999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999',
  515. 'NaN',
  516. 'Infinity',
  517. '-Infinity',
  518. '0x0',
  519. '0xffffffff',
  520. '0xffffffffffffffff',
  521. '0xabad1dea',
  522. '123456789012345678901234567890123456789',
  523. '1,000.00',
  524. '1 000.00',
  525. "1'000.00",
  526. '1,000,000.00',
  527. '1 000 000.00',
  528. "1'000'000.00",
  529. '1.000,00',
  530. '1 000,00',
  531. "1'000,00",
  532. '1.000.000,00',
  533. '1 000i̳̞v̢͇ḙ͎͟-҉̭̩̼͔m̤̭̫i͕͇̝̦n̗͙ḍ̟ ̯̲͕͞ǫ̟̯̰̲͙̻̝f ̪̰̰̗̖̭̘͘c̦͍̲̞͍̩̙ḥ͚a̮͎̟̙͜ơ̩̹͎s̤.̝̝ ҉Z̡̖̜͖̰̣͉̜a͖̰͙̬͡l̲̫̳͍̩g̡̟̼̱͚̞̬ͅo̗͜.̟',
  534. '̦H̬̤̗̤͝e͜ ̜̥̝̻͍̟́w̕h̖̯͓o̝͙̖͎̱̮ ҉̺̙̞̟͈W̷̼̭a̺̪͍į͈͕̭͙̯̜t̶̼̮s̘͙͖̕ ̠̫̠B̻͍͙͉̳ͅe̵h̵̬͇̫͙i̹͓̳̳̮͎̫̕n͟d̴̪̜̖ ̰͉̩͇͙̲͞ͅT͖̼͓̪͢h͏͓̮̻e̬̝̟ͅ ̤̹̝W͙̞̝͔͇͝ͅa͏͓͔̹̼̣l̴͔̰̤̟͔ḽ̫.͕',
  535. 'Z̮̞̠͙͔ͅḀ̗̞͈̻̗Ḷ͙͎̯̹̞͓G̻O̭̗̮',
  536. "˙ɐ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˥",
  537. '00˙Ɩ$-',
  538. 'The quick brown fox jumps over the lazy dog',
  539. '𝐓𝐡𝐞 𝐪𝐮𝐢𝐜𝐤 𝐛𝐫𝐨𝐰𝐧 𝐟𝐨𝐱 𝐣𝐮𝐦𝐩𝐬 𝐨𝐯𝐞𝐫 𝐭𝐡𝐞 𝐥𝐚𝐳𝐲 𝐝𝐨𝐠',
  540. '𝕿𝖍𝖊 𝖖𝖚𝖎𝖈𝖐 𝖇𝖗𝖔𝖜𝖓 𝖋𝖔𝖝 𝖏𝖚𝖒𝖕𝖘 𝖔𝖛𝖊𝖗 𝖙𝖍𝖊 𝖑𝖆𝖟𝖞 𝖉𝖔𝖌',
  541. '𝑻𝒉𝒆 𝒒𝒖𝒊𝒄𝒌 𝒃𝒓𝒐𝒘𝒏 𝒇𝒐𝒙 𝒋𝒖𝒎𝒑𝒔 𝒐𝒗𝒆𝒓 𝒕𝒉𝒆 𝒍𝒂𝒛𝒚 𝒅𝒐𝒈',
  542. '𝓣𝓱𝓮 𝓺𝓾𝓲𝓬𝓴 𝓫𝓻𝓸𝔀𝓷 𝓯𝓸𝔁 𝓳𝓾𝓶𝓹𝓼 𝓸𝓿𝓮𝓻 𝓽𝓱𝓮 𝓵𝓪𝔃𝔂 𝓭𝓸𝓰',
  543. '𝕋𝕙𝕖 𝕢𝕦𝕚𝕔𝕜 𝕓𝕣𝕠𝕨𝕟 𝕗𝕠𝕩 𝕛𝕦𝕞𝕡𝕤 𝕠𝕧𝕖𝕣 𝕥𝕙𝕖 𝕝𝕒𝕫𝕪 𝕕𝕠𝕘',
  544. '𝚃𝚑𝚎 𝚚𝚞𝚒𝚌𝚔 𝚋𝚛𝚘𝚠𝚗 𝚏𝚘𝚡 𝚓𝚞𝚖𝚙𝚜 𝚘𝚟𝚎𝚛 𝚝𝚑𝚎 𝚕𝚊𝚣𝚢 𝚍𝚘𝚐',
  545. '⒯⒣⒠ ⒬⒰⒤⒞⒦ ⒝⒭⒪⒲⒩ ⒡⒪⒳ ⒥⒰⒨⒫⒮ ⒪⒱⒠⒭ ⒯⒣⒠ ⒧⒜⒵⒴ ⒟⒪⒢',
  546. '<script>alert(123)</script>',
  547. '&lt;script&gt;alert(&#39;123&#39;);&lt;/script&gt;',
  548. '<img src=x onerror=alert(123) />',
  549. '<svg><script>123<1>alert(123)</script> ',
  550. '"><script>alert(123)</script>',
  551. "'><script>alert(123)</script>",
  552. '><script>alert(123)</script>',
  553. '</script><script>alert(123)</script>',
  554. '< / script >< script >alert(123)< / script >',
  555. ' onfocus=JaVaSCript:alert(123) autofocus ',
  556. '" onfocus=JaVaSCript:alert(123) autofocus ',
  557. "' onfocus=JaVaSCript:alert(123) autofocus ",
  558. '<script>alert(123)</script>',
  559. '<sc<script>ript>alert(123)</sc</script>ript>',
  560. '--><script>alert(123)</script>',
  561. '";alert(123);t="',
  562. "';alert(123);t='",
  563. 'JavaSCript:alert(123)',
  564. ';alert(123);',
  565. 'src=JaVaSCript:prompt(132)',
  566. '"><script>alert(123);</script x="',
  567. "'><script>alert(123);</script x='",
  568. '><script>alert(123);</script x=',
  569. '" autofocus onkeyup="javascript:alert(123)',
  570. "' autofocus onkeyup='javascript:alert(123)",
  571. '<script\\x20type="text/javascript">javascript:alert(1);</script>',
  572. '<script\\x3Etype="text/javascript">javascript:alert(1);</script>',
  573. '<script\\x0Dtype="text/javascript">javascript:alert(1);</script>',
  574. '<script\\x09type="text/javascript">javascript:alert(1);</script>',
  575. '<script\\x0Ctype="text/javascript">javascript:alert(1);</script>',
  576. '<script\\x2Ftype="text/javascript">javascript:alert(1);</script>',
  577. '<script\\x0Atype="text/javascript">javascript:alert(1);</script>',
  578. '\'`"><\\x3Cscript>javascript:alert(1)</script> ',
  579. '\'`"><\\x00script>javascript:alert(1)</script>',
  580. 'ABC<div style="x\\x3Aexpression(javascript:alert(1)">DEF',
  581. 'ABC<div style="x:expression\\x5C(javascript:alert(1)">DEF',
  582. 'ABC<div style="x:expression\\x00(javascript:alert(1)">DEF',
  583. 'ABC<div style="x:exp\\x00ression(javascript:alert(1)">DEF',
  584. 'ABC<div style="x:exp\\x5Cression(javascript:alert(1)">DEF',
  585. 'ABC<div style="x:\\x0Aexpression(javascript:alert(1)">DEF',
  586. 'ABC<div style="x:\\x09expression(javascript:alert(1)">DEF',
  587. 'ABC<div style="x:\\xE3\\x80\\x80expression(javascript:alert(1)">DEF',
  588. 'ABC<div style="x:\\xE2\\x80\\x84expression(javascript:alert(1)">DEF',
  589. 'ABC<div style="x:\\xC2\\xA0expression(javascript:alert(1)">DEF',
  590. 'ABC<div style="x:\\xE2\\x80\\x80expression(javascript:alert(1)">DEF',
  591. 'ABC<div style="x:\\xE2\\x80\\x8Aexpression(javascript:alert(1)">DEF',
  592. 'ABC<div style="x:\\x0Dexpression(javascript:alert(1)">DEF',
  593. 'ABC<div style="x:\\x0Cexpression(javascript:alert(1)">DEF',
  594. 'ABC<div style="x:\\xE2\\x80\\x87expression(javascript:alert(1)">DEF',
  595. 'ABC<div style="x:\\xEF\\xBB\\xBFexpression(javascript:alert(1)">DEF',
  596. 'ABC<div style="x:\\x20expression(javascript:alert(1)">DEF',
  597. 'ABC<div style="x:\\xE2\\x80\\x88expression(javascript:alert(1)">DEF',
  598. 'ABC<div style="x:\\x00expression(javascript:alert(1)">DEF',
  599. 'ABC<div style="x:\\xE2\\x80\\x8Bexpression(javascript:alert(1)">DEF',
  600. 'ABC<div style="x:\\xE2\\x80\\x86expression(javascript:alert(1)">DEF',
  601. 'ABC<div style="x:\\xE2\\x80\\x85expression(javascript:alert(1)">DEF',
  602. 'ABC<div style="x:\\xE2\\x80\\x82expression(javascript:alert(1)">DEF',
  603. 'ABC<div style="x:\\x0Bexpression(javascript:alert(1)">DEF',
  604. 'ABC<div style="x:\\xE2\\x80\\x81expression(javascript:alert(1)">DEF',
  605. 'ABC<div style="x:\\xE2\\x80\\x83expression(javascript:alert(1)">DEF',
  606. 'ABC<div style="x:\\xE2\\x80\\x89expression(javascript:alert(1)">DEF',
  607. '<a href="\\x0Bjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  608. '<a href="\\x0Fjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  609. '<a href="\\xC2\\xA0javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  610. '<a href="\\x05javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  611. '<a href="\\xE1\\xA0\\x8Ejavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  612. '<a href="\\x18javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  613. '<a href="\\x11javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  614. '<a href="\\xE2\\x80\\x88javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  615. '<a href="\\xE2\\x80\\x89javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  616. '<a href="\\xE2\\x80\\x80javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  617. '<a href="\\x17javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  618. '<a href="\\x03javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  619. '<a href="\\x0Ejavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  620. '<a href="\\x1Ajavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  621. '<a href="\\x00javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  622. '<a href="\\x10javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  623. '<a href="\\xE2\\x80\\x82javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  624. '<a href="\\x20javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  625. '<a href="\\x13javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  626. '<a href="\\x09javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  627. '<a href="\\xE2\\x80\\x8Ajavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  628. '<a href="\\x14javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  629. '<a href="\\x19javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  630. '<a href="\\xE2\\x80\\xAFjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  631. '<a href="\\x1Fjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  632. '<a href="\\xE2\\x80\\x81javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  633. '<a href="\\x1Djavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  634. '<a href="\\xE2\\x80\\x87javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  635. '<a href="\\x07javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  636. '<a href="\\xE1\\x9A\\x80javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  637. '<a href="\\xE2\\x80\\x83javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  638. '<a href="\\x04javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  639. '<a href="\\x01javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  640. '<a href="\\x08javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  641. '<a href="\\xE2\\x80\\x84javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  642. '<a href="\\xE2\\x80\\x86javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  643. '<a href="\\xE3\\x80\\x80javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  644. '<a href="\\x12javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  645. '<a href="\\x0Djavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  646. '<a href="\\x0Ajavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  647. '<a href="\\x0Cjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  648. '<a href="\\x15javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  649. '<a href="\\xE2\\x80\\xA8javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  650. '<a href="\\x16javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  651. '<a href="\\x02javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  652. '<a href="\\x1Bjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  653. '<a href="\\x06javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  654. '<a href="\\xE2\\x80\\xA9javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  655. '<a href="\\xE2\\x80\\x85javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  656. '<a href="\\x1Ejavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  657. '<a href="\\xE2\\x81\\x9Fjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  658. '<a href="\\x1Cjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
  659. '<a href="javascript\\x00:javascript:alert(1)" id="fuzzelement1">test</a>',
  660. '<a href="javascript\\x3A:javascript:alert(1)" id="fuzzelement1">test</a>',
  661. '<a href="javascript\\x09:javascript:alert(1)" id="fuzzelement1">test</a>',
  662. '<a href="javascript\\x0D:javascript:alert(1)" id="fuzzelement1">test</a>',
  663. '<a href="javascript\\x0A:javascript:alert(1)" id="fuzzelement1">test</a>',
  664. '`"\'><img src=xxx:x \\x0Aonerror=javascript:alert(1)>',
  665. '`"\'><img src=xxx:x \\x22onerror=javascript:alert(1)>',
  666. '`"\'><img src=xxx:x \\x0Bonerror=javascript:alert(1)>',
  667. '`"\'><img src=xxx:x \\x0Donerror=javascript:alert(1)>',
  668. '`"\'><img src=xxx:x \\x2Fonerror=javascript:alert(1)>',
  669. '`"\'><img src=xxx:x \\x09onerror=javascript:alert(1)>',
  670. '`"\'><img src=xxx:x \\x0Conerror=javascript:alert(1)>',
  671. '`"\'><img src=xxx:x \\x00onerror=javascript:alert(1)>',
  672. '`"\'><img src=xxx:x \\x27onerror=javascript:alert(1)>',
  673. '`"\'><img src=xxx:x \\x20onerror=javascript:alert(1)>',
  674. '"`\'><script>\\x3Bjavascript:alert(1)</script>',
  675. '"`\'><script>\\x0Djavascript:alert(1)</script>',
  676. '"`\'><script>\\xEF\\xBB\\xBFjavascript:alert(1)</script>',
  677. '"`\'><script>\\xE2\\x80\\x81javascript:alert(1)</script>',
  678. '"`\'><script>\\xE2\\x80\\x84javascript:alert(1)</script>',
  679. '"`\'><script>\\xE3\\x80\\x80javascript:alert(1)</script>',
  680. '"`\'><script>\\x09javascript:alert(1)</script>',
  681. '"`\'><script>\\xE2\\x80\\x89javascript:alert(1)</script>',
  682. '"`\'><script>\\xE2\\x80\\x85javascript:alert(1)</script>',
  683. '"`\'><script>\\xE2\\x80\\x88javascript:alert(1)</script>',
  684. '"`\'><script>\\x00javascript:alert(1)</script>',
  685. '"`\'><script>\\xE2\\x80\\xA8javascript:alert(1)</script>',
  686. '"`\'><script>\\xE2\\x80\\x8Ajavascript:alert(1)</script>',
  687. '"`\'><script>\\xE1\\x9A\\x80javascript:alert(1)</script>',
  688. '"`\'><script>\\x0Cjavascript:alert(1)</script>',
  689. '"`\'><script>\\x2Bjavascript:alert(1)</script>',
  690. '"`\'><script>\\xF0\\x90\\x96\\x9Ajavascript:alert(1)</script>',
  691. '"`\'><script>-javascript:alert(1)</script>',
  692. '"`\'><script>\\x0Ajavascript:alert(1)</script>',
  693. '"`\'><script>\\xE2\\x80\\xAFjavascript:alert(1)</script>',
  694. '"`\'><script>\\x7Ejavascript:alert(1)</script>',
  695. '"`\'><script>\\xE2\\x80\\x87javascript:alert(1)</script>',
  696. '"`\'><script>\\xE2\\x81\\x9Fjavascript:alert(1)</script>',
  697. '"`\'><script>\\xE2\\x80\\xA9javascript:alert(1)</script>',
  698. '"`\'><script>\\xC2\\x85javascript:alert(1)</script>',
  699. '"`\'><script>\\xEF\\xBF\\xAEjavascript:alert(1)</script>',
  700. '"`\'><script>\\xE2\\x80\\x83javascript:alert(1)</script>',
  701. '"`\'><script>\\xE2\\x80\\x8Bjavascript:alert(1)</script>',
  702. '"`\'><script>\\xEF\\xBF\\xBEjavascript:alert(1)</script>',
  703. '"`\'><script>\\xE2\\x80\\x80javascript:alert(1)</script>',
  704. '"`\'><script>\\x21javascript:alert(1)</script>',
  705. '"`\'><script>\\xE2\\x80\\x82javascript:alert(1)</script>',
  706. '"`\'><script>\\xE2\\x80\\x86javascript:alert(1)</script>',
  707. '"`\'><script>\\xE1\\xA0\\x8Ejavascript:alert(1)</script>',
  708. '"`\'><script>\\x0Bjavascript:alert(1)</script>',
  709. '"`\'><script>\\x20javascript:alert(1)</script>',
  710. '"`\'><script>\\xC2\\xA0javascript:alert(1)</script>',
  711. '<img \\x00src=x onerror="alert(1)">',
  712. '<img \\x47src=x onerror="javascript:alert(1)">',
  713. '<img \\x11src=x onerror="javascript:alert(1)">',
  714. '<img \\x12src=x onerror="javascript:alert(1)">',
  715. '<img\\x47src=x onerror="javascript:alert(1)">',
  716. '<img\\x10src=x onerror="javascript:alert(1)">',
  717. '<img\\x13src=x onerror="javascript:alert(1)">',
  718. '<img\\x32src=x onerror="javascript:alert(1)">',
  719. '<img\\x47src=x onerror="javascript:alert(1)">',
  720. '<img\\x11src=x onerror="javascript:alert(1)">',
  721. '<img \\x47src=x onerror="javascript:alert(1)">',
  722. '<img \\x34src=x onerror="javascript:alert(1)">',
  723. '<img \\x39src=x onerror="javascript:alert(1)">',
  724. '<img \\x00src=x onerror="javascript:alert(1)">',
  725. '<img src\\x09=x onerror="javascript:alert(1)">',
  726. '<img src\\x10=x onerror="javascript:alert(1)">',
  727. '<img src\\x13=x onerror="javascript:alert(1)">',
  728. '<img src\\x32=x onerror="javascript:alert(1)">',
  729. '<img src\\x12=x onerror="javascript:alert(1)">',
  730. '<img src\\x11=x onerror="javascript:alert(1)">',
  731. '<img src\\x00=x onerror="javascript:alert(1)">',
  732. '<img src\\x47=x onerror="javascript:alert(1)">',
  733. '<img src=x\\x09onerror="javascript:alert(1)">',
  734. '<img src=x\\x10onerror="javascript:alert(1)">',
  735. '<img src=x\\x11onerror="javascript:alert(1)">',
  736. '<img src=x\\x12onerror="javascript:alert(1)">',
  737. '<img src=x\\x13onerror="javascript:alert(1)">',
  738. '<img[a][b][c]src[d]=x[e]onerror=[f]"alert(1)">',
  739. '<img src=x onerror=\\x09"javascript:alert(1)">',
  740. '<img src=x onerror=\\x10"javascript:alert(1)">',
  741. '<img src=x onerror=\\x11"javascript:alert(1)">',
  742. '<img src=x onerror=\\x12"javascript:alert(1)">',
  743. '<img src=x onerror=\\x32"javascript:alert(1)">',
  744. '<img src=x onerror=\\x00"javascript:alert(1)">',
  745. '<a href=java&#1&#2&#3&#4&#5&#6&#7&#8&#11&#12script:javascript:alert(1)>XXX</a>',
  746. '<img src="x` `<script>javascript:alert(1)</script>"` `>',
  747. '<img src onerror /" \'"= alt=javascript:alert(1)//">',
  748. '<title onpropertychange=javascript:alert(1)></title><title title=>',
  749. '<a href=http://foo.bar/#x=`y></a><img alt="`><img src=x:x onerror=javascript:alert(1)></a>">',
  750. '<!--[if]><script>javascript:alert(1)</script -->',
  751. '<!--[if<img src=x onerror=javascript:alert(1)//]> -->',
  752. '<script src="/\\%(jscript)s"></script>',
  753. '<script src="\\\\%(jscript)s"></script>',
  754. '<IMG """><SCRIPT>alert("XSS")</SCRIPT>">',
  755. '<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>',
  756. '<IMG SRC=# onmouseover="alert(\'xxs\')">',
  757. '<IMG SRC= onmouseover="alert(\'xxs\')">',
  758. '<IMG onmouseover="alert(\'xxs\')">',
  759. '<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>',
  760. '<IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>',
  761. '<IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>',
  762. '<IMG SRC="jav ascript:alert(\'XSS\');">',
  763. '<IMG SRC="jav&#x09;ascript:alert(\'XSS\');">',
  764. '<IMG SRC="jav&#x0A;ascript:alert(\'XSS\');">',
  765. '<IMG SRC="jav&#x0D;ascript:alert(\'XSS\');">',
  766. 'perl -e \'print "<IMG SRC=java\\0script:alert(\\"XSS\\")>";\' > out',
  767. '<IMG SRC=" &#14; javascript:alert(\'XSS\');">',
  768. '<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>',
  769. '<BODY onload!#$%&()*~+-_.,:;?@[/|\\]^`=alert("XSS")>',
  770. '<SCRIPT/SRC="http://ha.ckers.org/xss.js"></SCRIPT>',
  771. '<<SCRIPT>alert("XSS");//<</SCRIPT>',
  772. '<SCRIPT SRC=http://ha.ckers.org/xss.js?< B >',
  773. '<SCRIPT SRC=//ha.ckers.org/.j>',
  774. '<IMG SRC="javascript:alert(\'XSS\')"',
  775. '<iframe src=http://ha.ckers.org/scriptlet.html <',
  776. "\\\";alert('XSS');//",
  777. '<plaintext>',
  778. '1;DROP TABLE users',
  779. "1'; DROP TABLE users-- 1",
  780. "' OR 1=1 -- 1",
  781. "' OR '1'='1",
  782. '-',
  783. '--',
  784. '--version',
  785. '--help',
  786. '$USER',
  787. '/dev/null; touch /tmp/blns.fail ; echo',
  788. '`touch /tmp/blns.fail`',
  789. '$(touch /tmp/blns.fail)',
  790. '@{[system "touch /tmp/blns.fail"]}',
  791. 'eval("puts \'hello world\'")',
  792. 'System("ls -al /")',
  793. '`ls -al /`',
  794. 'Kernel.exec("ls -al /")',
  795. 'Kernel.exit(1)',
  796. "%x('ls -al /')",
  797. '<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [ <!ELEMENT foo ANY ><!ENTITY xxe SYSTEM "file:///etc/passwd" >]><foo>&xxe;</foo>',
  798. '$HOME',
  799. "$ENV{'HOME'}",
  800. '%d',
  801. '%s',
  802. '%*.*s',
  803. '../../../../../../../../../../../etc/passwd%00',
  804. '../../../../../../../../../../../etc/hosts',
  805. '() { 0; }; touch /tmp/blns.shellshock1.fail;',
  806. '() { _; } >_[$($())] { touch /tmp/blns.shellshock2.fail; }',
  807. 'CON',
  808. 'PRN',
  809. 'AUX',
  810. 'CLOCK$',
  811. 'NUL',
  812. 'A:',
  813. 'ZZ:',
  814. 'COM1',
  815. 'LPT1',
  816. 'LPT2',
  817. 'LPT3',
  818. 'COM2',
  819. 'COM3',
  820. 'COM4',
  821. 'Scunthorpe General Hospital',
  822. 'Penistone Community Church',
  823. 'Lightwater Country Park',
  824. 'Jimmy Clitheroe',
  825. 'Horniman Museum',
  826. 'shitake mushrooms',
  827. 'RomansInSussex.co.uk',
  828. 'http://www.cum.qc.ca/',
  829. 'Craig Cockburn, Software Specialist',
  830. 'Linda Callahan',
  831. 'Dr. Herman I. Libshitz',
  832. 'magna cum laude',
  833. 'Super Bowl XXX',
  834. 'medieval erection of parapets',
  835. 'evaluate',
  836. 'mocha',
  837. 'expression',
  838. 'Arsenal canal',
  839. 'classic',
  840. 'Tyson Gay',
  841. "If you're reading this, you've been in a coma for almost 20 years now. We're trying a new technique. We don't know where this message will end up in your dream, but we hope it works. Please wake up, we miss you.",
  842. 'Roses are \u001b[0;31mred\u001b[0m, violets are \u001b[0;34mblue. Hope you enjoy terminal hue',
  843. 'But now...\u001b[20Cfor my greatest trick...\u001b[8m',
  844. 'The quic\b\b\b\b\b\bk brown fo\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007x... [Beeeep]',
  845. 'Powerلُلُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ冗',
  846. ],
  847. ranges: {},
  848. version: 2,
  849. }
  850. return DocstoreClient.createDoc(
  851. this.project_id,
  852. this.doc._id,
  853. this.doc.lines,
  854. this.doc.version,
  855. this.doc.ranges,
  856. error => {
  857. if (error != null) {
  858. throw error
  859. }
  860. return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => {
  861. this.res = res
  862. if (error != null) {
  863. throw error
  864. }
  865. return done()
  866. })
  867. }
  868. )
  869. })
  870. it('should successully archive the docs', function (done) {
  871. this.res.statusCode.should.equal(204)
  872. return done()
  873. })
  874. it('should set inS3 and unset lines and ranges in each doc', function (done) {
  875. return db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
  876. if (error != null) {
  877. throw error
  878. }
  879. expect(doc.lines).not.to.exist
  880. expect(doc.ranges).not.to.exist
  881. doc.inS3.should.equal(true)
  882. return done()
  883. })
  884. })
  885. it('should set the doc in s3 correctly', function (done) {
  886. return DocstoreClient.getS3Doc(
  887. this.project_id,
  888. this.doc._id,
  889. (error, s3Doc) => {
  890. if (error != null) {
  891. throw error
  892. }
  893. s3Doc.lines.should.deep.equal(this.doc.lines)
  894. s3Doc.ranges.should.deep.equal(this.doc.ranges)
  895. return done()
  896. }
  897. )
  898. })
  899. return describe('after unarchiving from a request for the project', function () {
  900. before(function (done) {
  901. return DocstoreClient.getAllDocs(
  902. this.project_id,
  903. (error, res, fetchedDocs) => {
  904. this.fetched_docs = fetchedDocs
  905. if (error != null) {
  906. throw error
  907. }
  908. return done()
  909. }
  910. )
  911. })
  912. return it('should restore the doc to mongo', function (done) {
  913. return db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
  914. if (error != null) {
  915. throw error
  916. }
  917. doc.lines.should.deep.equal(this.doc.lines)
  918. doc.ranges.should.deep.equal(this.doc.ranges)
  919. expect(doc.inS3).not.to.exist
  920. return done()
  921. })
  922. })
  923. })
  924. })
  925. describe('a doc with ranges', function () {
  926. before(function (done) {
  927. this.project_id = new ObjectId()
  928. this.doc = {
  929. _id: new ObjectId(),
  930. lines: ['one', 'two', 'three'],
  931. ranges: {
  932. changes: [
  933. {
  934. id: new ObjectId(),
  935. op: { i: 'foo', p: 24 },
  936. metadata: {
  937. user_id: new ObjectId(),
  938. ts: new Date('2017-01-27T16:10:44.194Z'),
  939. },
  940. },
  941. {
  942. id: new ObjectId(),
  943. op: { d: 'bar', p: 50 },
  944. metadata: {
  945. user_id: new ObjectId(),
  946. ts: new Date('2017-01-27T18:10:44.194Z'),
  947. },
  948. },
  949. ],
  950. comments: [
  951. {
  952. id: new ObjectId(),
  953. op: { c: 'comment', p: 284, t: new ObjectId() },
  954. metadata: {
  955. user_id: new ObjectId(),
  956. ts: new Date('2017-01-26T14:22:04.869Z'),
  957. },
  958. },
  959. ],
  960. },
  961. version: 2,
  962. }
  963. return DocstoreClient.createDoc(
  964. this.project_id,
  965. this.doc._id,
  966. this.doc.lines,
  967. this.doc.version,
  968. this.doc.ranges,
  969. error => {
  970. if (error != null) {
  971. throw error
  972. }
  973. return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => {
  974. this.res = res
  975. if (error != null) {
  976. throw error
  977. }
  978. return done()
  979. })
  980. }
  981. )
  982. })
  983. it('should successully archive the docs', function (done) {
  984. this.res.statusCode.should.equal(204)
  985. return done()
  986. })
  987. it('should set inS3 and unset lines and ranges in each doc', function (done) {
  988. return db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
  989. if (error != null) {
  990. throw error
  991. }
  992. expect(doc.lines).not.to.exist
  993. expect(doc.ranges).not.to.exist
  994. doc.inS3.should.equal(true)
  995. return done()
  996. })
  997. })
  998. it('should set the doc in s3 correctly', function (done) {
  999. return DocstoreClient.getS3Doc(
  1000. this.project_id,
  1001. this.doc._id,
  1002. (error, s3Doc) => {
  1003. if (error != null) {
  1004. throw error
  1005. }
  1006. s3Doc.lines.should.deep.equal(this.doc.lines)
  1007. const ranges = JSON.parse(JSON.stringify(this.doc.ranges)) // ObjectId -> String
  1008. s3Doc.ranges.should.deep.equal(ranges)
  1009. return done()
  1010. }
  1011. )
  1012. })
  1013. return describe('after unarchiving from a request for the project', function () {
  1014. before(function (done) {
  1015. return DocstoreClient.getAllDocs(
  1016. this.project_id,
  1017. (error, res, fetchedDocs) => {
  1018. this.fetched_docs = fetchedDocs
  1019. if (error != null) {
  1020. throw error
  1021. }
  1022. return done()
  1023. }
  1024. )
  1025. })
  1026. return it('should restore the doc to mongo', function (done) {
  1027. return db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
  1028. if (error != null) {
  1029. throw error
  1030. }
  1031. doc.lines.should.deep.equal(this.doc.lines)
  1032. doc.ranges.should.deep.equal(this.doc.ranges)
  1033. expect(doc.inS3).not.to.exist
  1034. return done()
  1035. })
  1036. })
  1037. })
  1038. })
  1039. describe('a doc that is archived twice', function () {
  1040. before(function (done) {
  1041. this.project_id = new ObjectId()
  1042. this.doc = {
  1043. _id: new ObjectId(),
  1044. lines: ['abc', 'def', 'ghi'],
  1045. ranges: {},
  1046. version: 2,
  1047. }
  1048. return DocstoreClient.createDoc(
  1049. this.project_id,
  1050. this.doc._id,
  1051. this.doc.lines,
  1052. this.doc.version,
  1053. this.doc.ranges,
  1054. error => {
  1055. if (error != null) {
  1056. throw error
  1057. }
  1058. return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => {
  1059. this.res = res
  1060. if (error != null) {
  1061. throw error
  1062. }
  1063. this.res.statusCode.should.equal(204)
  1064. return DocstoreClient.archiveAllDoc(
  1065. this.project_id,
  1066. (error, res1) => {
  1067. this.res = res1
  1068. if (error != null) {
  1069. throw error
  1070. }
  1071. this.res.statusCode.should.equal(204)
  1072. return done()
  1073. }
  1074. )
  1075. })
  1076. }
  1077. )
  1078. })
  1079. it('should set inS3 and unset lines and ranges in each doc', function (done) {
  1080. return db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
  1081. if (error != null) {
  1082. throw error
  1083. }
  1084. expect(doc.lines).not.to.exist
  1085. expect(doc.ranges).not.to.exist
  1086. doc.inS3.should.equal(true)
  1087. return done()
  1088. })
  1089. })
  1090. it('should set the doc in s3 correctly', function (done) {
  1091. return DocstoreClient.getS3Doc(
  1092. this.project_id,
  1093. this.doc._id,
  1094. (error, s3Doc) => {
  1095. if (error != null) {
  1096. throw error
  1097. }
  1098. s3Doc.lines.should.deep.equal(this.doc.lines)
  1099. s3Doc.ranges.should.deep.equal(this.doc.ranges)
  1100. return done()
  1101. }
  1102. )
  1103. })
  1104. return describe('after unarchiving from a request for the project', function () {
  1105. before(function (done) {
  1106. return DocstoreClient.getAllDocs(
  1107. this.project_id,
  1108. (error, res, fetchedDocs) => {
  1109. this.fetched_docs = fetchedDocs
  1110. if (error != null) {
  1111. throw error
  1112. }
  1113. return done()
  1114. }
  1115. )
  1116. })
  1117. return it('should restore the doc to mongo', function (done) {
  1118. return db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
  1119. if (error != null) {
  1120. throw error
  1121. }
  1122. doc.lines.should.deep.equal(this.doc.lines)
  1123. doc.ranges.should.deep.equal(this.doc.ranges)
  1124. expect(doc.inS3).not.to.exist
  1125. return done()
  1126. })
  1127. })
  1128. })
  1129. })
  1130. return describe('a doc with the old schema (just an array of lines)', function () {
  1131. before(function (done) {
  1132. this.project_id = new ObjectId()
  1133. this.doc = {
  1134. _id: new ObjectId(),
  1135. lines: ['abc', 'def', 'ghi'],
  1136. ranges: {},
  1137. version: 2,
  1138. }
  1139. uploadContent(
  1140. `${this.project_id}/${this.doc._id}`,
  1141. this.doc.lines,
  1142. error => {
  1143. expect(error).not.to.exist
  1144. db.docs.insertOne(
  1145. {
  1146. project_id: this.project_id,
  1147. _id: this.doc._id,
  1148. rev: this.doc.version,
  1149. inS3: true,
  1150. },
  1151. error => {
  1152. if (error != null) {
  1153. throw error
  1154. }
  1155. DocstoreClient.getAllDocs(
  1156. this.project_id,
  1157. (error, res, fetchedDocs) => {
  1158. this.fetched_docs = fetchedDocs
  1159. if (error != null) {
  1160. throw error
  1161. }
  1162. return done()
  1163. }
  1164. )
  1165. }
  1166. )
  1167. }
  1168. )
  1169. })
  1170. it('should restore the doc to mongo', function (done) {
  1171. return db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
  1172. if (error != null) {
  1173. throw error
  1174. }
  1175. doc.lines.should.deep.equal(this.doc.lines)
  1176. expect(doc.inS3).not.to.exist
  1177. return done()
  1178. })
  1179. })
  1180. return it('should return the doc', function (done) {
  1181. this.fetched_docs[0].lines.should.deep.equal(this.doc.lines)
  1182. return done()
  1183. })
  1184. })
  1185. })