From 6f7528deb011c1b547f8c041bb7ec04beb142a5f Mon Sep 17 00:00:00 2001 From: Gianlucci Badiali Minarelli Date: Thu, 3 May 2018 14:28:39 -0700 Subject: [PATCH 1/4] Add regression test --- .gitignore | 1 + .../regression-control.txt | Bin 0 -> 31 bytes package-lock.json | 76 +++++++++++++++++- package.json | 3 +- public/js/cipher.js | 7 +- public/js/dir.js | 40 ++++++++- 6 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 data/cc8/tluICx+fpoDNb+DsLMquWl+aai5sVg/regression-control.txt diff --git a/.gitignore b/.gitignore index 0772d0d..d950511 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ data/* +!data/cc8/ docker-compose.override.yml .idea diff --git a/data/cc8/tluICx+fpoDNb+DsLMquWl+aai5sVg/regression-control.txt b/data/cc8/tluICx+fpoDNb+DsLMquWl+aai5sVg/regression-control.txt new file mode 100644 index 0000000000000000000000000000000000000000..0a8d78d308252491462ff2fb5e6d83a38564cac0 GIT binary patch literal 31 ncmbO^(|;%bjEPl=!cLD*pW)T)oEmMs$&!KJQS{@Y`ZM+b-4qRM literal 0 HcmV?d00001 diff --git a/package-lock.json b/package-lock.json index cc7d741..817ee14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -88,6 +88,12 @@ "concat-map": "0.0.1" } }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -111,6 +117,12 @@ "delayed-stream": "1.0.0" } }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -170,9 +182,9 @@ } }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -183,6 +195,12 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, "ecc-jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", @@ -207,6 +225,12 @@ "es6-promise": "4.2.4" } }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", @@ -313,6 +337,12 @@ "path-is-absolute": "1.0.1" } }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", + "dev": true + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -327,6 +357,12 @@ "har-schema": "2.0.0" } }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, "hawk": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", @@ -338,6 +374,12 @@ "sntp": "2.1.0" } }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, "hoek": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", @@ -501,6 +543,25 @@ } } }, + "mocha": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.1.1.tgz", + "integrity": "sha512-kKKs/H1KrMMQIEsWNxGmb4/BGsmj0dkeyotEvbrAuQ01FcWRLssUNXCEUZk6SZtyJBi6EE7SL0zDDtItw1rGhw==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -709,6 +770,15 @@ "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", diff --git a/package.json b/package.json index c87c4b0..8132d54 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "slug": "^0.9.1" }, "devDependencies": { - "puppeteer": "^1.3.0" + "puppeteer": "^1.3.0", + "mocha": "^5.1.1" }, "scripts": { "test": "mocha" diff --git a/public/js/cipher.js b/public/js/cipher.js index fa5ed59..7bcf00c 100644 --- a/public/js/cipher.js +++ b/public/js/cipher.js @@ -54,12 +54,12 @@ const encryptFiles = async ([files, hashKey]) => { }); }; -const decryptFile = async (file) => { +const decryptFile = async ([file, hashKey]) => { const key = await window.crypto.subtle.importKey( "jwk", { kty: "oct", - k: window.location.hash.slice(1), + k: hashKey, alg: "A256GCM", ext: true, }, @@ -83,7 +83,8 @@ const decryptFile = async (file) => { key, data ); - resolve(window.URL.createObjectURL(new Blob([decryptedFileRaw]))); + // resolve(window.URL.createObjectURL(new Blob([decryptedFileRaw]))); + resolve(new Blob([decryptedFileRaw])); } reader.readAsArrayBuffer(file); }); diff --git a/public/js/dir.js b/public/js/dir.js index 060671f..5670e87 100644 --- a/public/js/dir.js +++ b/public/js/dir.js @@ -3,6 +3,15 @@ //TODO: avoid global variables... let content = ''; //list of uploaded files. +/*#############################################################| +| TESTS +*##############################################################*/ + +const regressionTest = () => { + window.location.hash = ''; + window.location.href = window.location.origin + '/dir/data/cc8/tluICx+fpoDNb+DsLMquWl+aai5sVg#NfF6mwHOSZire9yal1dlOMFn67RTD8tsL_mjlsPP_Is'; + window.location.reload(); +} /*#############################################################| | VALIDATION @@ -41,6 +50,24 @@ if (window.location.protocol === 'http:') { /* File download =========================================== */ +const beforeDownload = blob => { + if (window.location.hash === '#NfF6mwHOSZire9yal1dlOMFn67RTD8tsL_mjlsPP_Is') { + return new Promise((resolve, reject) => { + let reader = new FileReader(); + reader.onload = (e => { + if (e.target.result === 'bar') { + //TODO: setup back-end hook; + console.log('success'); + } + resolve('#'); // this prevents page refresh on click + }); + reader.readAsText(blob); + }); + } else { + return window.URL.createObjectURL(blob); + } +} + const handleFileDownload = (e) => { if (window.location.hash) { @@ -50,7 +77,8 @@ const handleFileDownload = (e) => { let fetchFilePath = function (filePath, filename) { fetch(filePath) .then(res => res.blob()) - .then(blob => decryptFile(blob)) + .then(blob => decryptFile([blob, window.location.hash.slice(1)])) + .then(beforeDownload) .then(downloadLink => { currentLink.setAttribute('href', downloadLink); currentLink.setAttribute('download', filename); @@ -84,7 +112,7 @@ const handleFileDownload = (e) => { } else { //TODO: better feedback? let hashWarning = new Alert().showMessage("danger", "Error: no hash found."); - console.log('Error: no hash found.'); + console.error('Error: no hash found.'); } }; @@ -120,6 +148,10 @@ const addFilesDecrypt = () => { } + /* Triggers regression test =========================================== */ + if (window.location.hash === '#NfF6mwHOSZire9yal1dlOMFn67RTD8tsL_mjlsPP_Is') { + document.querySelector(".files-listing").firstElementChild.firstElementChild.children[1].click(); // trigger regression-control.txt + } }; @@ -195,7 +227,7 @@ const listingFiles = () => { .then(removeListItem(deleteItem, deleteItemName)) //remove item from file listing .catch(error => { let deleteError = new Alert().showMessage("danger", `Error while trying to delete your file: ${error}`); - console.log(error); + console.error(error); }); } }); @@ -463,4 +495,4 @@ shareLinkBtn.addEventListener('click', function (e) { Display.copyLinkClipboard(); -}); \ No newline at end of file +}); From 8b2822aeb8d066411a364a54ebd7c97b0ee88cf3 Mon Sep 17 00:00:00 2001 From: Gianlucci Badiali Minarelli Date: Fri, 4 May 2018 07:14:28 -0700 Subject: [PATCH 2/4] Update regression test to throw error on fail --- public/js/dir.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/public/js/dir.js b/public/js/dir.js index 5670e87..7a24910 100644 --- a/public/js/dir.js +++ b/public/js/dir.js @@ -55,9 +55,8 @@ const beforeDownload = blob => { return new Promise((resolve, reject) => { let reader = new FileReader(); reader.onload = (e => { - if (e.target.result === 'bar') { - //TODO: setup back-end hook; - console.log('success'); + if (e.target.result !== 'bar') { + throw new Error('Regression test failed.'); } resolve('#'); // this prevents page refresh on click }); From 2da7abf8e43cf1cb48ebe058f7328848615b5309 Mon Sep 17 00:00:00 2001 From: Gianlucci Badiali Minarelli Date: Fri, 4 May 2018 07:40:03 -0700 Subject: [PATCH 3/4] Fix issue with page reload and update test feedback --- public/js/dir.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/public/js/dir.js b/public/js/dir.js index 7a24910..b549b37 100644 --- a/public/js/dir.js +++ b/public/js/dir.js @@ -10,7 +10,10 @@ let content = ''; //list of uploaded files. const regressionTest = () => { window.location.hash = ''; window.location.href = window.location.origin + '/dir/data/cc8/tluICx+fpoDNb+DsLMquWl+aai5sVg#NfF6mwHOSZire9yal1dlOMFn67RTD8tsL_mjlsPP_Is'; - window.location.reload(); + // Gian: we need the above reload for consecutive tests, since the page wont reload when the path doesn't change (only the hash is changing after the first test). We also need the delay since without it the reload happens before the url (with the new hash) is updated. + setTimeout(() => { + window.location.reload(); + }, 500); } /*#############################################################| @@ -57,6 +60,8 @@ const beforeDownload = blob => { reader.onload = (e => { if (e.target.result !== 'bar') { throw new Error('Regression test failed.'); + } else { + console.log('Success!'); } resolve('#'); // this prevents page refresh on click }); From 33c750304742dd0a15ddc43d0a97f453e7cfadda Mon Sep 17 00:00:00 2001 From: Gianlucci Badiali Minarelli Date: Fri, 4 May 2018 13:24:36 -0700 Subject: [PATCH 4/4] Add API tests --- index.js | 2 ++ package-lock.json | 48 ++++++++++++++++++++++++++-- package.json | 3 +- test/api.js | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 test/api.js diff --git a/index.js b/index.js index 492703d..8078c6d 100644 --- a/index.js +++ b/index.js @@ -241,3 +241,5 @@ http.createServer((req, res) => { }).listen(1234); + +module.exports = server; diff --git a/package-lock.json b/package-lock.json index 817ee14..bc45e9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -123,6 +123,12 @@ "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", "dev": true }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -145,6 +151,12 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" }, + "cookiejar": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.1.tgz", + "integrity": "sha1-Qa1XsbVVlR7BcUEqgZQrHoIA00o=", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -243,7 +255,6 @@ "dev": true, "requires": { "concat-stream": "1.6.0", - "debug": "2.6.9", "mkdirp": "0.5.0", "yauzl": "2.4.1" }, @@ -495,6 +506,12 @@ "is-buffer": "1.1.6" } }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -628,7 +645,6 @@ "integrity": "sha512-wx10aPQPpGJVxdB6yoDSLm9p4rCwARUSLMVV0bx++owuqkvviXKyiFM3EWsywaFmjOKNPXacIjplF7xhHiFP3w==", "dev": true, "requires": { - "debug": "2.6.9", "extract-zip": "1.6.6", "https-proxy-agent": "2.2.1", "mime": "1.6.0", @@ -770,6 +786,34 @@ "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" }, + "superagent": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "cookiejar": "2.1.1", + "debug": "3.1.0", + "extend": "3.0.1", + "form-data": "2.3.2", + "formidable": "1.2.1", + "methods": "1.1.2", + "mime": "1.6.0", + "qs": "6.5.1", + "readable-stream": "2.3.6" + } + }, + "supertest": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.0.0.tgz", + "integrity": "sha1-jUu2j9GDDuBwM7HFpamkAhyWUpY=", + "dev": true, + "requires": { + "methods": "1.1.2", + "superagent": "3.8.3" + } + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", diff --git a/package.json b/package.json index 8132d54..a62d322 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,9 @@ "slug": "^0.9.1" }, "devDependencies": { + "mocha": "^5.1.1", "puppeteer": "^1.3.0", - "mocha": "^5.1.1" + "supertest": "^3.0.0" }, "scripts": { "test": "mocha" diff --git a/test/api.js b/test/api.js new file mode 100644 index 0000000..0ee475d --- /dev/null +++ b/test/api.js @@ -0,0 +1,81 @@ +const server = require('../index.js'); +const request = require('supertest')(server); +const fs = require('fs'); +const path = require('path'); + +describe('GET /mkdir', function() { + let secretPath = ''; + after('delete secret folder', function(done) { + fs.rmdir(secretPath.split('/').slice(2).join(path.sep), function(err) { + if (err) return done(err); + fs.rmdir(secretPath.split('/').slice(2, 4).join(path.sep), function(err) { + if (err) return done(err); + done(); + }); + }); + }); + + it('create secret folder', function(done) { + request.get('/mkdir') + .expect(302) + .end(function(err, res) { + if (err) return done(err); + secretPath = res.headers.location; + // console.log(secretPath); + done(); + }); + }); +}); + +describe('File operations', function() { + let secretPath = ''; + before('create secret folder', function(done) { + request.get('/mkdir') + .end(function(err, res) { + if (err) return done(err); + secretPath = res.headers.location; + // console.log(secretPath); + done(); + }); + }); + + after('delete secret folder', function(done) { + fs.rmdir(secretPath.split('/').slice(2).join(path.sep), function(err) { + if (err) return done(err); + fs.rmdir(secretPath.split('/').slice(2, 4).join(path.sep), function(err) { + if (err) return done(err); + done(); + }); + }); + }); + + describe('POST /secret/folder', function() { + it('upload file to secret folder', function(done) { + request.post(secretPath) + //Gian: using the regression-contol file here instead of creating one from scratch. + .attach('test-file', './data/cc8/tluICx+fpoDNb+DsLMquWl+aai5sVg/regression-control.txt') + .expect(200, done); + }); + }); + + describe('GET /ls', function() { + it('list files', function(done) { + request.get(secretPath.replace("dir", "ls")) + // .expect(200, done); + .expect(200) + .end(function(err, res) { + if (err) return done(err); + //Gian: uncomment the log below if you want to check the files on the list. Otherwise, we could end the test earlier with 'expect(200, done)'. + // console.log(res.text); + done(); + }); + }); + }); + + describe('DELETE /secret/folder/file', function() { + it('delete file', function(done) { + request.delete(secretPath + '/regression-control.txt') + .expect(204, done); + }); + }); +});