0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

fix: ensure we initialise activeTheme on bootstrap (#6950)

closes #6948
- the hbs engine was never initialised  when server starts
- when you request a page which does not exist, express jumps directly into the error handlers
- delete some dynamic hbs engine setters in theme handler
This commit is contained in:
Katharina Irrgang 2016-07-21 13:09:11 +02:00 committed by Kevin Ansfield
parent 5e6b952e90
commit 8f2afeed03
4 changed files with 74 additions and 58 deletions

View file

@ -52,6 +52,7 @@ updateConfigCache = function () {
config.set({
theme: {
activeTheme: settingsCache.activeTheme.value,
title: (settingsCache.title && settingsCache.title.value) || '',
description: (settingsCache.description && settingsCache.description.value) || '',
logo: (settingsCache.logo && settingsCache.logo.value) || '',

View file

@ -1,20 +1,21 @@
var bodyParser = require('body-parser'),
compress = require('compression'),
config = require('../config'),
errors = require('../errors'),
express = require('express'),
hbs = require('express-hbs'),
logger = require('morgan'),
multer = require('multer'),
netjet = require('netjet'),
path = require('path'),
routes = require('../routes'),
serveStatic = require('express').static,
slashes = require('connect-slashes'),
storage = require('../storage'),
tmpdir = require('os').tmpdir,
passport = require('passport'),
config = require('../config'),
errors = require('../errors'),
routes = require('../routes'),
storage = require('../storage'),
utils = require('../utils'),
sitemapHandler = require('../data/xml/sitemap/handler'),
multer = require('multer'),
tmpdir = require('os').tmpdir,
authStrategies = require('./auth-strategies'),
auth = require('./auth'),
cacheControl = require('./cache-control'),
@ -30,7 +31,6 @@ var bodyParser = require('body-parser'),
maintenance = require('./maintenance'),
versionMatch = require('./api/version-match'),
cors = require('./cors'),
netjet = require('netjet'),
labs = require('./labs'),
helpers = require('../helpers'),
@ -129,7 +129,7 @@ setupMiddleware = function setupMiddleware(blogApp) {
// First determine whether we're serving admin or theme content
blogApp.use(decideIsAdmin);
blogApp.use(themeHandler.updateActiveTheme);
blogApp.use(themeHandler.updateActiveTheme(blogApp));
blogApp.use(themeHandler.configHbsForContext);
// Admin only config

View file

@ -48,7 +48,6 @@ themeHandler = {
// Pass 'secure' flag to the view engine
// so that templates can choose 'url' vs 'urlSSL'
res.locals.secure = req.secure;
next();
},
@ -89,40 +88,37 @@ themeHandler = {
// Updates the blogApp's activeTheme variable and subsequently
// activates that theme's views with the hbs templating engine if it
// is not yet activated.
updateActiveTheme: function updateActiveTheme(req, res, next) {
var blogApp = req.app;
//
// on server bootstrap we activate the default theme (which is casper)
updateActiveTheme: function updateActiveTheme(blog) {
themeHandler.activateTheme(blog, config.theme.activeTheme);
api.settings.read({context: {internal: true}, key: 'activeTheme'}).then(function then(response) {
var activeTheme = response.settings[0];
return function updateActiveThemeDynamically(req, res, next) {
var blogApp = req.app;
// Check if the theme changed
if (activeTheme.value !== blogApp.get('activeTheme')) {
// Change theme
if (!config.paths.availableThemes.hasOwnProperty(activeTheme.value)) {
if (!res.isAdmin) {
// Throw an error if the theme is not available, but not on the admin UI
return errors.throwError(i18n.t('errors.middleware.themehandler.missingTheme', {theme: activeTheme.value}));
api.settings.read({context: {internal: true}, key: 'activeTheme'}).then(function then(response) {
var activeTheme = response.settings[0];
// Check if the theme changed
if (activeTheme.value !== blogApp.get('activeTheme')) {
// Change theme
if (!config.paths.availableThemes.hasOwnProperty(activeTheme.value)) {
if (!res.isAdmin) {
// Throw an error if the theme is not available, but not on the admin UI
return errors.throwError(i18n.t('errors.middleware.themehandler.missingTheme', {theme: activeTheme.value}));
} else {
errors.logWarn(i18n.t('errors.middleware.themehandler.missingTheme', {theme: activeTheme.value}));
return next();
}
} else {
// At this point the activated theme is not present and the current
// request is for the admin client. In order to allow the user access
// to the admin client we set an hbs instance on the app so that middleware
// processing can continue.
blogApp.engine('hbs', hbs.express3());
errors.logWarn(i18n.t('errors.middleware.themehandler.missingTheme', {theme: activeTheme.value}));
return next();
themeHandler.activateTheme(blogApp, activeTheme.value);
}
} else {
themeHandler.activateTheme(blogApp, activeTheme.value);
}
}
next();
}).catch(function handleError(err) {
// Trying to start up without the active theme present, setup a simple hbs instance
// and render an error page straight away.
blogApp.engine('hbs', hbs.express3());
next(err);
});
next();
}).catch(function handleError(err) {
next(err);
});
};
}
};

View file

@ -127,19 +127,34 @@ describe('Theme Handler', function () {
});
describe('updateActiveTheme', function () {
it('updates the active theme if changed', function (done) {
it('sets active theme on bootstrap', function () {
should.not.exist(blogApp.get('activeTheme'));
var activateThemeSpy = sandbox.spy(themeHandler, 'activateTheme');
sandbox.stub(api.settings, 'read').withArgs(sandbox.match.has('key', 'activeTheme')).returns(Promise.resolve({
settings: [{
key: 'activeKey',
value: 'casper'
}]
}));
blogApp.set('activeTheme', 'not-casper');
configUtils.set({theme: {activeTheme: 'casper'}});
configUtils.set({paths: {availableThemes: {casper: {}}}});
themeHandler.updateActiveTheme(req, res, function () {
activateThemeSpy.called.should.be.true();
themeHandler.updateActiveTheme(blogApp);
activateThemeSpy.calledOnce.should.eql(true);
blogApp.get('activeTheme').should.eql('casper');
});
it('updates the active theme if changed', function (done) {
var activateThemeSpy = sandbox.spy(themeHandler, 'activateTheme');
sandbox.stub(api.settings, 'read').withArgs(sandbox.match.has('key', 'activeTheme')).returns(Promise.resolve({
settings: [{
key: 'activateTheme',
value: 'new-theme'
}]
}));
configUtils.set({theme: {activeTheme: 'casper'}});
configUtils.set({paths: {availableThemes: {casper: {}, 'new-theme': {}}}});
themeHandler.updateActiveTheme(blogApp)(req, res, function () {
activateThemeSpy.calledTwice.should.be.true();
blogApp.get('activeTheme').should.eql('new-theme');
done();
});
});
@ -148,15 +163,17 @@ describe('Theme Handler', function () {
var activateThemeSpy = sandbox.spy(themeHandler, 'activateTheme');
sandbox.stub(api.settings, 'read').withArgs(sandbox.match.has('key', 'activeTheme')).returns(Promise.resolve({
settings: [{
key: 'activeKey',
key: 'activateTheme',
value: 'casper'
}]
}));
blogApp.set('activeTheme', 'casper');
configUtils.set({theme: {activeTheme: 'casper'}});
configUtils.set({paths: {availableThemes: {casper: {}}}});
themeHandler.updateActiveTheme(req, res, function () {
activateThemeSpy.called.should.be.false();
themeHandler.updateActiveTheme(blogApp)(req, res, function () {
activateThemeSpy.calledOnce.should.be.true();
blogApp.get('activeTheme').should.eql('casper');
done();
});
});
@ -171,13 +188,14 @@ describe('Theme Handler', function () {
value: 'rasper'
}]
}));
blogApp.set('activeTheme', 'not-casper');
configUtils.set({theme: {activeTheme: 'casper'}});
configUtils.set({paths: {availableThemes: {casper: {}}}});
themeHandler.updateActiveTheme(req, res, function (err) {
themeHandler.updateActiveTheme(blogApp)(req, res, function (err) {
should.exist(err);
errorSpy.called.should.be.true();
activateThemeSpy.called.should.be.false();
activateThemeSpy.calledOnce.should.be.true();
err.message.should.eql('The currently active theme "rasper" is missing.');
done();
});
@ -194,13 +212,14 @@ describe('Theme Handler', function () {
value: 'rasper'
}]
}));
res.isAdmin = true;
blogApp.set('activeTheme', 'not-casper');
configUtils.set({theme: {activeTheme: 'casper'}});
configUtils.set({paths: {availableThemes: {casper: {}}}});
themeHandler.updateActiveTheme(req, res, function () {
themeHandler.updateActiveTheme(blogApp)(req, res, function () {
errorSpy.called.should.be.false();
activateThemeSpy.called.should.be.false();
activateThemeSpy.calledOnce.should.be.true();
warnSpy.called.should.be.true();
warnSpy.calledWith('The currently active theme "rasper" is missing.').should.be.true();
done();