integrate with new ui
This commit is contained in:
parent
13057804ab
commit
bf16e5c8a9
30
app/api.js
30
app/api.js
|
@ -136,7 +136,14 @@ function listenForResponse(ws, canceller) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function upload(stream, metadata, verifierB64, onprogress, canceller) {
|
async function upload(
|
||||||
|
stream,
|
||||||
|
metadata,
|
||||||
|
verifierB64,
|
||||||
|
timeLimit,
|
||||||
|
onprogress,
|
||||||
|
canceller
|
||||||
|
) {
|
||||||
const host = window.location.hostname;
|
const host = window.location.hostname;
|
||||||
const port = window.location.port;
|
const port = window.location.port;
|
||||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||||
|
@ -151,7 +158,8 @@ async function upload(stream, metadata, verifierB64, onprogress, canceller) {
|
||||||
const metadataHeader = arrayToB64(new Uint8Array(metadata));
|
const metadataHeader = arrayToB64(new Uint8Array(metadata));
|
||||||
const fileMeta = {
|
const fileMeta = {
|
||||||
fileMetadata: metadataHeader,
|
fileMetadata: metadataHeader,
|
||||||
authorization: `send-v1 ${verifierB64}`
|
authorization: `send-v1 ${verifierB64}`,
|
||||||
|
timeLimit
|
||||||
};
|
};
|
||||||
|
|
||||||
const responsePromise = listenForResponse(ws, canceller);
|
const responsePromise = listenForResponse(ws, canceller);
|
||||||
|
@ -188,7 +196,13 @@ async function upload(stream, metadata, verifierB64, onprogress, canceller) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function uploadWs(encrypted, metadata, verifierB64, onprogress) {
|
export function uploadWs(
|
||||||
|
encrypted,
|
||||||
|
metadata,
|
||||||
|
verifierB64,
|
||||||
|
onprogress,
|
||||||
|
timeLimit
|
||||||
|
) {
|
||||||
const canceller = { cancelled: false };
|
const canceller = { cancelled: false };
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -196,7 +210,15 @@ export function uploadWs(encrypted, metadata, verifierB64, onprogress) {
|
||||||
canceller.error = new Error(0);
|
canceller.error = new Error(0);
|
||||||
canceller.cancelled = true;
|
canceller.cancelled = true;
|
||||||
},
|
},
|
||||||
result: upload(encrypted, metadata, verifierB64, onprogress, canceller)
|
|
||||||
|
result: upload(
|
||||||
|
encrypted,
|
||||||
|
metadata,
|
||||||
|
verifierB64,
|
||||||
|
timeLimit,
|
||||||
|
onprogress,
|
||||||
|
canceller
|
||||||
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -276,7 +276,6 @@ a {
|
||||||
}
|
}
|
||||||
|
|
||||||
.stripedBox {
|
.stripedBox {
|
||||||
margin-top: 72;
|
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
@ -289,3 +288,9 @@ a {
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-device-width: 700px), (max-width: 700px) {
|
||||||
|
.stripedBox {
|
||||||
|
margin-top: 72px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* global MAXFILESIZE */
|
/* global MAXFILESIZE */
|
||||||
|
/* global DEFAULT_EXPIRE_SECONDS */
|
||||||
import FileSender from './fileSender';
|
import FileSender from './fileSender';
|
||||||
import FileReceiver from './fileReceiver';
|
import FileReceiver from './fileReceiver';
|
||||||
import { copyToClipboard, delay, openLinksInNewTab, percent } from './utils';
|
import { copyToClipboard, delay, openLinksInNewTab, percent } from './utils';
|
||||||
|
@ -110,7 +111,9 @@ export default function(state, emitter) {
|
||||||
emitter.on('upload', async ({ type, dlCount, password }) => {
|
emitter.on('upload', async ({ type, dlCount, password }) => {
|
||||||
if (!state.archive) return;
|
if (!state.archive) return;
|
||||||
const size = state.archive.size;
|
const size = state.archive.size;
|
||||||
const sender = new FileSender(state.archive);
|
if (!state.timeLimit) state.timeLimit = DEFAULT_EXPIRE_SECONDS;
|
||||||
|
const sender = new FileSender(state.archive, state.timeLimit);
|
||||||
|
|
||||||
sender.on('progress', updateProgress);
|
sender.on('progress', updateProgress);
|
||||||
sender.on('encrypting', render);
|
sender.on('encrypting', render);
|
||||||
sender.on('complete', render);
|
sender.on('complete', render);
|
||||||
|
@ -157,7 +160,7 @@ export default function(state, emitter) {
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
openLinksInNewTab(links, false);
|
openLinksInNewTab(links, false);
|
||||||
state.files = [];
|
state.archive = null;
|
||||||
state.password = '';
|
state.password = '';
|
||||||
state.uploading = false;
|
state.uploading = false;
|
||||||
state.transfer = null;
|
state.transfer = null;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global EXPIRE_SECONDS */
|
/* global DEFAULT_EXPIRE_SECONDS */
|
||||||
import Nanobus from 'nanobus';
|
import Nanobus from 'nanobus';
|
||||||
import OwnedFile from './ownedFile';
|
import OwnedFile from './ownedFile';
|
||||||
import Keychain from './keychain';
|
import Keychain from './keychain';
|
||||||
|
@ -7,8 +7,9 @@ import { uploadWs } from './api';
|
||||||
import { encryptedSize } from './ece';
|
import { encryptedSize } from './ece';
|
||||||
|
|
||||||
export default class FileSender extends Nanobus {
|
export default class FileSender extends Nanobus {
|
||||||
constructor(file) {
|
constructor(file, timeLimit) {
|
||||||
super('FileSender');
|
super('FileSender');
|
||||||
|
this.timeLimit = timeLimit || DEFAULT_EXPIRE_SECONDS;
|
||||||
this.file = file;
|
this.file = file;
|
||||||
this.keychain = new Keychain();
|
this.keychain = new Keychain();
|
||||||
this.reset();
|
this.reset();
|
||||||
|
@ -70,10 +71,16 @@ export default class FileSender extends Nanobus {
|
||||||
const metadata = await this.keychain.encryptMetadata(this.file);
|
const metadata = await this.keychain.encryptMetadata(this.file);
|
||||||
const authKeyB64 = await this.keychain.authKeyB64();
|
const authKeyB64 = await this.keychain.authKeyB64();
|
||||||
|
|
||||||
this.uploadRequest = uploadWs(encStream, metadata, authKeyB64, p => {
|
this.uploadRequest = uploadWs(
|
||||||
this.progress = [p, totalSize];
|
encStream,
|
||||||
this.emit('progress');
|
metadata,
|
||||||
});
|
authKeyB64,
|
||||||
|
p => {
|
||||||
|
this.progress = [p, totalSize];
|
||||||
|
this.emit('progress');
|
||||||
|
},
|
||||||
|
this.timeLimit
|
||||||
|
);
|
||||||
|
|
||||||
if (this.cancelled) {
|
if (this.cancelled) {
|
||||||
throw new Error(0);
|
throw new Error(0);
|
||||||
|
@ -97,10 +104,11 @@ export default class FileSender extends Nanobus {
|
||||||
time: time,
|
time: time,
|
||||||
speed: this.file.size / (time / 1000),
|
speed: this.file.size / (time / 1000),
|
||||||
createdAt: Date.now(),
|
createdAt: Date.now(),
|
||||||
expiresAt: Date.now() + EXPIRE_SECONDS * 1000,
|
expiresAt: Date.now() + this.timeLimit * 1000,
|
||||||
secretKey: secretKey,
|
secretKey: secretKey,
|
||||||
nonce: this.keychain.nonce,
|
nonce: this.keychain.nonce,
|
||||||
ownerToken: result.ownerToken
|
ownerToken: result.ownerToken,
|
||||||
|
timeLimit: this.timeLimit
|
||||||
});
|
});
|
||||||
|
|
||||||
return ownedFile;
|
return ownedFile;
|
||||||
|
|
|
@ -19,6 +19,7 @@ export default class OwnedFile {
|
||||||
this.dtotal = obj.dtotal || 0;
|
this.dtotal = obj.dtotal || 0;
|
||||||
this.keychain = new Keychain(obj.secretKey, obj.nonce);
|
this.keychain = new Keychain(obj.secretKey, obj.nonce);
|
||||||
this._hasPassword = !!obj.hasPassword;
|
this._hasPassword = !!obj.hasPassword;
|
||||||
|
this.timeLimit = obj.timeLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
async setPassword(password) {
|
async setPassword(password) {
|
||||||
|
@ -80,7 +81,8 @@ export default class OwnedFile {
|
||||||
ownerToken: this.ownerToken,
|
ownerToken: this.ownerToken,
|
||||||
dlimit: this.dlimit,
|
dlimit: this.dlimit,
|
||||||
dtotal: this.dtotal,
|
dtotal: this.dtotal,
|
||||||
hasPassword: this.hasPassword
|
hasPassword: this.hasPassword,
|
||||||
|
timeLimit: this.timeLimit
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/* global EXPIRE_SECONDS */
|
|
||||||
const html = require('choo/html');
|
const html = require('choo/html');
|
||||||
const raw = require('choo/html/raw');
|
const raw = require('choo/html/raw');
|
||||||
const assets = require('../../../common/assets');
|
const assets = require('../../../common/assets');
|
||||||
const notFound = require('../notFound');
|
const notFound = require('../notFound');
|
||||||
const deletePopup = require('../../templates/popup');
|
const deletePopup = require('../../templates/popup');
|
||||||
const uploadedFileList = require('../../templates/uploadedFileList');
|
const uploadedFileList = require('../../templates/uploadedFileList');
|
||||||
|
const timeLimitText = require('../../templates/timeLimitText');
|
||||||
const { allowedCopy, delay, fadeOut } = require('../../utils');
|
const { allowedCopy, delay, fadeOut } = require('../../utils');
|
||||||
|
|
||||||
module.exports = function(state, emit) {
|
module.exports = function(state, emit) {
|
||||||
|
@ -18,7 +18,6 @@ module.exports = function(state, emit) {
|
||||||
: 'passwordReminder--hidden';
|
: 'passwordReminder--hidden';
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
|
|
||||||
<div class="page effect--fadeIn" id="shareWrapper">
|
<div class="page effect--fadeIn" id="shareWrapper">
|
||||||
<a href="/" class="goBackButton">
|
<a href="/" class="goBackButton">
|
||||||
<img src="${assets.get('back-arrow.svg')}"/>
|
<img src="${assets.get('back-arrow.svg')}"/>
|
||||||
|
@ -98,13 +97,14 @@ module.exports = function(state, emit) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function expireInfo(file, translate) {
|
function expireInfo(file, translate) {
|
||||||
const hours = Math.floor(EXPIRE_SECONDS / 60 / 60);
|
const el = html`<div class="shareTitle">
|
||||||
const el = html`<div class="shareTitle">${raw(
|
${raw(
|
||||||
translate('expireInfo', {
|
translate('expireInfo', {
|
||||||
downloadCount: translate('downloadCount', { num: file.dlimit }),
|
downloadCount: translate('downloadCount', { num: file.dlimit }),
|
||||||
timespan: translate('timespanHours', { num: hours })
|
timespan: timeLimitText(translate, file.timeLimit)
|
||||||
})
|
})
|
||||||
)}</div>`;
|
)}
|
||||||
|
</div>`;
|
||||||
|
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ module.exports = function(state, emit) {
|
||||||
${title(state)}
|
${title(state)}
|
||||||
|
|
||||||
<label class="uploadArea"
|
<label class="uploadArea"
|
||||||
|
|
||||||
ondragover=${dragover}
|
ondragover=${dragover}
|
||||||
ondragleave=${dragleave}>
|
ondragleave=${dragleave}>
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
const html = require('choo/html');
|
const html = require('choo/html');
|
||||||
const raw = require('choo/html/raw');
|
const raw = require('choo/html/raw');
|
||||||
const selectbox = require('../selectbox');
|
const selectbox = require('../selectbox');
|
||||||
|
const timeLimitText = require('../timeLimitText');
|
||||||
|
|
||||||
module.exports = function(state) {
|
module.exports = function(state) {
|
||||||
const el = html`<div> ${raw(
|
const el = html`<div> ${raw(
|
||||||
state.translate('frontPageExpireInfo', {
|
state.translate('frontPageExpireInfo', {
|
||||||
downloadCount: '<select id=dlCount></select>',
|
downloadCount: '<select id=dlCount></select>',
|
||||||
timespan: state.translate('timespanHours', { num: 24 }) //'<select id=timespan></select>'
|
timespan: '<select id=timespan></select>'
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
</div>`;
|
</div>`;
|
||||||
|
@ -24,13 +25,18 @@ module.exports = function(state) {
|
||||||
dlCountSelect
|
dlCountSelect
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
|
||||||
const timeSelect = el.querySelector('#timespan');
|
const timeSelect = el.querySelector('#timespan');
|
||||||
el.replaceChild(
|
el.replaceChild(
|
||||||
selectbox(1, [1, 2, 3, 4, 5], num => num, () => {}),
|
selectbox(
|
||||||
|
state.timeLimit || 86400,
|
||||||
|
[300, 3600, 86400, 604800, 1209600],
|
||||||
|
num => timeLimitText(state.translate, num),
|
||||||
|
value => {
|
||||||
|
state.timeLimit = value;
|
||||||
|
}
|
||||||
|
),
|
||||||
timeSelect
|
timeSelect
|
||||||
);
|
);
|
||||||
*/
|
|
||||||
|
|
||||||
return el;
|
return el;
|
||||||
};
|
};
|
||||||
|
|
|
@ -51,6 +51,14 @@ module.exports = function(file, state) {
|
||||||
function timeLeft(milliseconds, state) {
|
function timeLeft(milliseconds, state) {
|
||||||
const minutes = Math.floor(milliseconds / 1000 / 60);
|
const minutes = Math.floor(milliseconds / 1000 / 60);
|
||||||
const hours = Math.floor(minutes / 60);
|
const hours = Math.floor(minutes / 60);
|
||||||
|
const days = Math.floor(hours / 24);
|
||||||
|
if (days >= 1) {
|
||||||
|
return state.translate('expiresDaysHoursMinutes', {
|
||||||
|
days,
|
||||||
|
hours: hours % 24,
|
||||||
|
minutes: minutes % 60
|
||||||
|
});
|
||||||
|
}
|
||||||
if (hours >= 1) {
|
if (hours >= 1) {
|
||||||
return state.translate('expiresHoursMinutes', {
|
return state.translate('expiresHoursMinutes', {
|
||||||
hours,
|
hours,
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
width: 22px;
|
width: 22px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fileIcon__lock {
|
.fileIcon__lock {
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-device-width: 750px), (max-width: 750px) {
|
@media (max-device-width: 700px), (max-width: 700px) {
|
||||||
.signupPromo {
|
.signupPromo {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
module.exports = function(translate, seconds) {
|
||||||
|
const displayText = {
|
||||||
|
300: translate('timespanMinutes', { num: 5 }),
|
||||||
|
3600: translate('timespanHours', { num: 1 }),
|
||||||
|
86400: translate('timespanHours', { num: 24 }),
|
||||||
|
604800: translate('timespanWeeks', { num: 1 }),
|
||||||
|
1209600: translate('timespanWeeks', { num: 2 })
|
||||||
|
};
|
||||||
|
|
||||||
|
if (displayText[seconds]) {
|
||||||
|
return displayText[seconds];
|
||||||
|
}
|
||||||
|
return seconds;
|
||||||
|
};
|
|
@ -7,4 +7,5 @@
|
||||||
align-content: center;
|
align-content: center;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
|
@ -921,15 +921,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"aws-sdk": {
|
"aws-sdk": {
|
||||||
<<<<<<< HEAD
|
"version": "2.288.0",
|
||||||
"version": "2.285.1",
|
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.288.0.tgz",
|
||||||
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.285.1.tgz",
|
"integrity": "sha512-kV0yLAP3DPfUpDfFOCvOn4s/69XqVH7D53Vnfgf6mgKO5bp1HVFpWfTJ/OZeiwRy7hfIi0xTiSEmPXaMG0ACkg==",
|
||||||
"integrity": "sha512-lkroCYcnb7UWR/jbaW6wyjAeGROrsBFWyqUukQjICuCV4a0Mapnjsxefl2A/z+0SX3gnBN7owUb/60UjQSHpzA==",
|
|
||||||
=======
|
|
||||||
"version": "2.283.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.283.1.tgz",
|
|
||||||
"integrity": "sha512-UZmiWboO0WgZUKcTDSa5v6xuHqfNr9PQrOoilWUBnWpWO4s6h9LlSvIm06qyA3XQjEpXVmetHAMl9GmiHk51qw==",
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"buffer": "4.9.1",
|
"buffer": "4.9.1",
|
||||||
"events": "1.1.1",
|
"events": "1.1.1",
|
||||||
|
@ -2327,7 +2321,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/choo/-/choo-6.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/choo/-/choo-6.13.0.tgz",
|
||||||
"integrity": "sha512-OsXC4v8zKcGAJ+C3fTVxU30daZIWFcQwTZlHKWzHzZvEaRaaBGF95jqTd3XYV5+Eitx/SaklbqtaoWUAKCG/Nw==",
|
"integrity": "sha512-OsXC4v8zKcGAJ+C3fTVxU30daZIWFcQwTZlHKWzHzZvEaRaaBGF95jqTd3XYV5+Eitx/SaklbqtaoWUAKCG/Nw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"document-ready": "^2.0.1",
|
"document-ready": "^2.0.1",
|
||||||
"nanoassert": "^1.1.0",
|
"nanoassert": "^1.1.0",
|
||||||
"nanobus": "^4.2.0",
|
"nanobus": "^4.2.0",
|
||||||
|
@ -2342,22 +2335,6 @@
|
||||||
"nanotiming": "^7.0.0",
|
"nanotiming": "^7.0.0",
|
||||||
"scroll-to-anchor": "^1.0.0",
|
"scroll-to-anchor": "^1.0.0",
|
||||||
"xtend": "^4.0.1"
|
"xtend": "^4.0.1"
|
||||||
=======
|
|
||||||
"document-ready": "2.0.1",
|
|
||||||
"nanoassert": "1.1.0",
|
|
||||||
"nanobus": "4.3.3",
|
|
||||||
"nanocomponent": "6.5.2",
|
|
||||||
"nanohref": "3.0.3",
|
|
||||||
"nanohtml": "1.2.4",
|
|
||||||
"nanolru": "1.0.0",
|
|
||||||
"nanomorph": "5.1.3",
|
|
||||||
"nanoquery": "1.2.0",
|
|
||||||
"nanoraf": "3.1.0",
|
|
||||||
"nanorouter": "3.1.1",
|
|
||||||
"nanotiming": "7.3.1",
|
|
||||||
"scroll-to-anchor": "1.1.0",
|
|
||||||
"xtend": "4.0.1"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chownr": {
|
"chownr": {
|
||||||
|
@ -7804,13 +7781,8 @@
|
||||||
"integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=",
|
"integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"unist-util-modify-children": "^1.0.0",
|
"unist-util-modify-children": "^1.0.0",
|
||||||
"unist-util-visit": "^1.1.0"
|
"unist-util-visit": "^1.1.0"
|
||||||
=======
|
|
||||||
"unist-util-modify-children": "1.1.2",
|
|
||||||
"unist-util-visit": "1.4.0"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mdn-data": {
|
"mdn-data": {
|
||||||
|
@ -8286,7 +8258,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/nanoraf/-/nanoraf-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/nanoraf/-/nanoraf-3.1.0.tgz",
|
||||||
"integrity": "sha512-7Emv5Pv/fvgVK6yrud93WsdO4d3AUqLoP38Cpn0chYe+tT/wu25Yl2guxBjE3ngRrI5Yd9DxaTCgCFi1uq7hgQ==",
|
"integrity": "sha512-7Emv5Pv/fvgVK6yrud93WsdO4d3AUqLoP38Cpn0chYe+tT/wu25Yl2guxBjE3ngRrI5Yd9DxaTCgCFi1uq7hgQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"nanoassert": "1.1.0"
|
"nanoassert": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nanorouter": {
|
"nanorouter": {
|
||||||
|
@ -8446,24 +8418,6 @@
|
||||||
"version": "1.0.0-alpha.10",
|
"version": "1.0.0-alpha.10",
|
||||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.0-alpha.10.tgz",
|
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.0-alpha.10.tgz",
|
||||||
"integrity": "sha512-BSQrRgOfN6L/MoKIa7pRUc7dHvflCXMcqyTBvphixcSsgJTuUd24vAFONuNfVsuwTyz28S1HEc9XN6ZKylk4Hg==",
|
"integrity": "sha512-BSQrRgOfN6L/MoKIa7pRUc7dHvflCXMcqyTBvphixcSsgJTuUd24vAFONuNfVsuwTyz28S1HEc9XN6ZKylk4Hg==",
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"semver": "5.5.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nodesecurity-npm-utils": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/nodesecurity-npm-utils/-/nodesecurity-npm-utils-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-NLRle1woNaT2orR6fue2jNqkhxDTktgJj3sZxvR/8kp21pvOY7Gwlx5wvo0H8ZVPqdgd2nE2ADB9wDu5Cl8zNg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"nomnom": {
|
|
||||||
"version": "1.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz",
|
|
||||||
"integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=",
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"semver": "^5.3.0"
|
"semver": "^5.3.0"
|
||||||
|
@ -11772,17 +11726,10 @@
|
||||||
"integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
|
"integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"chalk": "^1.1.3",
|
"chalk": "^1.1.3",
|
||||||
"js-base64": "^2.1.9",
|
"js-base64": "^2.1.9",
|
||||||
"source-map": "^0.5.6",
|
"source-map": "^0.5.6",
|
||||||
"supports-color": "^3.2.3"
|
"supports-color": "^3.2.3"
|
||||||
=======
|
|
||||||
"chalk": "1.1.3",
|
|
||||||
"js-base64": "2.4.8",
|
|
||||||
"source-map": "0.5.7",
|
|
||||||
"supports-color": "3.2.3"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"supports-color": {
|
"supports-color": {
|
||||||
|
@ -12004,11 +11951,7 @@
|
||||||
"integrity": "sha512-xZsFA3uX8MO3yAda03QrG3/Eg1LN3EPfjjf07vke/46HERLZyHrTsQ9E1r1w1W//fWEhtYNndo2hQplN2cVpCQ==",
|
"integrity": "sha512-xZsFA3uX8MO3yAda03QrG3/Eg1LN3EPfjjf07vke/46HERLZyHrTsQ9E1r1w1W//fWEhtYNndo2hQplN2cVpCQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"postcss": "^7.0.0"
|
"postcss": "^7.0.0"
|
||||||
=======
|
|
||||||
"postcss": "7.0.2"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": {
|
"ansi-styles": {
|
||||||
|
@ -12017,11 +11960,7 @@
|
||||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"color-convert": "^1.9.0"
|
"color-convert": "^1.9.0"
|
||||||
=======
|
|
||||||
"color-convert": "1.9.2"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
|
@ -12030,15 +11969,9 @@
|
||||||
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
|
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"ansi-styles": "^3.2.1",
|
"ansi-styles": "^3.2.1",
|
||||||
"escape-string-regexp": "^1.0.5",
|
"escape-string-regexp": "^1.0.5",
|
||||||
"supports-color": "^5.3.0"
|
"supports-color": "^5.3.0"
|
||||||
=======
|
|
||||||
"ansi-styles": "3.2.1",
|
|
||||||
"escape-string-regexp": "1.0.5",
|
|
||||||
"supports-color": "5.4.0"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
|
@ -12047,15 +11980,9 @@
|
||||||
"integrity": "sha512-fmaUY5370keLUTx+CnwRxtGiuFTcNBLQBqr1oE3WZ/euIYmGAo0OAgOhVJ3ByDnVmOR3PK+0V9VebzfjRIUcqw==",
|
"integrity": "sha512-fmaUY5370keLUTx+CnwRxtGiuFTcNBLQBqr1oE3WZ/euIYmGAo0OAgOhVJ3ByDnVmOR3PK+0V9VebzfjRIUcqw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"chalk": "^2.4.1",
|
"chalk": "^2.4.1",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1",
|
||||||
"supports-color": "^5.4.0"
|
"supports-color": "^5.4.0"
|
||||||
=======
|
|
||||||
"chalk": "2.4.1",
|
|
||||||
"source-map": "0.6.1",
|
|
||||||
"supports-color": "5.4.0"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
|
@ -12070,11 +11997,7 @@
|
||||||
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
|
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"has-flag": "^3.0.0"
|
"has-flag": "^3.0.0"
|
||||||
=======
|
|
||||||
"has-flag": "3.0.0"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12143,11 +12066,7 @@
|
||||||
"integrity": "sha512-um9zdGKaDZirMm+kZFKKVsnKPF7zF7qBAtIfTSnZXD1jZ0JNZIxdB6TxQOjCnlSzLRInVl2v3YdBh/M881C4ug==",
|
"integrity": "sha512-um9zdGKaDZirMm+kZFKKVsnKPF7zF7qBAtIfTSnZXD1jZ0JNZIxdB6TxQOjCnlSzLRInVl2v3YdBh/M881C4ug==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"postcss": "^7.0.0"
|
"postcss": "^7.0.0"
|
||||||
=======
|
|
||||||
"postcss": "7.0.2"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": {
|
"ansi-styles": {
|
||||||
|
@ -12156,11 +12075,7 @@
|
||||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"color-convert": "^1.9.0"
|
"color-convert": "^1.9.0"
|
||||||
=======
|
|
||||||
"color-convert": "1.9.2"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
|
@ -12169,15 +12084,9 @@
|
||||||
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
|
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"ansi-styles": "^3.2.1",
|
"ansi-styles": "^3.2.1",
|
||||||
"escape-string-regexp": "^1.0.5",
|
"escape-string-regexp": "^1.0.5",
|
||||||
"supports-color": "^5.3.0"
|
"supports-color": "^5.3.0"
|
||||||
=======
|
|
||||||
"ansi-styles": "3.2.1",
|
|
||||||
"escape-string-regexp": "1.0.5",
|
|
||||||
"supports-color": "5.4.0"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
|
@ -12186,15 +12095,9 @@
|
||||||
"integrity": "sha512-fmaUY5370keLUTx+CnwRxtGiuFTcNBLQBqr1oE3WZ/euIYmGAo0OAgOhVJ3ByDnVmOR3PK+0V9VebzfjRIUcqw==",
|
"integrity": "sha512-fmaUY5370keLUTx+CnwRxtGiuFTcNBLQBqr1oE3WZ/euIYmGAo0OAgOhVJ3ByDnVmOR3PK+0V9VebzfjRIUcqw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"chalk": "^2.4.1",
|
"chalk": "^2.4.1",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1",
|
||||||
"supports-color": "^5.4.0"
|
"supports-color": "^5.4.0"
|
||||||
=======
|
|
||||||
"chalk": "2.4.1",
|
|
||||||
"source-map": "0.6.1",
|
|
||||||
"supports-color": "5.4.0"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
|
@ -12209,11 +12112,7 @@
|
||||||
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
|
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"has-flag": "^3.0.0"
|
"has-flag": "^3.0.0"
|
||||||
=======
|
|
||||||
"has-flag": "3.0.0"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14069,7 +13968,6 @@
|
||||||
"integrity": "sha512-pcw0Dpb4Ib/OfgONhaeF+myA+5iZdsI8dYgWs1++IYN/dgvo90O0FhgMDKb1bMgZVy/A2Q1CCN/PFZ0FLnnRnQ==",
|
"integrity": "sha512-pcw0Dpb4Ib/OfgONhaeF+myA+5iZdsI8dYgWs1++IYN/dgvo90O0FhgMDKb1bMgZVy/A2Q1CCN/PFZ0FLnnRnQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"autoprefixer": "^9.0.0",
|
"autoprefixer": "^9.0.0",
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"chalk": "^2.4.1",
|
"chalk": "^2.4.1",
|
||||||
|
@ -14114,52 +14012,6 @@
|
||||||
"sugarss": "^1.0.0",
|
"sugarss": "^1.0.0",
|
||||||
"svg-tags": "^1.0.0",
|
"svg-tags": "^1.0.0",
|
||||||
"table": "^4.0.1"
|
"table": "^4.0.1"
|
||||||
=======
|
|
||||||
"autoprefixer": "9.0.2",
|
|
||||||
"balanced-match": "1.0.0",
|
|
||||||
"chalk": "2.4.1",
|
|
||||||
"cosmiconfig": "5.0.5",
|
|
||||||
"debug": "3.1.0",
|
|
||||||
"execall": "1.0.0",
|
|
||||||
"file-entry-cache": "2.0.0",
|
|
||||||
"get-stdin": "6.0.0",
|
|
||||||
"globby": "8.0.1",
|
|
||||||
"globjoin": "0.1.4",
|
|
||||||
"html-tags": "2.0.0",
|
|
||||||
"ignore": "4.0.2",
|
|
||||||
"import-lazy": "3.1.0",
|
|
||||||
"imurmurhash": "0.1.4",
|
|
||||||
"known-css-properties": "0.6.1",
|
|
||||||
"lodash": "4.17.10",
|
|
||||||
"log-symbols": "2.2.0",
|
|
||||||
"mathml-tag-names": "2.1.0",
|
|
||||||
"meow": "5.0.0",
|
|
||||||
"micromatch": "2.3.11",
|
|
||||||
"normalize-selector": "0.2.0",
|
|
||||||
"pify": "3.0.0",
|
|
||||||
"postcss": "7.0.2",
|
|
||||||
"postcss-html": "0.31.0",
|
|
||||||
"postcss-less": "2.0.0",
|
|
||||||
"postcss-markdown": "0.31.0",
|
|
||||||
"postcss-media-query-parser": "0.2.3",
|
|
||||||
"postcss-reporter": "5.0.0",
|
|
||||||
"postcss-resolve-nested-selector": "0.1.1",
|
|
||||||
"postcss-safe-parser": "4.0.1",
|
|
||||||
"postcss-sass": "0.3.2",
|
|
||||||
"postcss-scss": "2.0.0",
|
|
||||||
"postcss-selector-parser": "3.1.1",
|
|
||||||
"postcss-styled": "0.31.0",
|
|
||||||
"postcss-syntax": "0.31.0",
|
|
||||||
"postcss-value-parser": "3.3.0",
|
|
||||||
"resolve-from": "4.0.0",
|
|
||||||
"signal-exit": "3.0.2",
|
|
||||||
"specificity": "0.4.0",
|
|
||||||
"string-width": "2.1.1",
|
|
||||||
"style-search": "0.1.0",
|
|
||||||
"sugarss": "1.0.1",
|
|
||||||
"svg-tags": "1.0.0",
|
|
||||||
"table": "4.0.2"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": {
|
"ansi-styles": {
|
||||||
|
@ -14192,21 +14044,12 @@
|
||||||
"integrity": "sha512-t5PpCq5nCNzgPEzhty83UHYLmteY9FTL3COBfRjL0y4BTDB0OADbHVzG/S7gzqvITSsAZiaJPduoDEv2n68JNQ==",
|
"integrity": "sha512-t5PpCq5nCNzgPEzhty83UHYLmteY9FTL3COBfRjL0y4BTDB0OADbHVzG/S7gzqvITSsAZiaJPduoDEv2n68JNQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"browserslist": "^4.0.1",
|
"browserslist": "^4.0.1",
|
||||||
"caniuse-lite": "^1.0.30000865",
|
"caniuse-lite": "^1.0.30000865",
|
||||||
"normalize-range": "^0.1.2",
|
"normalize-range": "^0.1.2",
|
||||||
"num2fraction": "^1.2.2",
|
"num2fraction": "^1.2.2",
|
||||||
"postcss": "^7.0.2",
|
"postcss": "^7.0.2",
|
||||||
"postcss-value-parser": "^3.2.3"
|
"postcss-value-parser": "^3.2.3"
|
||||||
=======
|
|
||||||
"browserslist": "4.0.1",
|
|
||||||
"caniuse-lite": "1.0.30000865",
|
|
||||||
"normalize-range": "0.1.2",
|
|
||||||
"num2fraction": "1.2.2",
|
|
||||||
"postcss": "7.0.2",
|
|
||||||
"postcss-value-parser": "3.3.0"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"braces": {
|
"braces": {
|
||||||
|
@ -14231,17 +14074,6 @@
|
||||||
"node-releases": "^1.0.0-alpha.10"
|
"node-releases": "^1.0.0-alpha.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"browserslist": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-QqiiIWchEIkney3wY53/huI7ZErouNAdvOkjorUALAwRcu3tEwOV3Sh6He0DnP38mz1JjBpCBb50jQBmaYuHPw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"caniuse-lite": "1.0.30000865",
|
|
||||||
"electron-to-chromium": "1.3.52",
|
|
||||||
"node-releases": "1.0.0-alpha.10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"camelcase-keys": {
|
"camelcase-keys": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz",
|
||||||
|
@ -14303,7 +14135,6 @@
|
||||||
"integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==",
|
"integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"array-union": "^1.0.1",
|
"array-union": "^1.0.1",
|
||||||
"dir-glob": "^2.0.0",
|
"dir-glob": "^2.0.0",
|
||||||
"fast-glob": "^2.0.2",
|
"fast-glob": "^2.0.2",
|
||||||
|
@ -14311,15 +14142,6 @@
|
||||||
"ignore": "^3.3.5",
|
"ignore": "^3.3.5",
|
||||||
"pify": "^3.0.0",
|
"pify": "^3.0.0",
|
||||||
"slash": "^1.0.0"
|
"slash": "^1.0.0"
|
||||||
=======
|
|
||||||
"array-union": "1.0.2",
|
|
||||||
"dir-glob": "2.0.0",
|
|
||||||
"fast-glob": "2.2.2",
|
|
||||||
"glob": "7.1.2",
|
|
||||||
"ignore": "3.3.10",
|
|
||||||
"pify": "3.0.0",
|
|
||||||
"slash": "1.0.0"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ignore": {
|
"ignore": {
|
||||||
|
@ -14331,15 +14153,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ignore": {
|
"ignore": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"version": "4.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.3.tgz",
|
|
||||||
"integrity": "sha512-Z/vAH2GGIEATQnBVXMclE2IGV6i0GyVngKThcGZ5kHgHMxLo9Ow2+XHRq1aEKEej5vOF1TPJNbvX6J/anT0M7A==",
|
|
||||||
=======
|
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.2.tgz",
|
||||||
"integrity": "sha512-uoxnT7PYpyEnsja+yX+7v49B7LXxmzDJ2JALqHH3oEGzpM2U1IGcbfnOr8Dt57z3B/UWs7/iAgPFbmye8m4I0g==",
|
"integrity": "sha512-uoxnT7PYpyEnsja+yX+7v49B7LXxmzDJ2JALqHH3oEGzpM2U1IGcbfnOr8Dt57z3B/UWs7/iAgPFbmye8m4I0g==",
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"indent-string": {
|
"indent-string": {
|
||||||
|
@ -14402,7 +14218,6 @@
|
||||||
"integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==",
|
"integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"camelcase-keys": "^4.0.0",
|
"camelcase-keys": "^4.0.0",
|
||||||
"decamelize-keys": "^1.0.0",
|
"decamelize-keys": "^1.0.0",
|
||||||
"loud-rejection": "^1.0.0",
|
"loud-rejection": "^1.0.0",
|
||||||
|
@ -14412,17 +14227,6 @@
|
||||||
"redent": "^2.0.0",
|
"redent": "^2.0.0",
|
||||||
"trim-newlines": "^2.0.0",
|
"trim-newlines": "^2.0.0",
|
||||||
"yargs-parser": "^10.0.0"
|
"yargs-parser": "^10.0.0"
|
||||||
=======
|
|
||||||
"camelcase-keys": "4.2.0",
|
|
||||||
"decamelize-keys": "1.1.0",
|
|
||||||
"loud-rejection": "1.6.0",
|
|
||||||
"minimist-options": "3.0.2",
|
|
||||||
"normalize-package-data": "2.4.0",
|
|
||||||
"read-pkg-up": "3.0.0",
|
|
||||||
"redent": "2.0.0",
|
|
||||||
"trim-newlines": "2.0.0",
|
|
||||||
"yargs-parser": "10.1.0"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"micromatch": {
|
"micromatch": {
|
||||||
|
@ -14476,17 +14280,6 @@
|
||||||
"supports-color": "^5.4.0"
|
"supports-color": "^5.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"postcss": {
|
|
||||||
"version": "7.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.2.tgz",
|
|
||||||
"integrity": "sha512-fmaUY5370keLUTx+CnwRxtGiuFTcNBLQBqr1oE3WZ/euIYmGAo0OAgOhVJ3ByDnVmOR3PK+0V9VebzfjRIUcqw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"chalk": "2.4.1",
|
|
||||||
"source-map": "0.6.1",
|
|
||||||
"supports-color": "5.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"postcss-selector-parser": {
|
"postcss-selector-parser": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz",
|
||||||
|
@ -15104,21 +14897,12 @@
|
||||||
"integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==",
|
"integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"bail": "^1.0.0",
|
"bail": "^1.0.0",
|
||||||
"extend": "^3.0.0",
|
"extend": "^3.0.0",
|
||||||
"is-plain-obj": "^1.1.0",
|
"is-plain-obj": "^1.1.0",
|
||||||
"trough": "^1.0.0",
|
"trough": "^1.0.0",
|
||||||
"vfile": "^2.0.0",
|
"vfile": "^2.0.0",
|
||||||
"x-is-string": "^0.1.0"
|
"x-is-string": "^0.1.0"
|
||||||
=======
|
|
||||||
"bail": "1.0.3",
|
|
||||||
"extend": "3.0.2",
|
|
||||||
"is-plain-obj": "1.1.0",
|
|
||||||
"trough": "1.0.2",
|
|
||||||
"vfile": "2.3.0",
|
|
||||||
"x-is-string": "0.1.0"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"union-value": {
|
"union-value": {
|
||||||
|
@ -15210,11 +14994,7 @@
|
||||||
"integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==",
|
"integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"unist-util-visit": "^1.1.0"
|
"unist-util-visit": "^1.1.0"
|
||||||
=======
|
|
||||||
"unist-util-visit": "1.4.0"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"unist-util-stringify-position": {
|
"unist-util-stringify-position": {
|
||||||
|
@ -15229,11 +15009,7 @@
|
||||||
"integrity": "sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==",
|
"integrity": "sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
<<<<<<< HEAD
|
|
||||||
"unist-util-visit-parents": "^2.0.0"
|
"unist-util-visit-parents": "^2.0.0"
|
||||||
=======
|
|
||||||
"unist-util-visit-parents": "2.0.1"
|
|
||||||
>>>>>>> add fxA ui elements
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"unist-util-visit-parents": {
|
"unist-util-visit-parents": {
|
||||||
|
|
|
@ -117,7 +117,7 @@
|
||||||
"webpack-unassert-loader": "^1.2.0"
|
"webpack-unassert-loader": "^1.2.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"aws-sdk": "^2.285.1",
|
"aws-sdk": "^2.288.0",
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"choo": "^6.12.1",
|
"choo": "^6.12.1",
|
||||||
"cldr-core": "^33.0.0",
|
"cldr-core": "^33.0.0",
|
||||||
|
|
|
@ -122,6 +122,8 @@ reportIPInfringement = Report IP Infringement
|
||||||
javascriptRequired = Firefox Send requires JavaScript
|
javascriptRequired = Firefox Send requires JavaScript
|
||||||
whyJavascript = Why does Firefox Send require JavaScript?
|
whyJavascript = Why does Firefox Send require JavaScript?
|
||||||
enableJavascript = Please enable JavaScript and try again.
|
enableJavascript = Please enable JavaScript and try again.
|
||||||
|
expiresDaysHoursMinutes = { $days }d { $hours }h { $minutes }m
|
||||||
|
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
|
||||||
# A short representation of a countdown timer containing the number of hours and minutes remaining as digits, example "13h 47m"
|
# A short representation of a countdown timer containing the number of hours and minutes remaining as digits, example "13h 47m"
|
||||||
expiresHoursMinutes = { $hours }h { $minutes }m
|
expiresHoursMinutes = { $hours }h { $minutes }m
|
||||||
# A short representation of a countdown timer containing the number of minutes remaining as digits, example "56m"
|
# A short representation of a countdown timer containing the number of minutes remaining as digits, example "56m"
|
||||||
|
|
|
@ -4,10 +4,30 @@ const path = require('path');
|
||||||
const { randomBytes } = require('crypto');
|
const { randomBytes } = require('crypto');
|
||||||
|
|
||||||
const conf = convict({
|
const conf = convict({
|
||||||
s3_bucket: {
|
s3_buckets: {
|
||||||
format: String,
|
format: Array,
|
||||||
default: '',
|
default: [],
|
||||||
env: 'S3_BUCKET'
|
env: 'S3_BUCKETS'
|
||||||
|
},
|
||||||
|
num_of_buckets: {
|
||||||
|
format: Number,
|
||||||
|
default: 3,
|
||||||
|
env: 'NUM_OF_BUCKETS'
|
||||||
|
},
|
||||||
|
expire_times_seconds: {
|
||||||
|
format: Array,
|
||||||
|
default: [86400, 604800, 1209600],
|
||||||
|
env: 'EXPIRE_TIMES_SECONDS'
|
||||||
|
},
|
||||||
|
default_expire_seconds: {
|
||||||
|
format: Number,
|
||||||
|
default: 86400,
|
||||||
|
env: 'DEFAULT_EXPIRE_SECONDS'
|
||||||
|
},
|
||||||
|
max_expire_seconds: {
|
||||||
|
format: Number,
|
||||||
|
default: 1209600,
|
||||||
|
env: 'MAX_EXPIRE_SECONDS'
|
||||||
},
|
},
|
||||||
redis_host: {
|
redis_host: {
|
||||||
format: String,
|
format: String,
|
||||||
|
@ -55,11 +75,6 @@ const conf = convict({
|
||||||
default: 1024 * 1024 * 1024 * 3,
|
default: 1024 * 1024 * 1024 * 3,
|
||||||
env: 'MAX_FILE_SIZE'
|
env: 'MAX_FILE_SIZE'
|
||||||
},
|
},
|
||||||
expire_seconds: {
|
|
||||||
format: Number,
|
|
||||||
default: 86400,
|
|
||||||
env: 'EXPIRE_SECONDS'
|
|
||||||
},
|
|
||||||
l10n_dev: {
|
l10n_dev: {
|
||||||
format: Boolean,
|
format: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
|
|
@ -13,7 +13,8 @@ module.exports = async function(req, res) {
|
||||||
'Content-Length': contentLength,
|
'Content-Length': contentLength,
|
||||||
'WWW-Authenticate': `send-v1 ${req.nonce}`
|
'WWW-Authenticate': `send-v1 ${req.nonce}`
|
||||||
});
|
});
|
||||||
const file_stream = storage.get(id);
|
|
||||||
|
const file_stream = await storage.get(id);
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
|
|
||||||
req.on('close', () => {
|
req.on('close', () => {
|
||||||
|
|
|
@ -35,7 +35,7 @@ if (isIE && !isUnsupportedPage) {
|
||||||
window.location.replace('/unsupported/ie');
|
window.location.replace('/unsupported/ie');
|
||||||
}
|
}
|
||||||
var MAXFILESIZE = ${config.max_file_size};
|
var MAXFILESIZE = ${config.max_file_size};
|
||||||
var EXPIRE_SECONDS = ${config.expire_seconds};
|
var DEFAULT_EXPIRE_SECONDS = ${config.default_expire_seconds};
|
||||||
${ga}
|
${ga}
|
||||||
${sentry}
|
${sentry}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -24,7 +24,9 @@ module.exports = async function(req, res) {
|
||||||
try {
|
try {
|
||||||
const limiter = new Limiter(config.max_file_size);
|
const limiter = new Limiter(config.max_file_size);
|
||||||
const fileStream = req.pipe(limiter);
|
const fileStream = req.pipe(limiter);
|
||||||
await storage.set(newId, fileStream, meta);
|
//this hasn't been updated to expiration time setting yet
|
||||||
|
//if you want to fallback to this code add this
|
||||||
|
await storage.set(newId, fileStream, meta, config.default_expire_seconds);
|
||||||
const protocol = config.env === 'production' ? 'https' : req.protocol;
|
const protocol = config.env === 'production' ? 'https' : req.protocol;
|
||||||
const url = `${protocol}://${req.get('host')}/download/${newId}/`;
|
const url = `${protocol}://${req.get('host')}/download/${newId}/`;
|
||||||
res.set('WWW-Authenticate', `send-v1 ${meta.nonce}`);
|
res.set('WWW-Authenticate', `send-v1 ${meta.nonce}`);
|
||||||
|
|
|
@ -23,10 +23,16 @@ module.exports = async function(ws, req) {
|
||||||
const owner = crypto.randomBytes(10).toString('hex');
|
const owner = crypto.randomBytes(10).toString('hex');
|
||||||
|
|
||||||
const fileInfo = JSON.parse(message);
|
const fileInfo = JSON.parse(message);
|
||||||
|
const timeLimit = fileInfo.timeLimit;
|
||||||
const metadata = fileInfo.fileMetadata;
|
const metadata = fileInfo.fileMetadata;
|
||||||
const auth = fileInfo.authorization;
|
const auth = fileInfo.authorization;
|
||||||
|
|
||||||
if (!metadata || !auth) {
|
if (
|
||||||
|
!metadata ||
|
||||||
|
!auth ||
|
||||||
|
timeLimit <= 0 ||
|
||||||
|
timeLimit > config.max_expire_seconds
|
||||||
|
) {
|
||||||
ws.send(
|
ws.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 400
|
error: 400
|
||||||
|
@ -50,7 +56,7 @@ module.exports = async function(ws, req) {
|
||||||
fileStream = wsStream(ws, { binary: true })
|
fileStream = wsStream(ws, { binary: true })
|
||||||
.pipe(limiter)
|
.pipe(limiter)
|
||||||
.pipe(parser);
|
.pipe(parser);
|
||||||
await storage.set(newId, fileStream, meta);
|
await storage.set(newId, fileStream, meta, timeLimit);
|
||||||
|
|
||||||
if (ws.readyState === 1) {
|
if (ws.readyState === 1) {
|
||||||
// if the socket is closed by a cancelled upload the stream
|
// if the socket is closed by a cancelled upload the stream
|
||||||
|
|
|
@ -6,7 +6,7 @@ const mkdirp = require('mkdirp');
|
||||||
const stat = promisify(fs.stat);
|
const stat = promisify(fs.stat);
|
||||||
|
|
||||||
class FSStorage {
|
class FSStorage {
|
||||||
constructor(config, log) {
|
constructor(config, index, log) {
|
||||||
this.log = log;
|
this.log = log;
|
||||||
this.dir = config.file_dir;
|
this.dir = config.file_dir;
|
||||||
mkdirp.sync(this.dir);
|
mkdirp.sync(this.dir);
|
||||||
|
|
|
@ -5,10 +5,16 @@ const createRedisClient = require('./redis');
|
||||||
|
|
||||||
class DB {
|
class DB {
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
const Storage = config.s3_bucket ? require('./s3') : require('./fs');
|
const Storage =
|
||||||
|
config.s3_buckets.length > 0 ? require('./s3') : require('./fs');
|
||||||
this.log = mozlog('send.storage');
|
this.log = mozlog('send.storage');
|
||||||
this.expireSeconds = config.expire_seconds;
|
|
||||||
this.storage = new Storage(config, this.log);
|
this.storage = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < config.num_of_buckets; i++) {
|
||||||
|
this.storage.push(new Storage(config, i, this.log));
|
||||||
|
}
|
||||||
|
|
||||||
this.redis = createRedisClient(config);
|
this.redis = createRedisClient(config);
|
||||||
this.redis.on('error', err => {
|
this.redis.on('error', err => {
|
||||||
this.log.error('Redis:', err);
|
this.log.error('Redis:', err);
|
||||||
|
@ -20,32 +26,51 @@ class DB {
|
||||||
return Math.ceil(result) * 1000;
|
return Math.ceil(result) * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
length(id) {
|
async getBucket(id) {
|
||||||
return this.storage.length(id);
|
return this.redis.hgetAsync(id, 'bucket');
|
||||||
}
|
}
|
||||||
|
|
||||||
get(id) {
|
async length(id) {
|
||||||
return this.storage.getStream(id);
|
const bucket = await this.redis.hgetAsync(id, 'bucket');
|
||||||
|
return this.storage[bucket].length(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async set(id, file, meta) {
|
async get(id) {
|
||||||
await this.storage.set(id, file);
|
const bucket = await this.redis.hgetAsync(id, 'bucket');
|
||||||
|
return this.storage[bucket].getStream(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async set(id, file, meta, expireSeconds = config.default_expire_seconds) {
|
||||||
|
const bucketTimes = config.expire_times_seconds;
|
||||||
|
let bucket = 0;
|
||||||
|
while (bucket < config.num_of_buckets - 1) {
|
||||||
|
if (expireSeconds <= bucketTimes[bucket]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bucket++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.storage[bucket].set(id, file);
|
||||||
|
this.redis.hset(id, 'bucket', bucket);
|
||||||
this.redis.hmset(id, meta);
|
this.redis.hmset(id, meta);
|
||||||
this.redis.expire(id, this.expireSeconds);
|
this.redis.expire(id, expireSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
setField(id, key, value) {
|
setField(id, key, value) {
|
||||||
this.redis.hset(id, key, value);
|
this.redis.hset(id, key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
del(id) {
|
async del(id) {
|
||||||
|
const bucket = await this.redis.hgetAsync(id, 'bucket');
|
||||||
this.redis.del(id);
|
this.redis.del(id);
|
||||||
return this.storage.del(id);
|
this.storage[bucket].del(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async ping() {
|
async ping() {
|
||||||
await this.redis.pingAsync();
|
await this.redis.pingAsync();
|
||||||
await this.storage.ping();
|
for (const bucket of this.storage) {
|
||||||
|
bucket.ping();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async metadata(id) {
|
async metadata(id) {
|
||||||
|
|
|
@ -2,8 +2,8 @@ const AWS = require('aws-sdk');
|
||||||
const s3 = new AWS.S3();
|
const s3 = new AWS.S3();
|
||||||
|
|
||||||
class S3Storage {
|
class S3Storage {
|
||||||
constructor(config, log) {
|
constructor(config, index, log) {
|
||||||
this.bucket = config.s3_bucket;
|
this.bucket = config.s3_buckets[index];
|
||||||
this.log = log;
|
this.log = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ const S3Storage = proxyquire('../../server/storage/s3', {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('S3Storage', function() {
|
describe('S3Storage', function() {
|
||||||
it('uses config.s3_bucket', function() {
|
it('uses config.s3_buckets', function() {
|
||||||
const s = new S3Storage({ s3_bucket: 'foo' });
|
const s = new S3Storage({ s3_buckets: ['foo', 'bar', 'baz'] }, 0);
|
||||||
assert.equal(s.bucket, 'foo');
|
assert.equal(s.bucket, 'foo');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ describe('S3Storage', function() {
|
||||||
s3Stub.headObject = sinon
|
s3Stub.headObject = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.returns(resolvedPromise({ ContentLength: 123 }));
|
.returns(resolvedPromise({ ContentLength: 123 }));
|
||||||
const s = new S3Storage({ s3_bucket: 'foo' });
|
const s = new S3Storage({ s3_buckets: ['foo', 'bar', 'baz'] }, 0);
|
||||||
const len = await s.length('x');
|
const len = await s.length('x');
|
||||||
assert.equal(len, 123);
|
assert.equal(len, 123);
|
||||||
sinon.assert.calledWithMatch(s3Stub.headObject, {
|
sinon.assert.calledWithMatch(s3Stub.headObject, {
|
||||||
|
@ -54,7 +54,7 @@ describe('S3Storage', function() {
|
||||||
it('throws when id not found', async function() {
|
it('throws when id not found', async function() {
|
||||||
const err = new Error();
|
const err = new Error();
|
||||||
s3Stub.headObject = sinon.stub().returns(rejectedPromise(err));
|
s3Stub.headObject = sinon.stub().returns(rejectedPromise(err));
|
||||||
const s = new S3Storage({ s3_bucket: 'foo' });
|
const s = new S3Storage({ s3_buckets: ['foo', 'bar', 'baz'] }, 0);
|
||||||
try {
|
try {
|
||||||
await s.length('x');
|
await s.length('x');
|
||||||
assert.fail();
|
assert.fail();
|
||||||
|
@ -70,7 +70,7 @@ describe('S3Storage', function() {
|
||||||
s3Stub.getObject = sinon
|
s3Stub.getObject = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.returns({ createReadStream: () => stream });
|
.returns({ createReadStream: () => stream });
|
||||||
const s = new S3Storage({ s3_bucket: 'foo' });
|
const s = new S3Storage({ s3_buckets: ['foo', 'bar', 'baz'] }, 0);
|
||||||
const result = s.getStream('x');
|
const result = s.getStream('x');
|
||||||
assert.equal(result, stream);
|
assert.equal(result, stream);
|
||||||
sinon.assert.calledWithMatch(s3Stub.getObject, {
|
sinon.assert.calledWithMatch(s3Stub.getObject, {
|
||||||
|
@ -84,7 +84,7 @@ describe('S3Storage', function() {
|
||||||
it('calls s3.upload', async function() {
|
it('calls s3.upload', async function() {
|
||||||
const file = { on: sinon.stub() };
|
const file = { on: sinon.stub() };
|
||||||
s3Stub.upload = sinon.stub().returns(resolvedPromise());
|
s3Stub.upload = sinon.stub().returns(resolvedPromise());
|
||||||
const s = new S3Storage({ s3_bucket: 'foo' });
|
const s = new S3Storage({ s3_buckets: ['foo', 'bar', 'baz'] }, 0);
|
||||||
await s.set('x', file);
|
await s.set('x', file);
|
||||||
sinon.assert.calledWithMatch(s3Stub.upload, {
|
sinon.assert.calledWithMatch(s3Stub.upload, {
|
||||||
Bucket: 'foo',
|
Bucket: 'foo',
|
||||||
|
@ -103,7 +103,7 @@ describe('S3Storage', function() {
|
||||||
promise: () => Promise.reject(err),
|
promise: () => Promise.reject(err),
|
||||||
abort
|
abort
|
||||||
});
|
});
|
||||||
const s = new S3Storage({ s3_bucket: 'foo' });
|
const s = new S3Storage({ s3_buckets: ['foo', 'bar', 'baz'] }, 0);
|
||||||
try {
|
try {
|
||||||
await s.set('x', file);
|
await s.set('x', file);
|
||||||
assert.fail();
|
assert.fail();
|
||||||
|
@ -119,7 +119,7 @@ describe('S3Storage', function() {
|
||||||
};
|
};
|
||||||
const err = new Error();
|
const err = new Error();
|
||||||
s3Stub.upload = sinon.stub().returns(rejectedPromise(err));
|
s3Stub.upload = sinon.stub().returns(rejectedPromise(err));
|
||||||
const s = new S3Storage({ s3_bucket: 'foo' });
|
const s = new S3Storage({ s3_buckets: ['foo', 'bar', 'baz'] }, 0);
|
||||||
try {
|
try {
|
||||||
await s.set('x', file);
|
await s.set('x', file);
|
||||||
assert.fail();
|
assert.fail();
|
||||||
|
@ -132,7 +132,7 @@ describe('S3Storage', function() {
|
||||||
describe('del', function() {
|
describe('del', function() {
|
||||||
it('calls s3.deleteObject', async function() {
|
it('calls s3.deleteObject', async function() {
|
||||||
s3Stub.deleteObject = sinon.stub().returns(resolvedPromise(true));
|
s3Stub.deleteObject = sinon.stub().returns(resolvedPromise(true));
|
||||||
const s = new S3Storage({ s3_bucket: 'foo' });
|
const s = new S3Storage({ s3_buckets: ['foo', 'bar', 'baz'] }, 0);
|
||||||
const result = await s.del('x');
|
const result = await s.del('x');
|
||||||
assert.equal(result, true);
|
assert.equal(result, true);
|
||||||
sinon.assert.calledWithMatch(s3Stub.deleteObject, {
|
sinon.assert.calledWithMatch(s3Stub.deleteObject, {
|
||||||
|
@ -145,7 +145,7 @@ describe('S3Storage', function() {
|
||||||
describe('ping', function() {
|
describe('ping', function() {
|
||||||
it('calls s3.headBucket', async function() {
|
it('calls s3.headBucket', async function() {
|
||||||
s3Stub.headBucket = sinon.stub().returns(resolvedPromise(true));
|
s3Stub.headBucket = sinon.stub().returns(resolvedPromise(true));
|
||||||
const s = new S3Storage({ s3_bucket: 'foo' });
|
const s = new S3Storage({ s3_buckets: ['foo', 'bar', 'baz'] }, 0);
|
||||||
const result = await s.ping();
|
const result = await s.ping();
|
||||||
assert.equal(result, true);
|
assert.equal(result, true);
|
||||||
sinon.assert.calledWithMatch(s3Stub.headBucket, { Bucket: 'foo' });
|
sinon.assert.calledWithMatch(s3Stub.headBucket, { Bucket: 'foo' });
|
||||||
|
|
|
@ -20,14 +20,17 @@ class MockStorage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const expire_seconds = 10;
|
const config = {
|
||||||
|
default_expire_seconds: 10,
|
||||||
|
num_of_buckets: 3,
|
||||||
|
expire_times_seconds: [86400, 604800, 1209600],
|
||||||
|
s3_buckets: ['foo', 'bar', 'baz'],
|
||||||
|
env: 'development',
|
||||||
|
redis_host: 'localhost'
|
||||||
|
};
|
||||||
|
|
||||||
const storage = proxyquire('../../server/storage', {
|
const storage = proxyquire('../../server/storage', {
|
||||||
'../config': {
|
'../config': config,
|
||||||
expire_seconds,
|
|
||||||
s3_bucket: 'foo',
|
|
||||||
env: 'development',
|
|
||||||
redis_host: 'localhost'
|
|
||||||
},
|
|
||||||
'../log': () => {},
|
'../log': () => {},
|
||||||
'./s3': MockStorage
|
'./s3': MockStorage
|
||||||
});
|
});
|
||||||
|
@ -35,39 +38,58 @@ const storage = proxyquire('../../server/storage', {
|
||||||
describe('Storage', function() {
|
describe('Storage', function() {
|
||||||
describe('ttl', function() {
|
describe('ttl', function() {
|
||||||
it('returns milliseconds remaining', async function() {
|
it('returns milliseconds remaining', async function() {
|
||||||
await storage.set('x', null, { foo: 'bar' });
|
const time = 40;
|
||||||
|
await storage.set('x', null, { foo: 'bar' }, time);
|
||||||
const ms = await storage.ttl('x');
|
const ms = await storage.ttl('x');
|
||||||
await storage.del('x');
|
await storage.del('x');
|
||||||
assert.equal(ms, expire_seconds * 1000);
|
assert.equal(ms, time * 1000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('length', function() {
|
describe('length', function() {
|
||||||
it('returns the file size', async function() {
|
it('returns the file size', async function() {
|
||||||
|
await storage.set('x', null);
|
||||||
const len = await storage.length('x');
|
const len = await storage.length('x');
|
||||||
assert.equal(len, 12);
|
assert.equal(len, 12);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('get', function() {
|
describe('get', function() {
|
||||||
it('returns a stream', function() {
|
it('returns a stream', async function() {
|
||||||
const s = storage.get('x');
|
await storage.set('x', null);
|
||||||
|
const s = await storage.get('x');
|
||||||
assert.equal(s, stream);
|
assert.equal(s, stream);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('set', function() {
|
describe('set', function() {
|
||||||
it('sets expiration to config.expire_seconds', async function() {
|
it('sets expiration to expire time', async function() {
|
||||||
await storage.set('x', null, { foo: 'bar' });
|
const seconds = 100;
|
||||||
|
await storage.set('x', null, { foo: 'bar' }, seconds);
|
||||||
const s = await storage.redis.ttlAsync('x');
|
const s = await storage.redis.ttlAsync('x');
|
||||||
await storage.del('x');
|
await storage.del('x');
|
||||||
assert.equal(Math.ceil(s), expire_seconds);
|
assert.equal(Math.ceil(s), seconds);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('puts into right bucket based on expire time', async function() {
|
||||||
|
for (let i = 0; i < config.num_of_buckets; i++) {
|
||||||
|
await storage.set(
|
||||||
|
'x',
|
||||||
|
null,
|
||||||
|
{ foo: 'bar' },
|
||||||
|
config.expire_times_seconds[i]
|
||||||
|
);
|
||||||
|
const bucket = await storage.getBucket('x');
|
||||||
|
assert.equal(bucket, i);
|
||||||
|
await storage.del('x');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets metadata', async function() {
|
it('sets metadata', async function() {
|
||||||
const m = { foo: 'bar' };
|
const m = { foo: 'bar' };
|
||||||
await storage.set('x', null, m);
|
await storage.set('x', null, m);
|
||||||
const meta = await storage.redis.hgetallAsync('x');
|
const meta = await storage.redis.hgetallAsync('x');
|
||||||
|
delete meta.bucket;
|
||||||
await storage.del('x');
|
await storage.del('x');
|
||||||
assert.deepEqual(meta, m);
|
assert.deepEqual(meta, m);
|
||||||
});
|
});
|
||||||
|
@ -77,6 +99,7 @@ describe('Storage', function() {
|
||||||
|
|
||||||
describe('setField', function() {
|
describe('setField', function() {
|
||||||
it('works', async function() {
|
it('works', async function() {
|
||||||
|
await storage.set('x', null);
|
||||||
storage.setField('x', 'y', 'z');
|
storage.setField('x', 'y', 'z');
|
||||||
const z = await storage.redis.hgetAsync('x', 'y');
|
const z = await storage.redis.hgetAsync('x', 'y');
|
||||||
assert.equal(z, 'z');
|
assert.equal(z, 'z');
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* global DEFAULT_EXPIRE_SECONDS */
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import Archive from '../../../app/archive';
|
import Archive from '../../../app/archive';
|
||||||
import * as api from '../../../app/api';
|
import * as api from '../../../app/api';
|
||||||
|
@ -18,7 +19,13 @@ describe('API', function() {
|
||||||
const meta = await keychain.encryptMetadata(metadata);
|
const meta = await keychain.encryptMetadata(metadata);
|
||||||
const verifierB64 = await keychain.authKeyB64();
|
const verifierB64 = await keychain.authKeyB64();
|
||||||
const p = function() {};
|
const p = function() {};
|
||||||
const up = api.uploadWs(enc, meta, verifierB64, p);
|
const up = api.uploadWs(
|
||||||
|
enc,
|
||||||
|
meta,
|
||||||
|
verifierB64,
|
||||||
|
p,
|
||||||
|
DEFAULT_EXPIRE_SECONDS
|
||||||
|
);
|
||||||
|
|
||||||
const result = await up.result;
|
const result = await up.result;
|
||||||
assert.ok(result.url);
|
assert.ok(result.url);
|
||||||
|
@ -32,7 +39,14 @@ describe('API', function() {
|
||||||
const meta = await keychain.encryptMetadata(metadata);
|
const meta = await keychain.encryptMetadata(metadata);
|
||||||
const verifierB64 = await keychain.authKeyB64();
|
const verifierB64 = await keychain.authKeyB64();
|
||||||
const p = function() {};
|
const p = function() {};
|
||||||
const up = api.uploadWs(enc, meta, verifierB64, p);
|
const up = api.uploadWs(
|
||||||
|
enc,
|
||||||
|
meta,
|
||||||
|
verifierB64,
|
||||||
|
p,
|
||||||
|
DEFAULT_EXPIRE_SECONDS
|
||||||
|
);
|
||||||
|
|
||||||
up.cancel();
|
up.cancel();
|
||||||
try {
|
try {
|
||||||
await up.result;
|
await up.result;
|
||||||
|
|
Loading…
Reference in New Issue