From 99055b13429d0ac730a49def658892b9f6561c56 Mon Sep 17 00:00:00 2001 From: Danny Coates Date: Tue, 18 Sep 2018 16:23:58 -0700 Subject: [PATCH] fixed leaky app.state on the server-side. fixes #928 --- app/capabilities.js | 7 ++-- app/main.js | 3 +- app/routes/index.js | 80 ++++++++++++++++++++++-------------------- server/routes/pages.js | 12 +++---- 4 files changed, 52 insertions(+), 50 deletions(-) diff --git a/app/capabilities.js b/app/capabilities.js index ab2e0ff0..9d534efb 100644 --- a/app/capabilities.js +++ b/app/capabilities.js @@ -1,3 +1,5 @@ +import { browserName } from './utils'; + async function checkCrypto() { try { const key = await crypto.subtle.generateKey( @@ -76,10 +78,7 @@ export default async function capabilities() { streamDownload: nativeStreams && 'serviceWorker' in navigator && - !( - /safari/i.test(navigator.userAgent) && - !/chrome/i.test(navigator.userAgent) - ), + browserName() !== 'safari', multifile: nativeStreams || polyStreams }; } diff --git a/app/main.js b/app/main.js index 3efb1102..8febde65 100644 --- a/app/main.js +++ b/app/main.js @@ -1,6 +1,6 @@ import 'fast-text-encoding'; // MS Edge support import 'fluent-intl-polyfill'; -import app from './routes'; +import routes from './routes'; import capabilities from './capabilities'; import locale from '../common/locales'; import fileManager from './fileManager'; @@ -14,6 +14,7 @@ import './main.css'; import User from './user'; (async function start() { + const app = routes(); if (navigator.doNotTrack !== '1' && window.RAVEN_CONFIG) { Raven.config(window.SENTRY_ID, window.RAVEN_CONFIG).install(); } diff --git a/app/routes/index.js b/app/routes/index.js index d7db4a36..a28b683e 100644 --- a/app/routes/index.js +++ b/app/routes/index.js @@ -11,23 +11,25 @@ const profile = require('../templates/userAccount'); const modal = require('../templates/modal'); nanotiming.disabled = true; -const app = choo(); -function banner(state, emit) { - if (state.promo && !state.route.startsWith('/unsupported/')) { - return fxPromo(state, emit); +module.exports = function() { + const app = choo(); + + function banner(state, emit) { + if (state.promo && !state.route.startsWith('/unsupported/')) { + return fxPromo(state, emit); + } } -} -function modalDialog(state, emit) { - if (state.modal) { - return modal(state, emit); + function modalDialog(state, emit) { + if (state.modal) { + return modal(state, emit); + } } -} -function body(template) { - return function(state, emit) { - const b = html` + function body(template) { + return function(state, emit) { + const b = html` ${modalDialog(state, emit)} ${banner(state, emit)}
@@ -59,32 +61,32 @@ function body(template) {
${footer(state)} `; - if (state.layout) { - // server side only - return state.layout(state, b); - } - return b; - }; -} - -app.route('/', body(require('../pages/welcome'))); -app.route('/share/:id', body(require('../pages/share'))); -app.route('/download/:id', body(download)); -app.route('/download/:id/:key', body(download)); -app.route('/unsupported/:reason', body(require('../pages/unsupported'))); -app.route('/legal', body(require('../pages/legal'))); -app.route('/error', body(require('../pages/error'))); -app.route('/blank', body(require('../pages/blank'))); -app.route('/signin', body(require('../pages/signin'))); -app.route('/api/fxa/oauth', async function(state, emit) { - try { - await state.user.finishLogin(state.query.code); - emit('replaceState', '/'); - } catch (e) { - emit('replaceState', '/error'); - setTimeout(() => emit('render')); + if (state.layout) { + // server side only + return state.layout(state, b); + } + return b; + }; } -}); -app.route('*', body(require('../pages/notFound'))); -module.exports = app; + app.route('/', body(require('../pages/welcome'))); + app.route('/share/:id', body(require('../pages/share'))); + app.route('/download/:id', body(download)); + app.route('/download/:id/:key', body(download)); + app.route('/unsupported/:reason', body(require('../pages/unsupported'))); + app.route('/legal', body(require('../pages/legal'))); + app.route('/error', body(require('../pages/error'))); + app.route('/blank', body(require('../pages/blank'))); + app.route('/signin', body(require('../pages/signin'))); + app.route('/api/fxa/oauth', async function(state, emit) { + try { + await state.user.finishLogin(state.query.code); + emit('replaceState', '/'); + } catch (e) { + emit('replaceState', '/error'); + setTimeout(() => emit('render')); + } + }); + app.route('*', body(require('../pages/notFound'))); + return app; +}; diff --git a/server/routes/pages.js b/server/routes/pages.js index d880b549..efe8fdae 100644 --- a/server/routes/pages.js +++ b/server/routes/pages.js @@ -10,11 +10,11 @@ function stripEvents(str) { module.exports = { index: function(req, res) { - res.send(stripEvents(routes.toString('/', state(req)))); + res.send(stripEvents(routes().toString('/', state(req)))); }, blank: function(req, res) { - res.send(stripEvents(routes.toString('/blank', state(req)))); + res.send(stripEvents(routes().toString('/blank', state(req)))); }, download: async function(req, res, next) { @@ -24,7 +24,7 @@ module.exports = { res.set('WWW-Authenticate', `send-v1 ${nonce}`); res.send( stripEvents( - routes.toString( + routes().toString( `/download/${id}`, Object.assign(state(req), { downloadMetadata: { nonce, pwd } @@ -40,7 +40,7 @@ module.exports = { unsupported: function(req, res) { res.send( stripEvents( - routes.toString( + routes().toString( `/unsupported/${req.params.reason}`, Object.assign(state(req), { fira: true }) ) @@ -49,10 +49,10 @@ module.exports = { }, legal: function(req, res) { - res.send(stripEvents(routes.toString('/legal', state(req)))); + res.send(stripEvents(routes().toString('/legal', state(req)))); }, notfound: function(req, res) { - res.status(404).send(stripEvents(routes.toString('/404', state(req)))); + res.status(404).send(stripEvents(routes().toString('/404', state(req)))); } };