Merge branch 'time' into vnext
This commit is contained in:
commit
37c2926252
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 port = window.location.port;
|
||||
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 fileMeta = {
|
||||
fileMetadata: metadataHeader,
|
||||
authorization: `send-v1 ${verifierB64}`
|
||||
authorization: `send-v1 ${verifierB64}`,
|
||||
timeLimit
|
||||
};
|
||||
|
||||
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 };
|
||||
|
||||
return {
|
||||
|
@ -196,7 +210,15 @@ export function uploadWs(encrypted, metadata, verifierB64, onprogress) {
|
|||
canceller.error = new Error(0);
|
||||
canceller.cancelled = true;
|
||||
},
|
||||
result: upload(encrypted, metadata, verifierB64, onprogress, canceller)
|
||||
|
||||
result: upload(
|
||||
encrypted,
|
||||
metadata,
|
||||
verifierB64,
|
||||
timeLimit,
|
||||
onprogress,
|
||||
canceller
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -293,3 +293,9 @@ a {
|
|||
margin: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-device-width: 700px), (max-width: 700px) {
|
||||
.stripedBox {
|
||||
margin-top: 72px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* global MAXFILESIZE */
|
||||
/* global DEFAULT_EXPIRE_SECONDS */
|
||||
import FileSender from './fileSender';
|
||||
import FileReceiver from './fileReceiver';
|
||||
import { copyToClipboard, delay, openLinksInNewTab, percent } from './utils';
|
||||
|
@ -110,7 +111,9 @@ export default function(state, emitter) {
|
|||
emitter.on('upload', async ({ type, dlCount, password }) => {
|
||||
if (!state.archive) return;
|
||||
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('encrypting', render);
|
||||
sender.on('complete', render);
|
||||
|
@ -157,7 +160,7 @@ export default function(state, emitter) {
|
|||
}
|
||||
} finally {
|
||||
openLinksInNewTab(links, false);
|
||||
state.files = [];
|
||||
state.archive = null;
|
||||
state.password = '';
|
||||
state.uploading = false;
|
||||
state.transfer = null;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global EXPIRE_SECONDS */
|
||||
/* global DEFAULT_EXPIRE_SECONDS */
|
||||
import Nanobus from 'nanobus';
|
||||
import OwnedFile from './ownedFile';
|
||||
import Keychain from './keychain';
|
||||
|
@ -7,8 +7,9 @@ import { uploadWs } from './api';
|
|||
import { encryptedSize } from './ece';
|
||||
|
||||
export default class FileSender extends Nanobus {
|
||||
constructor(file) {
|
||||
constructor(file, timeLimit) {
|
||||
super('FileSender');
|
||||
this.timeLimit = timeLimit || DEFAULT_EXPIRE_SECONDS;
|
||||
this.file = file;
|
||||
this.keychain = new Keychain();
|
||||
this.reset();
|
||||
|
@ -70,10 +71,16 @@ export default class FileSender extends Nanobus {
|
|||
const metadata = await this.keychain.encryptMetadata(this.file);
|
||||
const authKeyB64 = await this.keychain.authKeyB64();
|
||||
|
||||
this.uploadRequest = uploadWs(encStream, metadata, authKeyB64, p => {
|
||||
this.progress = [p, totalSize];
|
||||
this.emit('progress');
|
||||
});
|
||||
this.uploadRequest = uploadWs(
|
||||
encStream,
|
||||
metadata,
|
||||
authKeyB64,
|
||||
p => {
|
||||
this.progress = [p, totalSize];
|
||||
this.emit('progress');
|
||||
},
|
||||
this.timeLimit
|
||||
);
|
||||
|
||||
if (this.cancelled) {
|
||||
throw new Error(0);
|
||||
|
@ -97,10 +104,11 @@ export default class FileSender extends Nanobus {
|
|||
time: time,
|
||||
speed: this.file.size / (time / 1000),
|
||||
createdAt: Date.now(),
|
||||
expiresAt: Date.now() + EXPIRE_SECONDS * 1000,
|
||||
expiresAt: Date.now() + this.timeLimit * 1000,
|
||||
secretKey: secretKey,
|
||||
nonce: this.keychain.nonce,
|
||||
ownerToken: result.ownerToken
|
||||
ownerToken: result.ownerToken,
|
||||
timeLimit: this.timeLimit
|
||||
});
|
||||
|
||||
return ownedFile;
|
||||
|
|
|
@ -19,6 +19,7 @@ export default class OwnedFile {
|
|||
this.dtotal = obj.dtotal || 0;
|
||||
this.keychain = new Keychain(obj.secretKey, obj.nonce);
|
||||
this._hasPassword = !!obj.hasPassword;
|
||||
this.timeLimit = obj.timeLimit;
|
||||
}
|
||||
|
||||
async setPassword(password) {
|
||||
|
@ -80,7 +81,8 @@ export default class OwnedFile {
|
|||
ownerToken: this.ownerToken,
|
||||
dlimit: this.dlimit,
|
||||
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 raw = require('choo/html/raw');
|
||||
const assets = require('../../../common/assets');
|
||||
const notFound = require('../notFound');
|
||||
const deletePopup = require('../../templates/popup');
|
||||
const uploadedFileList = require('../../templates/uploadedFileList');
|
||||
const timeLimitText = require('../../templates/timeLimitText');
|
||||
const { allowedCopy, delay, fadeOut } = require('../../utils');
|
||||
|
||||
module.exports = function(state, emit) {
|
||||
|
@ -18,7 +18,6 @@ module.exports = function(state, emit) {
|
|||
: 'passwordReminder--hidden';
|
||||
|
||||
return html`
|
||||
|
||||
<div class="page effect--fadeIn" id="shareWrapper">
|
||||
<a href="/" class="goBackButton">
|
||||
<img src="${assets.get('back-arrow.svg')}"/>
|
||||
|
@ -98,13 +97,14 @@ module.exports = function(state, emit) {
|
|||
};
|
||||
|
||||
function expireInfo(file, translate) {
|
||||
const hours = Math.floor(EXPIRE_SECONDS / 60 / 60);
|
||||
const el = html`<div class="shareTitle">${raw(
|
||||
translate('expireInfo', {
|
||||
downloadCount: translate('downloadCount', { num: file.dlimit }),
|
||||
timespan: translate('timespanHours', { num: hours })
|
||||
})
|
||||
)}</div>`;
|
||||
const el = html`<div class="shareTitle">
|
||||
${raw(
|
||||
translate('expireInfo', {
|
||||
downloadCount: translate('downloadCount', { num: file.dlimit }),
|
||||
timespan: timeLimitText(translate, file.timeLimit)
|
||||
})
|
||||
)}
|
||||
</div>`;
|
||||
|
||||
return el;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ module.exports = function(state, emit) {
|
|||
${title(state)}
|
||||
|
||||
<label class="uploadArea"
|
||||
|
||||
ondragover=${dragover}
|
||||
ondragleave=${dragleave}>
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
const html = require('choo/html');
|
||||
const raw = require('choo/html/raw');
|
||||
const selectbox = require('../selectbox');
|
||||
const timeLimitText = require('../timeLimitText');
|
||||
|
||||
module.exports = function(state) {
|
||||
const el = html`<div> ${raw(
|
||||
state.translate('frontPageExpireInfo', {
|
||||
downloadCount: '<select id=dlCount></select>',
|
||||
timespan: state.translate('timespanHours', { num: 24 }) //'<select id=timespan></select>'
|
||||
timespan: '<select id=timespan></select>'
|
||||
})
|
||||
)}
|
||||
</div>`;
|
||||
|
@ -24,13 +25,18 @@ module.exports = function(state) {
|
|||
dlCountSelect
|
||||
);
|
||||
|
||||
/*
|
||||
const timeSelect = el.querySelector('#timespan');
|
||||
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
|
||||
);
|
||||
*/
|
||||
|
||||
return el;
|
||||
};
|
||||
|
|
|
@ -51,6 +51,14 @@ module.exports = function(file, state) {
|
|||
function timeLeft(milliseconds, state) {
|
||||
const minutes = Math.floor(milliseconds / 1000 / 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) {
|
||||
return state.translate('expiresHoursMinutes', {
|
||||
hours,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
width: 22px;
|
||||
height: 32px;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.fileIcon__lock {
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media (max-device-width: 750px), (max-width: 750px) {
|
||||
@media (max-device-width: 700px), (max-width: 700px) {
|
||||
.signupPromo {
|
||||
flex-direction: row;
|
||||
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;
|
||||
};
|
|
@ -926,9 +926,9 @@
|
|||
}
|
||||
},
|
||||
"aws-sdk": {
|
||||
"version": "2.285.1",
|
||||
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.285.1.tgz",
|
||||
"integrity": "sha512-lkroCYcnb7UWR/jbaW6wyjAeGROrsBFWyqUukQjICuCV4a0Mapnjsxefl2A/z+0SX3gnBN7owUb/60UjQSHpzA==",
|
||||
"version": "2.288.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.288.0.tgz",
|
||||
"integrity": "sha512-kV0yLAP3DPfUpDfFOCvOn4s/69XqVH7D53Vnfgf6mgKO5bp1HVFpWfTJ/OZeiwRy7hfIi0xTiSEmPXaMG0ACkg==",
|
||||
"requires": {
|
||||
"buffer": "4.9.1",
|
||||
"events": "1.1.1",
|
||||
|
|
|
@ -117,7 +117,7 @@
|
|||
"webpack-unassert-loader": "^1.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"aws-sdk": "^2.285.1",
|
||||
"aws-sdk": "^2.288.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"choo": "^6.12.1",
|
||||
"cldr-core": "^33.0.0",
|
||||
|
|
|
@ -122,6 +122,8 @@ reportIPInfringement = Report IP Infringement
|
|||
javascriptRequired = Firefox Send requires JavaScript
|
||||
whyJavascript = Why does Firefox Send require JavaScript?
|
||||
enableJavascript = Please enable JavaScript and try again.
|
||||
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
|
||||
expiresDaysHoursMinutes = { $days }d { $hours }h { $minutes }m
|
||||
# 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
|
||||
# A short representation of a countdown timer containing the number of minutes remaining as digits, example "56m"
|
||||
|
|
|
@ -9,6 +9,31 @@ const conf = convict({
|
|||
default: '',
|
||||
env: 'S3_BUCKET'
|
||||
},
|
||||
num_of_prefixes: {
|
||||
format: Number,
|
||||
default: 5,
|
||||
env: 'NUM_OF_PREFIXES'
|
||||
},
|
||||
expire_prefixes: {
|
||||
format: Array,
|
||||
default: ['5minutes', '1hour', '1day', '1week', '2weeks'],
|
||||
env: 'EXPIRE_PREFIXES'
|
||||
},
|
||||
expire_times_seconds: {
|
||||
format: Array,
|
||||
default: [300, 3600, 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: {
|
||||
format: String,
|
||||
default: 'localhost',
|
||||
|
@ -55,11 +80,6 @@ const conf = convict({
|
|||
default: 1024 * 1024 * 1024 * 3,
|
||||
env: 'MAX_FILE_SIZE'
|
||||
},
|
||||
expire_seconds: {
|
||||
format: Number,
|
||||
default: 86400,
|
||||
env: 'EXPIRE_SECONDS'
|
||||
},
|
||||
l10n_dev: {
|
||||
format: Boolean,
|
||||
default: false,
|
||||
|
|
|
@ -13,7 +13,8 @@ module.exports = async function(req, res) {
|
|||
'Content-Length': contentLength,
|
||||
'WWW-Authenticate': `send-v1 ${req.nonce}`
|
||||
});
|
||||
const file_stream = storage.get(id);
|
||||
|
||||
const file_stream = await storage.get(id);
|
||||
let cancelled = false;
|
||||
|
||||
req.on('close', () => {
|
||||
|
|
|
@ -35,7 +35,7 @@ if (isIE && !isUnsupportedPage) {
|
|||
window.location.replace('/unsupported/ie');
|
||||
}
|
||||
var MAXFILESIZE = ${config.max_file_size};
|
||||
var EXPIRE_SECONDS = ${config.expire_seconds};
|
||||
var DEFAULT_EXPIRE_SECONDS = ${config.default_expire_seconds};
|
||||
${ga}
|
||||
${sentry}
|
||||
`;
|
||||
|
|
|
@ -24,7 +24,9 @@ module.exports = async function(req, res) {
|
|||
try {
|
||||
const limiter = new Limiter(config.max_file_size);
|
||||
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 url = `${protocol}://${req.get('host')}/download/${newId}/`;
|
||||
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 fileInfo = JSON.parse(message);
|
||||
const timeLimit = fileInfo.timeLimit;
|
||||
const metadata = fileInfo.fileMetadata;
|
||||
const auth = fileInfo.authorization;
|
||||
|
||||
if (!metadata || !auth) {
|
||||
if (
|
||||
!metadata ||
|
||||
!auth ||
|
||||
timeLimit <= 0 ||
|
||||
timeLimit > config.max_expire_seconds
|
||||
) {
|
||||
ws.send(
|
||||
JSON.stringify({
|
||||
error: 400
|
||||
|
@ -50,7 +56,7 @@ module.exports = async function(ws, req) {
|
|||
fileStream = wsStream(ws, { binary: true })
|
||||
.pipe(limiter)
|
||||
.pipe(parser);
|
||||
await storage.set(newId, fileStream, meta);
|
||||
await storage.set(newId, fileStream, meta, timeLimit);
|
||||
|
||||
if (ws.readyState === 1) {
|
||||
// if the socket is closed by a cancelled upload the stream
|
||||
|
|
|
@ -7,8 +7,9 @@ class DB {
|
|||
constructor(config) {
|
||||
const Storage = config.s3_bucket ? require('./s3') : require('./fs');
|
||||
this.log = mozlog('send.storage');
|
||||
this.expireSeconds = config.expire_seconds;
|
||||
|
||||
this.storage = new Storage(config, this.log);
|
||||
|
||||
this.redis = createRedisClient(config);
|
||||
this.redis.on('error', err => {
|
||||
this.log.error('Redis:', err);
|
||||
|
@ -20,27 +21,45 @@ class DB {
|
|||
return Math.ceil(result) * 1000;
|
||||
}
|
||||
|
||||
length(id) {
|
||||
return this.storage.length(id);
|
||||
async getPrefixedId(id) {
|
||||
const prefix = await this.redis.hgetAsync(id, 'prefix');
|
||||
return `${prefix}-${id}`;
|
||||
}
|
||||
|
||||
get(id) {
|
||||
return this.storage.getStream(id);
|
||||
async length(id) {
|
||||
const filePath = await this.getPrefixedId(id);
|
||||
return this.storage.length(filePath);
|
||||
}
|
||||
|
||||
async set(id, file, meta) {
|
||||
await this.storage.set(id, file);
|
||||
async get(id) {
|
||||
const filePath = await this.getPrefixedId(id);
|
||||
return this.storage.getStream(filePath);
|
||||
}
|
||||
|
||||
async set(id, file, meta, expireSeconds = config.default_expire_seconds) {
|
||||
const expireTimes = config.expire_times_seconds;
|
||||
let i;
|
||||
for (i = 0; i < expireTimes.length - 1; i++) {
|
||||
if (expireSeconds <= expireTimes[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
const prefix = config.expire_prefixes[i];
|
||||
const filePath = `${prefix}-${id}`;
|
||||
await this.storage.set(filePath, file);
|
||||
this.redis.hset(id, 'prefix', prefix);
|
||||
this.redis.hmset(id, meta);
|
||||
this.redis.expire(id, this.expireSeconds);
|
||||
this.redis.expire(id, expireSeconds);
|
||||
}
|
||||
|
||||
setField(id, key, value) {
|
||||
this.redis.hset(id, key, value);
|
||||
}
|
||||
|
||||
del(id) {
|
||||
async del(id) {
|
||||
const filePath = await this.getPrefixedId(id);
|
||||
this.storage.del(filePath);
|
||||
this.redis.del(id);
|
||||
return this.storage.del(id);
|
||||
}
|
||||
|
||||
async ping() {
|
||||
|
|
|
@ -20,14 +20,18 @@ class MockStorage {
|
|||
}
|
||||
}
|
||||
|
||||
const expire_seconds = 10;
|
||||
const config = {
|
||||
s3_bucket: 'foo',
|
||||
default_expire_seconds: 20,
|
||||
num_of_prefixes: 3,
|
||||
expire_prefixes: ['ten', 'twenty', 'thirty'],
|
||||
expire_times_seconds: [10, 20, 30],
|
||||
env: 'development',
|
||||
redis_host: 'localhost'
|
||||
};
|
||||
|
||||
const storage = proxyquire('../../server/storage', {
|
||||
'../config': {
|
||||
expire_seconds,
|
||||
s3_bucket: 'foo',
|
||||
env: 'development',
|
||||
redis_host: 'localhost'
|
||||
},
|
||||
'../config': config,
|
||||
'../log': () => {},
|
||||
'./s3': MockStorage
|
||||
});
|
||||
|
@ -35,10 +39,11 @@ const storage = proxyquire('../../server/storage', {
|
|||
describe('Storage', function() {
|
||||
describe('ttl', 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');
|
||||
await storage.del('x');
|
||||
assert.equal(ms, expire_seconds * 1000);
|
||||
assert.equal(ms, time * 1000);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -50,33 +55,51 @@ describe('Storage', function() {
|
|||
});
|
||||
|
||||
describe('get', function() {
|
||||
it('returns a stream', function() {
|
||||
const s = storage.get('x');
|
||||
it('returns a stream', async function() {
|
||||
const s = await storage.get('x');
|
||||
assert.equal(s, stream);
|
||||
});
|
||||
});
|
||||
|
||||
describe('set', function() {
|
||||
it('sets expiration to config.expire_seconds', async function() {
|
||||
await storage.set('x', null, { foo: 'bar' });
|
||||
it('sets expiration to expire time', async function() {
|
||||
const seconds = 100;
|
||||
await storage.set('x', null, { foo: 'bar' }, seconds);
|
||||
const s = await storage.redis.ttlAsync('x');
|
||||
await storage.del('x');
|
||||
assert.equal(Math.ceil(s), expire_seconds);
|
||||
assert.equal(Math.ceil(s), seconds);
|
||||
});
|
||||
|
||||
it('adds right prefix based on expire time', async function() {
|
||||
await storage.set('x', null, { foo: 'bar' }, 10);
|
||||
const path_x = await storage.getPrefixedId('x');
|
||||
assert.equal(path_x, 'ten-x');
|
||||
await storage.del('x');
|
||||
|
||||
await storage.set('y', null, { foo: 'bar' }, 11);
|
||||
const path_y = await storage.getPrefixedId('y');
|
||||
assert.equal(path_y, 'twenty-y');
|
||||
await storage.del('y');
|
||||
|
||||
await storage.set('z', null, { foo: 'bar' }, 33);
|
||||
const path_z = await storage.getPrefixedId('z');
|
||||
assert.equal(path_z, 'thirty-z');
|
||||
await storage.del('z');
|
||||
});
|
||||
|
||||
it('sets metadata', async function() {
|
||||
const m = { foo: 'bar' };
|
||||
await storage.set('x', null, m);
|
||||
const meta = await storage.redis.hgetallAsync('x');
|
||||
delete meta.prefix;
|
||||
await storage.del('x');
|
||||
assert.deepEqual(meta, m);
|
||||
});
|
||||
|
||||
//it('throws when storage fails');
|
||||
});
|
||||
|
||||
describe('setField', function() {
|
||||
it('works', async function() {
|
||||
await storage.set('x', null);
|
||||
storage.setField('x', 'y', 'z');
|
||||
const z = await storage.redis.hgetAsync('x', 'y');
|
||||
assert.equal(z, 'z');
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* global DEFAULT_EXPIRE_SECONDS */
|
||||
import assert from 'assert';
|
||||
import Archive from '../../../app/archive';
|
||||
import * as api from '../../../app/api';
|
||||
|
@ -18,7 +19,13 @@ describe('API', function() {
|
|||
const meta = await keychain.encryptMetadata(metadata);
|
||||
const verifierB64 = await keychain.authKeyB64();
|
||||
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;
|
||||
assert.ok(result.url);
|
||||
|
@ -32,7 +39,14 @@ describe('API', function() {
|
|||
const meta = await keychain.encryptMetadata(metadata);
|
||||
const verifierB64 = await keychain.authKeyB64();
|
||||
const p = function() {};
|
||||
const up = api.uploadWs(enc, meta, verifierB64, p);
|
||||
const up = api.uploadWs(
|
||||
enc,
|
||||
meta,
|
||||
verifierB64,
|
||||
p,
|
||||
DEFAULT_EXPIRE_SECONDS
|
||||
);
|
||||
|
||||
up.cancel();
|
||||
try {
|
||||
await up.result;
|
||||
|
|
Loading…
Reference in New Issue