0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-20 22:42:53 -05:00

🎨 Ghost bootstrap: optimise requires (#8121)

* 🎨  Ghost bootstrap: optimise requires

no issue

- require as less as possible on bootstrap

* do not load icojs on bootstrap
This commit is contained in:
Katharina Irrgang 2017-03-13 21:07:12 +01:00 committed by Hannah Wolfe
parent e0cd5b55ce
commit 7556e68c48
9 changed files with 222 additions and 138 deletions

View file

@ -309,7 +309,7 @@ authentication = {
})); }));
} }
spamPrevention.userLogin.reset(opts.ip, tokenParts.email + 'login'); spamPrevention.userLogin().reset(opts.ip, tokenParts.email + 'login');
return models.User.changePassword({ return models.User.changePassword({
oldPassword: oldPassword, oldPassword: oldPassword,

View file

@ -8,19 +8,16 @@
// there if available. The cacheId is a combination of `updated_at` and the `slug`. // there if available. The cacheId is a combination of `updated_at` and the `slug`.
var hbs = require('express-hbs'), var hbs = require('express-hbs'),
Promise = require('bluebird'), Promise = require('bluebird'),
Amperize = require('amperize'),
moment = require('moment'), moment = require('moment'),
sanitizeHtml = require('sanitize-html'),
logging = require('../../../../logging'), logging = require('../../../../logging'),
i18n = require('../../../../i18n'), i18n = require('../../../../i18n'),
errors = require('../../../../errors'), errors = require('../../../../errors'),
makeAbsoluteUrl = require('../../../../utils/make-absolute-urls'), makeAbsoluteUrl = require('../../../../utils/make-absolute-urls'),
utils = require('../../../../utils'), utils = require('../../../../utils'),
cheerio = require('cheerio'),
amperize = new Amperize(),
amperizeCache = {}, amperizeCache = {},
allowedAMPTags = [], allowedAMPTags = [],
allowedAMPAttributes = {}, allowedAMPAttributes = {},
amperize,
cleanHTML, cleanHTML,
ampHTML; ampHTML;
@ -120,6 +117,9 @@ function getAmperizeHTML(html, post) {
return; return;
} }
var Amperize = require('amperize');
amperize = amperize || new Amperize();
// make relative URLs abolute // make relative URLs abolute
html = makeAbsoluteUrl(html, utils.url.urlFor('home', true), post.url).html(); html = makeAbsoluteUrl(html, utils.url.urlFor('home', true), post.url).html();
@ -154,7 +154,9 @@ function getAmperizeHTML(html, post) {
} }
function ampContent() { function ampContent() {
var amperizeHTML = { var sanitizeHtml = require('sanitize-html'),
cheerio = require('cheerio'),
amperizeHTML = {
amperize: getAmperizeHTML(this.html, this) amperize: getAmperizeHTML(this.html, this)
}; };

View file

@ -17,7 +17,7 @@ function exchangeRefreshToken(client, refreshToken, scope, body, authInfo, done)
var token = model.toJSON(); var token = model.toJSON();
if (token.expires > Date.now()) { if (token.expires > Date.now()) {
spamPrevention.userLogin.reset(authInfo.ip, body.refresh_token + 'login'); spamPrevention.userLogin().reset(authInfo.ip, body.refresh_token + 'login');
authUtils.createTokens({ authUtils.createTokens({
clientId: token.client_id, clientId: token.client_id,
@ -54,7 +54,7 @@ function exchangePassword(client, username, password, scope, body, authInfo, don
}); });
}) })
.then(function then(response) { .then(function then(response) {
spamPrevention.userLogin.reset(authInfo.ip, username + 'login'); spamPrevention.userLogin().reset(authInfo.ip, username + 'login');
return done(null, response.access_token, response.refresh_token, {expires_in: response.expires_in}); return done(null, response.access_token, response.refresh_token, {expires_in: response.expires_in});
}); });
}) })
@ -83,7 +83,7 @@ function exchangeAuthorizationCode(req, res, next) {
})); }));
} }
spamPrevention.userLogin.reset(req.authInfo.ip, req.body.authorizationCode + 'login'); spamPrevention.userLogin().reset(req.authInfo.ip, req.body.authorizationCode + 'login');
authUtils.createTokens({ authUtils.createTokens({
clientId: req.client.id, clientId: req.client.id,

View file

@ -2,7 +2,6 @@
// Handles sending email for Ghost // Handles sending email for Ghost
var _ = require('lodash'), var _ = require('lodash'),
Promise = require('bluebird'), Promise = require('bluebird'),
nodemailer = require('nodemailer'),
validator = require('validator'), validator = require('validator'),
config = require('../config'), config = require('../config'),
settingsCache = require('../settings/cache'), settingsCache = require('../settings/cache'),
@ -10,13 +9,12 @@ var _ = require('lodash'),
utils = require('../utils'); utils = require('../utils');
function GhostMailer() { function GhostMailer() {
var transport = config.get('mail') && config.get('mail').transport || 'direct', var nodemailer = require('nodemailer'),
transport = config.get('mail') && config.get('mail').transport || 'direct',
options = config.get('mail') && _.clone(config.get('mail').options) || {}; options = config.get('mail') && _.clone(config.get('mail').options) || {};
this.state = {}; this.state = {};
this.transport = nodemailer.createTransport(transport, options); this.transport = nodemailer.createTransport(transport, options);
this.state.usingDirect = transport === 'direct'; this.state.usingDirect = transport === 'direct';
} }

View file

@ -1,8 +1,4 @@
var ExpressBrute = require('express-brute'), var moment = require('moment'),
BruteKnex = require('brute-knex'),
knexInstance = require('../../data/db/connection'),
store = new BruteKnex({tablename: 'brute', createTable:false, knex: knexInstance}),
moment = require('moment'),
errors = require('../../errors'), errors = require('../../errors'),
config = require('../../config'), config = require('../../config'),
spam = config.get('spam') || {}, spam = config.get('spam') || {},
@ -14,9 +10,15 @@ var ExpressBrute = require('express-brute'),
spamUserLogin = spam.user_login || {}, spamUserLogin = spam.user_login || {},
i18n = require('../../i18n'), i18n = require('../../i18n'),
store,
handleStoreError, handleStoreError,
globalBlock, globalBlock,
globalReset, globalReset,
privateBlogInstance,
globalResetInstance,
globalBlockInstance,
userLoginInstance,
userResetInstance,
privateBlog, privateBlog,
userLogin, userLogin,
userReset, userReset,
@ -46,7 +48,18 @@ handleStoreError = function handleStoreError(err) {
// requests from a single IP // requests from a single IP
// We allow for a generous number of requests here to prevent communites on the same IP bing barred on account of a single suer // We allow for a generous number of requests here to prevent communites on the same IP bing barred on account of a single suer
// Defaults to 50 attempts per hour and locks the endpoint for an hour // Defaults to 50 attempts per hour and locks the endpoint for an hour
globalBlock = new ExpressBrute(store, globalBlock = function globalBlock() {
var ExpressBrute = require('express-brute'),
BruteKnex = require('brute-knex'),
db = require('../../data/db');
store = store || new BruteKnex({
tablename: 'brute',
createTable: false,
knex: db.knex
});
globalBlockInstance = globalBlockInstance || new ExpressBrute(store,
_.extend({ _.extend({
attachResetToRequest: false, attachResetToRequest: false,
failCallback: function (req, res, next, nextValidRequestDate) { failCallback: function (req, res, next, nextValidRequestDate) {
@ -61,7 +74,21 @@ globalBlock = new ExpressBrute(store,
}, _.pick(spamGlobalBlock, spamConfigKeys)) }, _.pick(spamGlobalBlock, spamConfigKeys))
); );
globalReset = new ExpressBrute(store, return globalBlockInstance;
};
globalReset = function globalReset() {
var ExpressBrute = require('express-brute'),
BruteKnex = require('brute-knex'),
db = require('../../data/db');
store = store || new BruteKnex({
tablename: 'brute',
createTable: false,
knex: db.knex
});
globalResetInstance = globalResetInstance || new ExpressBrute(store,
_.extend({ _.extend({
attachResetToRequest: false, attachResetToRequest: false,
failCallback: function (req, res, next, nextValidRequestDate) { failCallback: function (req, res, next, nextValidRequestDate) {
@ -77,11 +104,25 @@ globalReset = new ExpressBrute(store,
}, _.pick(spamGlobalReset, spamConfigKeys)) }, _.pick(spamGlobalReset, spamConfigKeys))
); );
return globalResetInstance;
};
// Stops login attempts for a user+IP pair with an increasing time period starting from 10 minutes // Stops login attempts for a user+IP pair with an increasing time period starting from 10 minutes
// and rising to a week in a fibonnaci sequence // and rising to a week in a fibonnaci sequence
// The user+IP count is reset when on successful login // The user+IP count is reset when on successful login
// Default value of 5 attempts per user+IP pair // Default value of 5 attempts per user+IP pair
userLogin = new ExpressBrute(store, userLogin = function userLogin() {
var ExpressBrute = require('express-brute'),
BruteKnex = require('brute-knex'),
db = require('../../data/db');
store = store || new BruteKnex({
tablename: 'brute',
createTable: false,
knex: db.knex
});
userLoginInstance = userLoginInstance || new ExpressBrute(store,
_.extend({ _.extend({
attachResetToRequest: true, attachResetToRequest: true,
failCallback: function (req, res, next, nextValidRequestDate) { failCallback: function (req, res, next, nextValidRequestDate) {
@ -96,10 +137,24 @@ userLogin = new ExpressBrute(store,
}, _.pick(spamUserLogin, spamConfigKeys)) }, _.pick(spamUserLogin, spamConfigKeys))
); );
return userLoginInstance;
};
// Stop password reset requests when there are (freeRetries + 1) requests per lifetime per email // Stop password reset requests when there are (freeRetries + 1) requests per lifetime per email
// Defaults here are 5 attempts per hour for a user+IP pair // Defaults here are 5 attempts per hour for a user+IP pair
// The endpoint is then locked for an hour // The endpoint is then locked for an hour
userReset = new ExpressBrute(store, userReset = function userReset() {
var ExpressBrute = require('express-brute'),
BruteKnex = require('brute-knex'),
db = require('../../data/db');
store = store || new BruteKnex({
tablename: 'brute',
createTable: false,
knex: db.knex
});
userResetInstance = userResetInstance || new ExpressBrute(store,
_.extend({ _.extend({
attachResetToRequest: true, attachResetToRequest: true,
failCallback: function (req, res, next, nextValidRequestDate) { failCallback: function (req, res, next, nextValidRequestDate) {
@ -114,9 +169,23 @@ userReset = new ExpressBrute(store,
}, _.pick(spamUserReset, spamConfigKeys)) }, _.pick(spamUserReset, spamConfigKeys))
); );
return userResetInstance;
};
// This protects a private blog from spam attacks. The defaults here allow 10 attempts per IP per hour // This protects a private blog from spam attacks. The defaults here allow 10 attempts per IP per hour
// The endpoint is then locked for an hour // The endpoint is then locked for an hour
privateBlog = new ExpressBrute(store, privateBlog = function privateBlog() {
var ExpressBrute = require('express-brute'),
BruteKnex = require('brute-knex'),
db = require('../../data/db');
store = store || new BruteKnex({
tablename: 'brute',
createTable: false,
knex: db.knex
});
privateBlogInstance = privateBlogInstance || new ExpressBrute(store,
_.extend({ _.extend({
attachResetToRequest: false, attachResetToRequest: false,
failCallback: function (req, res, next, nextValidRequestDate) { failCallback: function (req, res, next, nextValidRequestDate) {
@ -134,6 +203,9 @@ privateBlog = new ExpressBrute(store,
}, _.pick(spamPrivateBlog, spamConfigKeys)) }, _.pick(spamPrivateBlog, spamConfigKeys))
); );
return privateBlogInstance;
};
module.exports = { module.exports = {
globalBlock: globalBlock, globalBlock: globalBlock,
globalReset: globalReset, globalReset: globalReset,

View file

@ -9,26 +9,31 @@ module.exports = {
/** /**
* block per route per ip * block per route per ip
*/ */
globalBlock: spamPrevention.globalBlock.getMiddleware({ globalBlock: function (req, res, next) {
return spamPrevention.globalBlock().getMiddleware({
ignoreIP: false, ignoreIP: false,
key: function (req, res, next) { key: function (req, res, next) {
next(url.parse(req.url).pathname); next(url.parse(req.url).pathname);
} }
}), })(req, res, next);
},
/** /**
* block per route per ip * block per route per ip
*/ */
globalReset: spamPrevention.globalReset.getMiddleware({ globalReset: function (req, res, next) {
return spamPrevention.globalReset().getMiddleware({
ignoreIP: false, ignoreIP: false,
key: function (req, res, next) { key: function (req, res, next) {
next(url.parse(req.url).pathname); next(url.parse(req.url).pathname);
} }
}), })(req, res, next);
},
/** /**
* block per user * block per user
* username === email! * username === email!
*/ */
userLogin: spamPrevention.userLogin.getMiddleware({ userLogin: function (req, res, next) {
return spamPrevention.userLogin().getMiddleware({
ignoreIP: false, ignoreIP: false,
key: function (req, res, next) { key: function (req, res, next) {
if (req.body.username) { if (req.body.username) {
@ -45,20 +50,28 @@ module.exports = {
return next(); return next();
} }
}), })(req, res, next);
},
/** /**
* block per user * block per user
*/ */
userReset: spamPrevention.userReset.getMiddleware({ userReset: function (req, res, next) {
return spamPrevention.userReset().getMiddleware({
ignoreIP: false, ignoreIP: false,
key: function (req, res, next) { key: function (req, res, next) {
next(req.body.username + 'reset'); next(req.body.username + 'reset');
} }
}), })(req, res, next);
privateBlog: spamPrevention.privateBlog.getMiddleware({ },
/**
* block per ip
*/
privateBlog: function (req, res, next) {
return spamPrevention.privateBlog().getMiddleware({
ignoreIP: false, ignoreIP: false,
key: function (req, res, next) { key: function (req, res, next) {
next('privateblog'); next('privateblog');
} }
}) })(req, res, next);
}
}; };

View file

@ -1,6 +1,5 @@
var errors = require('../../errors'), var errors = require('../../errors'),
config = require('../../config'), config = require('../../config'),
ICO = require('icojs'),
fs = require('fs'), fs = require('fs'),
Promise = require('bluebird'), Promise = require('bluebird'),
sizeOf = require('image-size'), sizeOf = require('image-size'),
@ -15,7 +14,8 @@ validIconSize = function validIconSize(size) {
getIconDimensions = function getIconDimensions(icon) { getIconDimensions = function getIconDimensions(icon) {
return new Promise(function getImageSize(resolve, reject) { return new Promise(function getImageSize(resolve, reject) {
var arrayBuffer; var arrayBuffer,
ICO = require('icojs');
// image-size doesn't support .ico files // image-size doesn't support .ico files
if (icon.name.match(/.ico$/i)) { if (icon.name.match(/.ico$/i)) {

View file

@ -1,8 +1,8 @@
var archiver = require('archiver'), var fs = require('fs');
fs = require('fs');
module.exports = function zipFolder(folderToZip, destination, callback) { module.exports = function zipFolder(folderToZip, destination, callback) {
var output = fs.createWriteStream(destination), var archiver = require('archiver'),
output = fs.createWriteStream(destination),
archive = archiver.create('zip', {}); archive = archiver.create('zip', {});
output.on('close', function () { output.on('close', function () {
@ -17,4 +17,3 @@ module.exports = function zipFolder(folderToZip, destination, callback) {
archive.pipe(output); archive.pipe(output);
archive.finalize(); archive.finalize();
}; };

View file

@ -22,7 +22,7 @@ describe('OAuth', function () {
res = {}; res = {};
next = sandbox.spy(); next = sandbox.spy();
sandbox.stub(spamPrevention.userLogin, 'reset'); sandbox.stub(spamPrevention.userLogin(), 'reset');
}); });
afterEach(function () { afterEach(function () {
@ -80,7 +80,7 @@ describe('OAuth', function () {
json.should.have.property('expires_in'); json.should.have.property('expires_in');
json.should.have.property('token_type', 'Bearer'); json.should.have.property('token_type', 'Bearer');
next.called.should.eql(false); next.called.should.eql(false);
spamPrevention.userLogin.reset.called.should.eql(true); spamPrevention.userLogin().reset.called.should.eql(true);
done(); done();
} catch (err) { } catch (err) {
done(err); done(err);