format
This commit is contained in:
parent
a7de951115
commit
caeba94e04
|
@ -1,8 +1,6 @@
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const { arrayToHex } = require('./utils');
|
const { arrayToHex } = require('./utils');
|
||||||
|
|
||||||
const Raven = window.Raven;
|
|
||||||
|
|
||||||
class FileSender extends EventEmitter {
|
class FileSender extends EventEmitter {
|
||||||
constructor(file) {
|
constructor(file) {
|
||||||
super();
|
super();
|
||||||
|
@ -38,8 +36,7 @@ class FileSender extends EventEmitter {
|
||||||
const self = this;
|
const self = this;
|
||||||
self.emit('loading', true);
|
self.emit('loading', true);
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
window.crypto.subtle
|
window.crypto.subtle.generateKey(
|
||||||
.generateKey(
|
|
||||||
{
|
{
|
||||||
name: 'AES-GCM',
|
name: 'AES-GCM',
|
||||||
length: 128
|
length: 128
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
/* global MAXFILESIZE EXPIRE_SECONDS */
|
/* global MAXFILESIZE EXPIRE_SECONDS */
|
||||||
require('./common');
|
require('./common');
|
||||||
const FileSender = require('./fileSender');
|
const FileSender = require('./fileSender');
|
||||||
const {
|
const { notify, findMetric, sendEvent, ONE_DAY_IN_MS } = require('./utils');
|
||||||
notify,
|
|
||||||
findMetric,
|
|
||||||
sendEvent,
|
|
||||||
ONE_DAY_IN_MS
|
|
||||||
} = require('./utils');
|
|
||||||
const bytes = require('bytes');
|
const bytes = require('bytes');
|
||||||
const Storage = require('./storage');
|
const Storage = require('./storage');
|
||||||
const storage = new Storage(localStorage);
|
const storage = new Storage(localStorage);
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
/*** index.html ***/
|
/*** index.html ***/
|
||||||
html {
|
html {
|
||||||
background: url('resources/send_bg.svg');
|
background: url('resources/send_bg.svg');
|
||||||
font-family: -apple-system,
|
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', Helvetica,
|
||||||
BlinkMacSystemFont,
|
Arial, sans-serif;
|
||||||
'SF Pro Text',
|
|
||||||
Helvetica,
|
|
||||||
Arial,
|
|
||||||
sans-serif;
|
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
background-size: 110%;
|
background-size: 110%;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
|
|
|
@ -14,7 +14,7 @@ const filename = path.join(__dirname, '..', 'public', 'version.json');
|
||||||
const filedata = {
|
const filedata = {
|
||||||
commit,
|
commit,
|
||||||
source: pkg.homepage,
|
source: pkg.homepage,
|
||||||
version: process.env.CIRCLE_TAG || `v${ pkg.version }`
|
version: process.env.CIRCLE_TAG || `v${pkg.version}`
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.writeFileSync(filename, JSON.stringify(filedata, null, 2) + '\n');
|
fs.writeFileSync(filename, JSON.stringify(filedata, null, 2) + '\n');
|
||||||
|
|
|
@ -9,7 +9,7 @@ window.Raven = {
|
||||||
captureException: function(err) {
|
captureException: function(err) {
|
||||||
console.error(err, err.stack);
|
console.error(err, err.stack);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
window.FakeFile = FakeFile;
|
window.FakeFile = FakeFile;
|
||||||
window.FileSender = require('../../frontend/src/fileSender');
|
window.FileSender = require('../../frontend/src/fileSender');
|
||||||
|
|
|
@ -16,40 +16,39 @@ let originalBlob;
|
||||||
describe('File Sender', function() {
|
describe('File Sender', function() {
|
||||||
before(function() {
|
before(function() {
|
||||||
server.respondImmediately = true;
|
server.respondImmediately = true;
|
||||||
server.respondWith(
|
server.respondWith('POST', '/upload', function(request) {
|
||||||
'POST',
|
|
||||||
'/upload',
|
|
||||||
function(request) {
|
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.readAsArrayBuffer(request.requestBody.get('data'));
|
reader.readAsArrayBuffer(request.requestBody.get('data'));
|
||||||
|
|
||||||
reader.onload = function(event) {
|
reader.onload = function(event) {
|
||||||
file = this.result;
|
file = this.result;
|
||||||
}
|
};
|
||||||
|
|
||||||
const responseObj = JSON.parse(request.requestHeaders['X-File-Metadata']);
|
const responseObj = JSON.parse(request.requestHeaders['X-File-Metadata']);
|
||||||
request.respond(
|
request.respond(
|
||||||
200,
|
200,
|
||||||
{'Content-Type': 'application/json'},
|
{ 'Content-Type': 'application/json' },
|
||||||
JSON.stringify({url: 'some url',
|
JSON.stringify({
|
||||||
|
url: 'some url',
|
||||||
id: responseObj.id,
|
id: responseObj.id,
|
||||||
delete: responseObj.delete})
|
delete: responseObj.delete
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Should get a loading event emission', function() {
|
it('Should get a loading event emission', function() {
|
||||||
const file = new FakeFile('hello_world.txt', ['This is some data.'])
|
const file = new FakeFile('hello_world.txt', ['This is some data.']);
|
||||||
const fs = new FileSender(file);
|
const fs = new FileSender(file);
|
||||||
let testLoading = true;
|
let testLoading = true;
|
||||||
|
|
||||||
fs.on('loading', isStillLoading => {
|
fs.on('loading', isStillLoading => {
|
||||||
assert(!(!testLoading && isStillLoading));
|
assert(!(!testLoading && isStillLoading));
|
||||||
testLoading = isStillLoading;
|
testLoading = isStillLoading;
|
||||||
})
|
});
|
||||||
|
|
||||||
return fs.upload()
|
return fs
|
||||||
|
.upload()
|
||||||
.then(info => {
|
.then(info => {
|
||||||
assert(info);
|
assert(info);
|
||||||
assert(!testLoading);
|
assert(!testLoading);
|
||||||
|
@ -58,19 +57,20 @@ describe('File Sender', function() {
|
||||||
console.log(err, err.stack);
|
console.log(err, err.stack);
|
||||||
assert.fail();
|
assert.fail();
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Should get a hashing event emission', function() {
|
it('Should get a hashing event emission', function() {
|
||||||
const file = new FakeFile('hello_world.txt', ['This is some data.'])
|
const file = new FakeFile('hello_world.txt', ['This is some data.']);
|
||||||
const fs = new FileSender(file);
|
const fs = new FileSender(file);
|
||||||
let testHashing = true;
|
let testHashing = true;
|
||||||
|
|
||||||
fs.on('hashing', isStillHashing => {
|
fs.on('hashing', isStillHashing => {
|
||||||
assert(!(!testHashing && isStillHashing));
|
assert(!(!testHashing && isStillHashing));
|
||||||
testHashing = isStillHashing;
|
testHashing = isStillHashing;
|
||||||
})
|
});
|
||||||
|
|
||||||
return fs.upload()
|
return fs
|
||||||
|
.upload()
|
||||||
.then(info => {
|
.then(info => {
|
||||||
assert(info);
|
assert(info);
|
||||||
assert(!testHashing);
|
assert(!testHashing);
|
||||||
|
@ -79,19 +79,20 @@ describe('File Sender', function() {
|
||||||
console.log(err, err.stack);
|
console.log(err, err.stack);
|
||||||
assert.fail();
|
assert.fail();
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Should get a encrypting event emission', function() {
|
it('Should get a encrypting event emission', function() {
|
||||||
const file = new FakeFile('hello_world.txt', ['This is some data.'])
|
const file = new FakeFile('hello_world.txt', ['This is some data.']);
|
||||||
const fs = new FileSender(file);
|
const fs = new FileSender(file);
|
||||||
let testEncrypting = true;
|
let testEncrypting = true;
|
||||||
|
|
||||||
fs.on('encrypting', isStillEncrypting => {
|
fs.on('encrypting', isStillEncrypting => {
|
||||||
assert(!(!testEncrypting && isStillEncrypting));
|
assert(!(!testEncrypting && isStillEncrypting));
|
||||||
testEncrypting = isStillEncrypting;
|
testEncrypting = isStillEncrypting;
|
||||||
})
|
});
|
||||||
|
|
||||||
return fs.upload()
|
return fs
|
||||||
|
.upload()
|
||||||
.then(info => {
|
.then(info => {
|
||||||
assert(info);
|
assert(info);
|
||||||
assert(!testEncrypting);
|
assert(!testEncrypting);
|
||||||
|
@ -100,10 +101,10 @@ describe('File Sender', function() {
|
||||||
console.log(err, err.stack);
|
console.log(err, err.stack);
|
||||||
assert.fail();
|
assert.fail();
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Should encrypt a file properly', function(done) {
|
it('Should encrypt a file properly', function(done) {
|
||||||
const newFile = new FakeFile('hello_world.txt', ['This is some data.'])
|
const newFile = new FakeFile('hello_world.txt', ['This is some data.']);
|
||||||
const fs = new FileSender(newFile);
|
const fs = new FileSender(newFile);
|
||||||
fs.upload().then(info => {
|
fs.upload().then(info => {
|
||||||
const key = info.secretKey;
|
const key = info.secretKey;
|
||||||
|
@ -111,20 +112,21 @@ describe('File Sender', function() {
|
||||||
const IV = info.fileId;
|
const IV = info.fileId;
|
||||||
encryptedIV = info.fileId;
|
encryptedIV = info.fileId;
|
||||||
|
|
||||||
const readRaw = new FileReader;
|
const readRaw = new FileReader();
|
||||||
readRaw.onload = function(event) {
|
readRaw.onload = function(event) {
|
||||||
const rawArray = new Uint8Array(this.result);
|
const rawArray = new Uint8Array(this.result);
|
||||||
originalBlob = rawArray;
|
originalBlob = rawArray;
|
||||||
|
|
||||||
window.crypto.subtle.digest('SHA-256', rawArray).then(hash => {
|
window.crypto.subtle.digest('SHA-256', rawArray).then(hash => {
|
||||||
fileHash = hash;
|
fileHash = hash;
|
||||||
window.crypto.subtle.importKey(
|
window.crypto.subtle
|
||||||
|
.importKey(
|
||||||
'jwk',
|
'jwk',
|
||||||
{
|
{
|
||||||
kty: 'oct',
|
kty: 'oct',
|
||||||
k: key,
|
k: key,
|
||||||
alg: 'A128GCM',
|
alg: 'A128GCM',
|
||||||
ext: true,
|
ext: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'AES-GCM'
|
name: 'AES-GCM'
|
||||||
|
@ -133,7 +135,8 @@ describe('File Sender', function() {
|
||||||
['encrypt', 'decrypt']
|
['encrypt', 'decrypt']
|
||||||
)
|
)
|
||||||
.then(cryptoKey => {
|
.then(cryptoKey => {
|
||||||
window.crypto.subtle.encrypt(
|
window.crypto.subtle
|
||||||
|
.encrypt(
|
||||||
{
|
{
|
||||||
name: 'AES-GCM',
|
name: 'AES-GCM',
|
||||||
iv: hexToArray(IV),
|
iv: hexToArray(IV),
|
||||||
|
@ -144,23 +147,22 @@ describe('File Sender', function() {
|
||||||
rawArray
|
rawArray
|
||||||
)
|
)
|
||||||
.then(encrypted => {
|
.then(encrypted => {
|
||||||
assert(new Uint8Array(encrypted).toString() ===
|
assert(
|
||||||
new Uint8Array(file).toString());
|
new Uint8Array(encrypted).toString() ===
|
||||||
|
new Uint8Array(file).toString()
|
||||||
|
);
|
||||||
done();
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
readRaw.readAsArrayBuffer(newFile);
|
readRaw.readAsArrayBuffer(newFile);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('File Receiver', function() {
|
describe('File Receiver', function() {
|
||||||
|
|
||||||
class FakeXHR {
|
class FakeXHR {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.response = file;
|
this.response = file;
|
||||||
|
@ -169,19 +171,19 @@ describe('File Receiver', function() {
|
||||||
|
|
||||||
static setup() {
|
static setup() {
|
||||||
FakeXHR.prototype.open = sinon.spy();
|
FakeXHR.prototype.open = sinon.spy();
|
||||||
FakeXHR.prototype.send = function () {
|
FakeXHR.prototype.send = function() {
|
||||||
this.onload();
|
this.onload();
|
||||||
}
|
};
|
||||||
|
|
||||||
FakeXHR.prototype.originalXHR = window.XMLHttpRequest;
|
FakeXHR.prototype.originalXHR = window.XMLHttpRequest;
|
||||||
|
|
||||||
FakeXHR.prototype.getResponseHeader = function () {
|
FakeXHR.prototype.getResponseHeader = function() {
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
aad: arrayToHex(new Uint8Array(fileHash)),
|
aad: arrayToHex(new Uint8Array(fileHash)),
|
||||||
filename: 'hello_world.txt',
|
filename: 'hello_world.txt',
|
||||||
id: encryptedIV
|
id: encryptedIV
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
window.XMLHttpRequest = FakeXHR;
|
window.XMLHttpRequest = FakeXHR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,36 +195,45 @@ describe('File Receiver', function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const cb = function(done) {
|
const cb = function(done) {
|
||||||
if (file === undefined ||
|
if (
|
||||||
|
file === undefined ||
|
||||||
encryptedIV === undefined ||
|
encryptedIV === undefined ||
|
||||||
fileHash === undefined ||
|
fileHash === undefined ||
|
||||||
secretKey === undefined) {
|
secretKey === undefined
|
||||||
assert.fail('Please run file sending tests before trying to receive the files.');
|
) {
|
||||||
|
assert.fail(
|
||||||
|
'Please run file sending tests before trying to receive the files.'
|
||||||
|
);
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|
||||||
FakeXHR.setup();
|
FakeXHR.setup();
|
||||||
done();
|
done();
|
||||||
}
|
};
|
||||||
|
|
||||||
before(cb)
|
before(cb);
|
||||||
|
|
||||||
after(function() {
|
after(function() {
|
||||||
FakeXHR.restore();
|
FakeXHR.restore();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Should decrypt properly', function() {
|
it('Should decrypt properly', function() {
|
||||||
const fr = new FileReceiver();
|
const fr = new FileReceiver();
|
||||||
location.hash = secretKey;
|
location.hash = secretKey;
|
||||||
return fr.download().then(([decrypted, name]) => {
|
return fr
|
||||||
|
.download()
|
||||||
|
.then(([decrypted, name]) => {
|
||||||
assert(name);
|
assert(name);
|
||||||
assert(new Uint8Array(decrypted).toString() ===
|
assert(
|
||||||
new Uint8Array(originalBlob).toString())
|
new Uint8Array(decrypted).toString() ===
|
||||||
}).catch(err => {
|
new Uint8Array(originalBlob).toString()
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
console.log(err, err.stack);
|
console.log(err, err.stack);
|
||||||
assert.fail();
|
assert.fail();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Should emit decrypting events', function() {
|
it('Should emit decrypting events', function() {
|
||||||
const fr = new FileReceiver();
|
const fr = new FileReceiver();
|
||||||
|
@ -237,17 +248,20 @@ describe('File Receiver', function() {
|
||||||
|
|
||||||
fr.on('safe', isSafe => {
|
fr.on('safe', isSafe => {
|
||||||
assert(isSafe);
|
assert(isSafe);
|
||||||
})
|
});
|
||||||
|
|
||||||
return fr.download().then(([decrypted, name]) => {
|
return fr
|
||||||
|
.download()
|
||||||
|
.then(([decrypted, name]) => {
|
||||||
assert(decrypted);
|
assert(decrypted);
|
||||||
assert(name);
|
assert(name);
|
||||||
assert(!testDecrypting);
|
assert(!testDecrypting);
|
||||||
}).catch(err => {
|
})
|
||||||
|
.catch(err => {
|
||||||
console.log(err, err.stack);
|
console.log(err, err.stack);
|
||||||
assert.fail();
|
assert.fail();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Should emit hashing events', function() {
|
it('Should emit hashing events', function() {
|
||||||
const fr = new FileReceiver();
|
const fr = new FileReceiver();
|
||||||
|
@ -262,27 +276,32 @@ describe('File Receiver', function() {
|
||||||
|
|
||||||
fr.on('safe', isSafe => {
|
fr.on('safe', isSafe => {
|
||||||
assert(isSafe);
|
assert(isSafe);
|
||||||
})
|
});
|
||||||
|
|
||||||
return fr.download().then(([decrypted, name]) => {
|
return fr
|
||||||
|
.download()
|
||||||
|
.then(([decrypted, name]) => {
|
||||||
assert(decrypted);
|
assert(decrypted);
|
||||||
assert(name);
|
assert(name);
|
||||||
assert(!testHashing);
|
assert(!testHashing);
|
||||||
}).catch(err => {
|
})
|
||||||
|
.catch(err => {
|
||||||
assert.fail();
|
assert.fail();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Should catch fraudulent checksums', function(done) {
|
it('Should catch fraudulent checksums', function(done) {
|
||||||
// Use the secret key and file hash of the previous file to encrypt,
|
// Use the secret key and file hash of the previous file to encrypt,
|
||||||
// which has a different hash than this one (different strings).
|
// which has a different hash than this one (different strings).
|
||||||
const newFile = new FakeFile('hello_world.txt',
|
const newFile = new FakeFile('hello_world.txt', [
|
||||||
['This is some data, with a changed hash.'])
|
'This is some data, with a changed hash.'
|
||||||
|
]);
|
||||||
const readRaw = new FileReader();
|
const readRaw = new FileReader();
|
||||||
|
|
||||||
readRaw.onload = function(event) {
|
readRaw.onload = function(event) {
|
||||||
const plaintext = new Uint8Array(this.result);
|
const plaintext = new Uint8Array(this.result);
|
||||||
window.crypto.subtle.importKey(
|
window.crypto.subtle
|
||||||
|
.importKey(
|
||||||
'jwk',
|
'jwk',
|
||||||
{
|
{
|
||||||
kty: 'oct',
|
kty: 'oct',
|
||||||
|
@ -308,7 +327,7 @@ describe('File Receiver', function() {
|
||||||
},
|
},
|
||||||
key,
|
key,
|
||||||
plaintext
|
plaintext
|
||||||
)
|
);
|
||||||
})
|
})
|
||||||
.then(encrypted => {
|
.then(encrypted => {
|
||||||
file = encrypted;
|
file = encrypted;
|
||||||
|
@ -316,45 +335,50 @@ describe('File Receiver', function() {
|
||||||
location.hash = secretKey;
|
location.hash = secretKey;
|
||||||
|
|
||||||
fr.on('unsafe', isUnsafe => {
|
fr.on('unsafe', isUnsafe => {
|
||||||
assert(isUnsafe)
|
assert(isUnsafe);
|
||||||
})
|
});
|
||||||
|
|
||||||
fr.on('safe', () => {
|
fr.on('safe', () => {
|
||||||
// This event should not be emitted.
|
// This event should not be emitted.
|
||||||
assert.fail();
|
assert.fail();
|
||||||
})
|
});
|
||||||
|
|
||||||
fr.download().then(() => {
|
fr
|
||||||
|
.download()
|
||||||
|
.then(() => {
|
||||||
assert.fail();
|
assert.fail();
|
||||||
done();
|
done();
|
||||||
}).catch(err => {
|
})
|
||||||
|
.catch(err => {
|
||||||
assert(1);
|
assert(1);
|
||||||
done();
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
readRaw.readAsArrayBuffer(newFile);
|
readRaw.readAsArrayBuffer(newFile);
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Should not decrypt with an incorrect checksum', function() {
|
it('Should not decrypt with an incorrect checksum', function() {
|
||||||
FakeXHR.prototype.getResponseHeader = function () {
|
FakeXHR.prototype.getResponseHeader = function() {
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
aad: 'some_bad_hashz',
|
aad: 'some_bad_hashz',
|
||||||
filename: 'hello_world.txt',
|
filename: 'hello_world.txt',
|
||||||
id: encryptedIV
|
id: encryptedIV
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
const fr = new FileReceiver();
|
const fr = new FileReceiver();
|
||||||
location.hash = secretKey;
|
location.hash = secretKey;
|
||||||
|
|
||||||
return fr.download().then(([decrypted, name]) => {
|
return fr
|
||||||
|
.download()
|
||||||
|
.then(([decrypted, name]) => {
|
||||||
assert(decrypted);
|
assert(decrypted);
|
||||||
assert(name);
|
assert(name);
|
||||||
assert.fail();
|
assert.fail();
|
||||||
}).catch(err => {
|
})
|
||||||
|
.catch(err => {
|
||||||
assert(1);
|
assert(1);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
});
|
||||||
})
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ const proxyquire = require('proxyquire');
|
||||||
const request = require('supertest');
|
const request = require('supertest');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
|
|
||||||
const logStub = {};
|
const logStub = {};
|
||||||
logStub.info = sinon.stub();
|
logStub.info = sinon.stub();
|
||||||
logStub.error = sinon.stub();
|
logStub.error = sinon.stub();
|
||||||
|
@ -38,17 +37,21 @@ describe('Server integration tests', function() {
|
||||||
storage.flushall();
|
storage.flushall();
|
||||||
storage.quit();
|
storage.quit();
|
||||||
server.close();
|
server.close();
|
||||||
})
|
});
|
||||||
|
|
||||||
function upload() {
|
function upload() {
|
||||||
return request(server).post('/upload')
|
return request(server)
|
||||||
|
.post('/upload')
|
||||||
.field('fname', 'test_upload.txt')
|
.field('fname', 'test_upload.txt')
|
||||||
.set('X-File-Metadata', JSON.stringify({
|
.set(
|
||||||
|
'X-File-Metadata',
|
||||||
|
JSON.stringify({
|
||||||
aad: '11111',
|
aad: '11111',
|
||||||
id: '111111111111111111111111',
|
id: '111111111111111111111111',
|
||||||
filename: 'test_upload.txt'
|
filename: 'test_upload.txt'
|
||||||
}))
|
})
|
||||||
.attach('file', './test/test_upload.txt')
|
)
|
||||||
|
.attach('file', './test/test_upload.txt');
|
||||||
}
|
}
|
||||||
|
|
||||||
it('Responds with a 200 when the service is up', function() {
|
it('Responds with a 200 when the service is up', function() {
|
||||||
|
@ -56,14 +59,18 @@ describe('Server integration tests', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Rejects with a 404 when a file id is not valid', function() {
|
it('Rejects with a 404 when a file id is not valid', function() {
|
||||||
return request(server).post('/upload/123')
|
return request(server)
|
||||||
|
.post('/upload/123')
|
||||||
.field('fname', 'test_upload.txt')
|
.field('fname', 'test_upload.txt')
|
||||||
.set('X-File-Metadata', JSON.stringify({
|
.set(
|
||||||
'silly': 'text'
|
'X-File-Metadata',
|
||||||
}))
|
JSON.stringify({
|
||||||
.attach('file', './test/test_upload.txt')
|
silly: 'text'
|
||||||
.expect(404)
|
|
||||||
})
|
})
|
||||||
|
)
|
||||||
|
.attach('file', './test/test_upload.txt')
|
||||||
|
.expect(404);
|
||||||
|
});
|
||||||
|
|
||||||
it('Accepts a file and stores it when properly uploaded', function(done) {
|
it('Accepts a file and stores it when properly uploaded', function(done) {
|
||||||
upload().then(res => {
|
upload().then(res => {
|
||||||
|
@ -78,34 +85,37 @@ describe('Server integration tests', function() {
|
||||||
} else {
|
} else {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Responds with a 200 if a file exists', function() {
|
it('Responds with a 200 if a file exists', function() {
|
||||||
return request(server).get('/exists/' + fileId)
|
return request(server).get('/exists/' + fileId).expect(200);
|
||||||
.expect(200)
|
});
|
||||||
})
|
|
||||||
|
|
||||||
it('Exists in the redis server', function() {
|
it('Exists in the redis server', function() {
|
||||||
return storage.exists(fileId)
|
return storage
|
||||||
|
.exists(fileId)
|
||||||
.then(() => assert(1))
|
.then(() => assert(1))
|
||||||
.catch(err => assert.fail())
|
.catch(err => assert.fail());
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Fails delete if the delete token does not match', function() {
|
it('Fails delete if the delete token does not match', function() {
|
||||||
return request(server).post('/delete/' + fileId)
|
return request(server)
|
||||||
|
.post('/delete/' + fileId)
|
||||||
.send({ delete_token: 11 })
|
.send({ delete_token: 11 })
|
||||||
.expect(404);
|
.expect(404);
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Fails delete if the id is invalid', function() {
|
it('Fails delete if the id is invalid', function() {
|
||||||
return request(server).post('/delete/1')
|
return request(server).post('/delete/1').expect(404);
|
||||||
.expect(404);
|
});
|
||||||
})
|
|
||||||
|
|
||||||
it('Successfully deletes if the id is valid and the delete token matches', function(done) {
|
it('Successfully deletes if the id is valid and the delete token matches', function(
|
||||||
request(server).post('/delete/' + fileId)
|
done
|
||||||
|
) {
|
||||||
|
request(server)
|
||||||
|
.post('/delete/' + fileId)
|
||||||
.send({ delete_token: uuid })
|
.send({ delete_token: uuid })
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -115,14 +125,13 @@ describe('Server integration tests', function() {
|
||||||
} else {
|
} else {
|
||||||
done(new Error('The file does not exist'));
|
done(new Error('The file does not exist'));
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Responds with a 404 if a file does not exist', function() {
|
it('Responds with a 404 if a file does not exist', function() {
|
||||||
return request(server).get('/exists/notfound')
|
return request(server).get('/exists/notfound').expect(404);
|
||||||
.expect(404)
|
});
|
||||||
})
|
|
||||||
|
|
||||||
it('Uploads properly after a delete', function(done) {
|
it('Uploads properly after a delete', function(done) {
|
||||||
upload().then(res => {
|
upload().then(res => {
|
||||||
|
@ -137,34 +146,36 @@ describe('Server integration tests', function() {
|
||||||
} else {
|
} else {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Responds with a 200 for the download page', function() {
|
it('Responds with a 200 for the download page', function() {
|
||||||
return request(server).get('/download/' + fileId)
|
return request(server).get('/download/' + fileId).expect(200);
|
||||||
.expect(200);
|
});
|
||||||
})
|
|
||||||
|
|
||||||
it('Downloads a file properly', function() {
|
it('Downloads a file properly', function() {
|
||||||
return request(server).get('/assets/download/' + fileId)
|
return request(server).get('/assets/download/' + fileId).then(res => {
|
||||||
.then(res => {
|
|
||||||
assert(res.header.hasOwnProperty('content-disposition'));
|
assert(res.header.hasOwnProperty('content-disposition'));
|
||||||
assert(res.header.hasOwnProperty('content-type'))
|
assert(res.header.hasOwnProperty('content-type'));
|
||||||
assert(res.header.hasOwnProperty('content-length'))
|
assert(res.header.hasOwnProperty('content-length'));
|
||||||
assert(res.header.hasOwnProperty('x-file-metadata'))
|
assert(res.header.hasOwnProperty('x-file-metadata'));
|
||||||
assert.equal(res.header['content-disposition'], 'attachment; filename=test_upload.txt')
|
assert.equal(
|
||||||
assert.equal(res.header['content-type'], 'application/octet-stream')
|
res.header['content-disposition'],
|
||||||
})
|
'attachment; filename=test_upload.txt'
|
||||||
})
|
);
|
||||||
|
assert.equal(res.header['content-type'], 'application/octet-stream');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('The file is deleted after one download', function() {
|
it('The file is deleted after one download', function() {
|
||||||
assert(!fs.existsSync('./static/' + fileId));
|
assert(!fs.existsSync('./static/' + fileId));
|
||||||
})
|
});
|
||||||
|
|
||||||
it('No longer exists in the redis server', function() {
|
it('No longer exists in the redis server', function() {
|
||||||
return storage.exists(fileId)
|
return storage
|
||||||
|
.exists(fileId)
|
||||||
.then(() => assert.fail())
|
.then(() => assert.fail())
|
||||||
.catch(err => assert(1))
|
.catch(err => assert(1));
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -110,9 +110,9 @@ describe('Testing Set using aws', function() {
|
||||||
it('Should pass when the file is successfully uploaded', function() {
|
it('Should pass when the file is successfully uploaded', function() {
|
||||||
const buf = Buffer.alloc(10);
|
const buf = Buffer.alloc(10);
|
||||||
sinon.stub(crypto, 'randomBytes').returns(buf);
|
sinon.stub(crypto, 'randomBytes').returns(buf);
|
||||||
s3Stub.upload.returns({promise: () => Promise.resolve()});
|
s3Stub.upload.returns({ promise: () => Promise.resolve() });
|
||||||
return storage
|
return storage
|
||||||
.set('123', {on: sinon.stub()}, 'Filename.moz', {})
|
.set('123', { on: sinon.stub() }, 'Filename.moz', {})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
assert(expire.calledOnce);
|
assert(expire.calledOnce);
|
||||||
assert(expire.calledWith('123', 86400));
|
assert(expire.calledWith('123', 86400));
|
||||||
|
@ -121,9 +121,9 @@ describe('Testing Set using aws', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should fail if there was an error during uploading', function() {
|
it('Should fail if there was an error during uploading', function() {
|
||||||
s3Stub.upload.returns({promise: () => Promise.reject()});
|
s3Stub.upload.returns({ promise: () => Promise.reject() });
|
||||||
return storage
|
return storage
|
||||||
.set('123', {on: sinon.stub()}, 'Filename.moz', 'url.com')
|
.set('123', { on: sinon.stub() }, 'Filename.moz', 'url.com')
|
||||||
.then(_reply => assert.fail())
|
.then(_reply => assert.fail())
|
||||||
.catch(err => assert(1));
|
.catch(err => assert(1));
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue