mirror of
https://gitlab.com/timvisee/send.git
synced 2024-11-12 14:12:30 +01:00
added /config endpoint, use fewer globals (#1172)
* added /config endpoint, use fewer globals * fixed integration tests
This commit is contained in:
parent
8df400a676
commit
1c44d1d0f9
@ -1,29 +1,9 @@
|
|||||||
/* global window, navigator */
|
/* global window, navigator */
|
||||||
|
|
||||||
window.LIMITS = {
|
|
||||||
ANON: {
|
|
||||||
MAX_FILE_SIZE: 1024 * 1024 * 1024 * 2,
|
|
||||||
MAX_DOWNLOADS: 20,
|
|
||||||
MAX_EXPIRE_SECONDS: 86400
|
|
||||||
},
|
|
||||||
MAX_FILE_SIZE: 1024 * 1024 * 1024 * 2,
|
|
||||||
MAX_DOWNLOADS: 200,
|
|
||||||
MAX_EXPIRE_SECONDS: 604800,
|
|
||||||
MAX_FILES_PER_ARCHIVE: 64,
|
|
||||||
MAX_ARCHIVES_PER_USER: 16
|
|
||||||
};
|
|
||||||
|
|
||||||
window.DEFAULTS = {
|
|
||||||
DOWNLOAD_COUNTS: [1, 2, 3, 4, 5, 20, 50, 100, 200],
|
|
||||||
EXPIRE_TIMES_SECONDS: [300, 3600, 86400, 604800],
|
|
||||||
EXPIRE_SECONDS: 3600
|
|
||||||
};
|
|
||||||
|
|
||||||
import choo from 'choo';
|
import choo from 'choo';
|
||||||
import html from 'choo/html';
|
import html from 'choo/html';
|
||||||
import Raven from 'raven-js';
|
import Raven from 'raven-js';
|
||||||
|
|
||||||
import { setApiUrlPrefix } from '../app/api';
|
import { setApiUrlPrefix, getConstants } from '../app/api';
|
||||||
import metrics from '../app/metrics';
|
import metrics from '../app/metrics';
|
||||||
//import assets from '../common/assets';
|
//import assets from '../common/assets';
|
||||||
import Archive from '../app/archive';
|
import Archive from '../app/archive';
|
||||||
@ -78,14 +58,17 @@ function body(main) {
|
|||||||
}
|
}
|
||||||
(async function start() {
|
(async function start() {
|
||||||
const translate = await getTranslator('en-US');
|
const translate = await getTranslator('en-US');
|
||||||
|
const { LIMITS, DEFAULTS } = await getConstants();
|
||||||
app.use((state, emitter) => {
|
app.use((state, emitter) => {
|
||||||
|
state.LIMITS = LIMITS;
|
||||||
|
state.DEFAULTS = DEFAULTS;
|
||||||
state.translate = translate;
|
state.translate = translate;
|
||||||
state.capabilities = {
|
state.capabilities = {
|
||||||
account: true
|
account: true
|
||||||
}; //TODO
|
}; //TODO
|
||||||
state.archive = new Archive();
|
state.archive = new Archive([], DEFAULTS.EXPIRE_SECONDS);
|
||||||
state.storage = storage;
|
state.storage = storage;
|
||||||
state.user = new User(storage);
|
state.user = new User(storage, LIMITS);
|
||||||
state.raven = Raven;
|
state.raven = Raven;
|
||||||
|
|
||||||
window.finishLogin = async function(accountInfo) {
|
window.finishLogin = async function(accountInfo) {
|
||||||
|
@ -3,8 +3,8 @@ import User from '../app/user';
|
|||||||
import { deriveFileListKey } from '../app/fxa';
|
import { deriveFileListKey } from '../app/fxa';
|
||||||
|
|
||||||
export default class AndroidUser extends User {
|
export default class AndroidUser extends User {
|
||||||
constructor(storage) {
|
constructor(storage, limits) {
|
||||||
super(storage);
|
super(storage, limits);
|
||||||
}
|
}
|
||||||
|
|
||||||
async login() {
|
async login() {
|
||||||
|
11
app/api.js
11
app/api.js
@ -401,3 +401,14 @@ export function sendMetrics(blob) {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getConstants() {
|
||||||
|
const response = await fetch(getApiUrl('/config'));
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const obj = await response.json();
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(response.status);
|
||||||
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/* global LIMITS DEFAULTS */
|
|
||||||
import { blobStream, concatStream } from './streams';
|
import { blobStream, concatStream } from './streams';
|
||||||
|
|
||||||
function isDupe(newFile, array) {
|
function isDupe(newFile, array) {
|
||||||
@ -15,9 +14,10 @@ function isDupe(newFile, array) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class Archive {
|
export default class Archive {
|
||||||
constructor(files = []) {
|
constructor(files = [], defaultTimeLimit = 86400) {
|
||||||
this.files = Array.from(files);
|
this.files = Array.from(files);
|
||||||
this.timeLimit = DEFAULTS.EXPIRE_SECONDS;
|
this.defaultTimeLimit = defaultTimeLimit;
|
||||||
|
this.timeLimit = defaultTimeLimit;
|
||||||
this.dlimit = 1;
|
this.dlimit = 1;
|
||||||
this.password = null;
|
this.password = null;
|
||||||
}
|
}
|
||||||
@ -52,8 +52,8 @@ export default class Archive {
|
|||||||
return concatStream(this.files.map(file => blobStream(file)));
|
return concatStream(this.files.map(file => blobStream(file)));
|
||||||
}
|
}
|
||||||
|
|
||||||
addFiles(files, maxSize) {
|
addFiles(files, maxSize, maxFiles) {
|
||||||
if (this.files.length + files.length > LIMITS.MAX_FILES_PER_ARCHIVE) {
|
if (this.files.length + files.length > maxFiles) {
|
||||||
throw new Error('tooManyFiles');
|
throw new Error('tooManyFiles');
|
||||||
}
|
}
|
||||||
const newFiles = files.filter(
|
const newFiles = files.filter(
|
||||||
@ -77,7 +77,7 @@ export default class Archive {
|
|||||||
clear() {
|
clear() {
|
||||||
this.files = [];
|
this.files = [];
|
||||||
this.dlimit = 1;
|
this.dlimit = 1;
|
||||||
this.timeLimit = DEFAULTS.EXPIRE_SECONDS;
|
this.timeLimit = this.defaultTimeLimit;
|
||||||
this.password = null;
|
this.password = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/* global LIMITS */
|
|
||||||
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';
|
||||||
@ -87,15 +86,19 @@ export default function(state, emitter) {
|
|||||||
}
|
}
|
||||||
const maxSize = state.user.maxSize;
|
const maxSize = state.user.maxSize;
|
||||||
try {
|
try {
|
||||||
state.archive.addFiles(files, maxSize);
|
state.archive.addFiles(
|
||||||
|
files,
|
||||||
|
maxSize,
|
||||||
|
state.LIMITS.MAX_FILES_PER_ARCHIVE
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.message === 'fileTooBig' && maxSize < LIMITS.MAX_FILE_SIZE) {
|
if (e.message === 'fileTooBig' && maxSize < state.LIMITS.MAX_FILE_SIZE) {
|
||||||
return emitter.emit('signup-cta', 'size');
|
return emitter.emit('signup-cta', 'size');
|
||||||
}
|
}
|
||||||
state.modal = okDialog(
|
state.modal = okDialog(
|
||||||
state.translate(e.message, {
|
state.translate(e.message, {
|
||||||
size: bytes(maxSize),
|
size: bytes(maxSize),
|
||||||
count: LIMITS.MAX_FILES_PER_ARCHIVE
|
count: state.LIMITS.MAX_FILES_PER_ARCHIVE
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -119,10 +122,10 @@ export default function(state, emitter) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
emitter.on('upload', async () => {
|
emitter.on('upload', async () => {
|
||||||
if (state.storage.files.length >= LIMITS.MAX_ARCHIVES_PER_USER) {
|
if (state.storage.files.length >= state.LIMITS.MAX_ARCHIVES_PER_USER) {
|
||||||
state.modal = okDialog(
|
state.modal = okDialog(
|
||||||
state.translate('tooManyArchives', {
|
state.translate('tooManyArchives', {
|
||||||
count: LIMITS.MAX_ARCHIVES_PER_USER
|
count: state.LIMITS.MAX_ARCHIVES_PER_USER
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
return render();
|
return render();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* global LOCALE */
|
/* global DEFAULTS LIMITS LOCALE */
|
||||||
import 'core-js';
|
import 'core-js';
|
||||||
import 'fast-text-encoding'; // MS Edge support
|
import 'fast-text-encoding'; // MS Edge support
|
||||||
import 'fluent-intl-polyfill';
|
import 'fluent-intl-polyfill';
|
||||||
@ -41,12 +41,14 @@ if (process.env.NODE_ENV === 'production') {
|
|||||||
|
|
||||||
const translate = await getTranslator(LOCALE);
|
const translate = await getTranslator(LOCALE);
|
||||||
window.initialState = {
|
window.initialState = {
|
||||||
archive: new Archive(),
|
LIMITS,
|
||||||
|
DEFAULTS,
|
||||||
|
archive: new Archive([], DEFAULTS.EXPIRE_SECONDS),
|
||||||
capabilities,
|
capabilities,
|
||||||
translate,
|
translate,
|
||||||
storage,
|
storage,
|
||||||
raven: Raven,
|
raven: Raven,
|
||||||
user: new User(storage),
|
user: new User(storage, LIMITS, window.AUTH_CONFIG),
|
||||||
transfer: null,
|
transfer: null,
|
||||||
fileInfo: null
|
fileInfo: null
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* global Android LIMITS */
|
/* global Android */
|
||||||
|
|
||||||
const html = require('choo/html');
|
const html = require('choo/html');
|
||||||
const raw = require('choo/html/raw');
|
const raw = require('choo/html/raw');
|
||||||
@ -390,7 +390,7 @@ module.exports.empty = function(state, emit) {
|
|||||||
: html`
|
: html`
|
||||||
<p class="center font-medium text-xs text-grey-dark mt-4 mb-2">
|
<p class="center font-medium text-xs text-grey-dark mt-4 mb-2">
|
||||||
${state.translate('signInSizeBump', {
|
${state.translate('signInSizeBump', {
|
||||||
size: bytes(LIMITS.MAX_FILE_SIZE, 0)
|
size: bytes(state.LIMITS.MAX_FILE_SIZE, 0)
|
||||||
})}
|
})}
|
||||||
</p>
|
</p>
|
||||||
`;
|
`;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/* globals DEFAULTS */
|
|
||||||
const html = require('choo/html');
|
const html = require('choo/html');
|
||||||
const raw = require('choo/html/raw');
|
const raw = require('choo/html/raw');
|
||||||
const { secondsToL10nId } = require('../utils');
|
const { secondsToL10nId } = require('../utils');
|
||||||
@ -21,7 +20,7 @@ module.exports = function(state, emit) {
|
|||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
const counts = DEFAULTS.DOWNLOAD_COUNTS.filter(
|
const counts = state.DEFAULTS.DOWNLOAD_COUNTS.filter(
|
||||||
i => state.capabilities.account || i <= state.user.maxDownloads
|
i => state.capabilities.account || i <= state.user.maxDownloads
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -45,7 +44,7 @@ module.exports = function(state, emit) {
|
|||||||
dlCountSelect
|
dlCountSelect
|
||||||
);
|
);
|
||||||
|
|
||||||
const expires = DEFAULTS.EXPIRE_TIMES_SECONDS.filter(
|
const expires = state.DEFAULTS.EXPIRE_TIMES_SECONDS.filter(
|
||||||
i => state.capabilities.account || i <= state.user.maxExpireSeconds
|
i => state.capabilities.account || i <= state.user.maxExpireSeconds
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
/* global LIMITS */
|
|
||||||
const html = require('choo/html');
|
const html = require('choo/html');
|
||||||
const { bytes, platform } = require('../utils');
|
const { bytes, platform } = require('../utils');
|
||||||
const { canceledSignup, submittedSignup } = require('../metrics');
|
const { canceledSignup, submittedSignup } = require('../metrics');
|
||||||
|
|
||||||
const DAYS = Math.floor(LIMITS.MAX_EXPIRE_SECONDS / 86400);
|
|
||||||
|
|
||||||
module.exports = function(trigger) {
|
module.exports = function(trigger) {
|
||||||
return function(state, emit, close) {
|
return function(state, emit, close) {
|
||||||
|
const DAYS = Math.floor(state.LIMITS.MAX_EXPIRE_SECONDS / 86400);
|
||||||
const hidden = platform() === 'android' ? 'hidden' : '';
|
const hidden = platform() === 'android' ? 'hidden' : '';
|
||||||
let submitting = false;
|
let submitting = false;
|
||||||
return html`
|
return html`
|
||||||
@ -14,7 +12,7 @@ module.exports = function(trigger) {
|
|||||||
<h2 class="font-bold">${state.translate('accountBenefitTitle')}</h3>
|
<h2 class="font-bold">${state.translate('accountBenefitTitle')}</h3>
|
||||||
<ul class="my-2 leading-normal list-reset text-lg mb-8 mt-4">
|
<ul class="my-2 leading-normal list-reset text-lg mb-8 mt-4">
|
||||||
<li>${state.translate('accountBenefitLargeFiles', {
|
<li>${state.translate('accountBenefitLargeFiles', {
|
||||||
size: bytes(LIMITS.MAX_FILE_SIZE)
|
size: bytes(state.LIMITS.MAX_FILE_SIZE)
|
||||||
})}</li>
|
})}</li>
|
||||||
<li>${state.translate('accountBenefitExpiry')}</li>
|
<li>${state.translate('accountBenefitExpiry')}</li>
|
||||||
<li>${state.translate('accountBenefitExpiryTwo', { count: DAYS })}</li>
|
<li>${state.translate('accountBenefitExpiryTwo', { count: DAYS })}</li>
|
||||||
|
29
app/user.js
29
app/user.js
@ -1,4 +1,3 @@
|
|||||||
/* global LIMITS AUTH_CONFIG */
|
|
||||||
import assets from '../common/assets';
|
import assets from '../common/assets';
|
||||||
import { getFileList, setFileList } from './api';
|
import { getFileList, setFileList } from './api';
|
||||||
import { encryptStream, decryptStream } from './ece';
|
import { encryptStream, decryptStream } from './ece';
|
||||||
@ -21,7 +20,9 @@ async function hashId(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class User {
|
export default class User {
|
||||||
constructor(storage) {
|
constructor(storage, limits, authConfig) {
|
||||||
|
this.authConfig = authConfig;
|
||||||
|
this.limits = limits;
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
this.data = storage.user || {};
|
this.data = storage.user || {};
|
||||||
}
|
}
|
||||||
@ -68,17 +69,21 @@ export default class User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get maxSize() {
|
get maxSize() {
|
||||||
return this.loggedIn ? LIMITS.MAX_FILE_SIZE : LIMITS.ANON.MAX_FILE_SIZE;
|
return this.loggedIn
|
||||||
|
? this.limits.MAX_FILE_SIZE
|
||||||
|
: this.limits.ANON.MAX_FILE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
get maxExpireSeconds() {
|
get maxExpireSeconds() {
|
||||||
return this.loggedIn
|
return this.loggedIn
|
||||||
? LIMITS.MAX_EXPIRE_SECONDS
|
? this.limits.MAX_EXPIRE_SECONDS
|
||||||
: LIMITS.ANON.MAX_EXPIRE_SECONDS;
|
: this.limits.ANON.MAX_EXPIRE_SECONDS;
|
||||||
}
|
}
|
||||||
|
|
||||||
get maxDownloads() {
|
get maxDownloads() {
|
||||||
return this.loggedIn ? LIMITS.MAX_DOWNLOADS : LIMITS.ANON.MAX_DOWNLOADS;
|
return this.loggedIn
|
||||||
|
? this.limits.MAX_DOWNLOADS
|
||||||
|
: this.limits.ANON.MAX_DOWNLOADS;
|
||||||
}
|
}
|
||||||
|
|
||||||
async metricId() {
|
async metricId() {
|
||||||
@ -95,11 +100,11 @@ export default class User {
|
|||||||
const keys_jwk = await prepareScopedBundleKey(this.storage);
|
const keys_jwk = await prepareScopedBundleKey(this.storage);
|
||||||
const code_challenge = await preparePkce(this.storage);
|
const code_challenge = await preparePkce(this.storage);
|
||||||
const options = {
|
const options = {
|
||||||
client_id: AUTH_CONFIG.client_id,
|
client_id: this.authConfig.client_id,
|
||||||
code_challenge,
|
code_challenge,
|
||||||
code_challenge_method: 'S256',
|
code_challenge_method: 'S256',
|
||||||
response_type: 'code',
|
response_type: 'code',
|
||||||
scope: `profile ${AUTH_CONFIG.key_scope}`,
|
scope: `profile ${this.authConfig.key_scope}`,
|
||||||
state,
|
state,
|
||||||
keys_jwk
|
keys_jwk
|
||||||
};
|
};
|
||||||
@ -108,7 +113,7 @@ export default class User {
|
|||||||
}
|
}
|
||||||
const params = new URLSearchParams(options);
|
const params = new URLSearchParams(options);
|
||||||
location.assign(
|
location.assign(
|
||||||
`${AUTH_CONFIG.authorization_endpoint}?${params.toString()}`
|
`${this.authConfig.authorization_endpoint}?${params.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,19 +123,19 @@ export default class User {
|
|||||||
if (state !== localState) {
|
if (state !== localState) {
|
||||||
throw new Error('state mismatch');
|
throw new Error('state mismatch');
|
||||||
}
|
}
|
||||||
const tokenResponse = await fetch(AUTH_CONFIG.token_endpoint, {
|
const tokenResponse = await fetch(this.authConfig.token_endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
code,
|
code,
|
||||||
client_id: AUTH_CONFIG.client_id,
|
client_id: this.authConfig.client_id,
|
||||||
code_verifier: this.storage.get('pkceVerifier')
|
code_verifier: this.storage.get('pkceVerifier')
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
const auth = await tokenResponse.json();
|
const auth = await tokenResponse.json();
|
||||||
const infoResponse = await fetch(AUTH_CONFIG.userinfo_endpoint, {
|
const infoResponse = await fetch(this.authConfig.userinfo_endpoint, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${auth.access_token}`
|
Authorization: `Bearer ${auth.access_token}`
|
||||||
|
21
server/clientConstants.js
Normal file
21
server/clientConstants.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
const config = require('./config');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
LIMITS: {
|
||||||
|
ANON: {
|
||||||
|
MAX_FILE_SIZE: config.anon_max_file_size,
|
||||||
|
MAX_DOWNLOADS: config.anon_max_downloads,
|
||||||
|
MAX_EXPIRE_SECONDS: config.anon_max_expire_seconds
|
||||||
|
},
|
||||||
|
MAX_FILE_SIZE: config.max_file_size,
|
||||||
|
MAX_DOWNLOADS: config.max_downloads,
|
||||||
|
MAX_EXPIRE_SECONDS: config.max_expire_seconds,
|
||||||
|
MAX_FILES_PER_ARCHIVE: config.max_files_per_archive,
|
||||||
|
MAX_ARCHIVES_PER_USER: config.max_archives_per_user
|
||||||
|
},
|
||||||
|
DEFAULTS: {
|
||||||
|
DOWNLOAD_COUNTS: config.download_counts,
|
||||||
|
EXPIRE_TIMES_SECONDS: config.expire_times_seconds,
|
||||||
|
EXPIRE_SECONDS: config.default_expire_seconds
|
||||||
|
}
|
||||||
|
};
|
@ -1,6 +1,7 @@
|
|||||||
const html = require('choo/html');
|
const html = require('choo/html');
|
||||||
const raw = require('choo/html/raw');
|
const raw = require('choo/html/raw');
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
|
const clientConstants = require('./clientConstants');
|
||||||
|
|
||||||
let sentry = '';
|
let sentry = '';
|
||||||
if (config.sentry_id) {
|
if (config.sentry_id) {
|
||||||
@ -44,23 +45,8 @@ module.exports = function(state) {
|
|||||||
window.location.assign('/unsupported/outdated');
|
window.location.assign('/unsupported/outdated');
|
||||||
}
|
}
|
||||||
|
|
||||||
var LIMITS = {
|
var LIMITS = ${JSON.stringify(clientConstants.LIMITS)};
|
||||||
ANON: {
|
var DEFAULTS = ${JSON.stringify(clientConstants.DEFAULTS)};
|
||||||
MAX_FILE_SIZE: ${config.anon_max_file_size},
|
|
||||||
MAX_DOWNLOADS: ${config.anon_max_downloads},
|
|
||||||
MAX_EXPIRE_SECONDS: ${config.anon_max_expire_seconds},
|
|
||||||
},
|
|
||||||
MAX_FILE_SIZE: ${config.max_file_size},
|
|
||||||
MAX_DOWNLOADS: ${config.max_downloads},
|
|
||||||
MAX_EXPIRE_SECONDS: ${config.max_expire_seconds},
|
|
||||||
MAX_FILES_PER_ARCHIVE: ${config.max_files_per_archive},
|
|
||||||
MAX_ARCHIVES_PER_USER: ${config.max_archives_per_user}
|
|
||||||
};
|
|
||||||
var DEFAULTS = {
|
|
||||||
DOWNLOAD_COUNTS: ${JSON.stringify(config.download_counts)},
|
|
||||||
EXPIRE_TIMES_SECONDS: ${JSON.stringify(config.expire_times_seconds)},
|
|
||||||
EXPIRE_SECONDS: ${config.default_expire_seconds}
|
|
||||||
};
|
|
||||||
const LOCALE = '${state.locale}';
|
const LOCALE = '${state.locale}';
|
||||||
const downloadMetadata = ${
|
const downloadMetadata = ${
|
||||||
state.downloadMetadata ? raw(JSON.stringify(state.downloadMetadata)) : '{}'
|
state.downloadMetadata ? raw(JSON.stringify(state.downloadMetadata)) : '{}'
|
||||||
|
@ -8,6 +8,7 @@ const auth = require('../middleware/auth');
|
|||||||
const language = require('../middleware/language');
|
const language = require('../middleware/language');
|
||||||
const pages = require('./pages');
|
const pages = require('./pages');
|
||||||
const filelist = require('./filelist');
|
const filelist = require('./filelist');
|
||||||
|
const clientConstants = require('../clientConstants');
|
||||||
|
|
||||||
const IS_DEV = config.env === 'development';
|
const IS_DEV = config.env === 'development';
|
||||||
const ID_REGEX = '([0-9a-fA-F]{10})';
|
const ID_REGEX = '([0-9a-fA-F]{10})';
|
||||||
@ -70,6 +71,9 @@ module.exports = function(app) {
|
|||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.use(bodyParser.text());
|
app.use(bodyParser.text());
|
||||||
app.get('/', language, pages.index);
|
app.get('/', language, pages.index);
|
||||||
|
app.get('/config', function(req, res) {
|
||||||
|
res.json(clientConstants);
|
||||||
|
});
|
||||||
app.get('/error', language, pages.blank);
|
app.get('/error', language, pages.blank);
|
||||||
app.get('/oauth', language, pages.blank);
|
app.get('/oauth', language, pages.blank);
|
||||||
app.get('/legal', language, pages.legal);
|
app.get('/legal', language, pages.legal);
|
||||||
|
@ -52,7 +52,7 @@ describe('Firefox Send', function() {
|
|||||||
browser.back();
|
browser.back();
|
||||||
browser.waitForExist('send-archive');
|
browser.waitForExist('send-archive');
|
||||||
assert.equal(
|
assert.equal(
|
||||||
browser.getText('send-archive > div').substring(0, 24),
|
browser.getText('send-archive > div:first-of-type').substring(0, 24),
|
||||||
'Expires after 1 download'
|
'Expires after 1 download'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -17,7 +17,7 @@ class Page {
|
|||||||
waitForPageToLoad() {
|
waitForPageToLoad() {
|
||||||
browser.waitUntil(function() {
|
browser.waitUntil(function() {
|
||||||
return browser.execute(function() {
|
return browser.execute(function() {
|
||||||
return typeof window.appState !== 'undefined';
|
return typeof window.app !== 'undefined';
|
||||||
});
|
});
|
||||||
}, 3000);
|
}, 3000);
|
||||||
browser.pause(100);
|
browser.pause(100);
|
||||||
|
Loading…
Reference in New Issue
Block a user