mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 22:43:30 +03: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:
parent
e0cd5b55ce
commit
7556e68c48
@ -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({
|
||||
oldPassword: oldPassword,
|
||||
|
@ -8,19 +8,16 @@
|
||||
// there if available. The cacheId is a combination of `updated_at` and the `slug`.
|
||||
var hbs = require('express-hbs'),
|
||||
Promise = require('bluebird'),
|
||||
Amperize = require('amperize'),
|
||||
moment = require('moment'),
|
||||
sanitizeHtml = require('sanitize-html'),
|
||||
logging = require('../../../../logging'),
|
||||
i18n = require('../../../../i18n'),
|
||||
errors = require('../../../../errors'),
|
||||
makeAbsoluteUrl = require('../../../../utils/make-absolute-urls'),
|
||||
utils = require('../../../../utils'),
|
||||
cheerio = require('cheerio'),
|
||||
amperize = new Amperize(),
|
||||
amperizeCache = {},
|
||||
allowedAMPTags = [],
|
||||
allowedAMPAttributes = {},
|
||||
amperize,
|
||||
cleanHTML,
|
||||
ampHTML;
|
||||
|
||||
@ -120,6 +117,9 @@ function getAmperizeHTML(html, post) {
|
||||
return;
|
||||
}
|
||||
|
||||
var Amperize = require('amperize');
|
||||
amperize = amperize || new Amperize();
|
||||
|
||||
// make relative URLs abolute
|
||||
html = makeAbsoluteUrl(html, utils.url.urlFor('home', true), post.url).html();
|
||||
|
||||
@ -154,7 +154,9 @@ function getAmperizeHTML(html, post) {
|
||||
}
|
||||
|
||||
function ampContent() {
|
||||
var amperizeHTML = {
|
||||
var sanitizeHtml = require('sanitize-html'),
|
||||
cheerio = require('cheerio'),
|
||||
amperizeHTML = {
|
||||
amperize: getAmperizeHTML(this.html, this)
|
||||
};
|
||||
|
||||
|
@ -17,7 +17,7 @@ function exchangeRefreshToken(client, refreshToken, scope, body, authInfo, done)
|
||||
var token = model.toJSON();
|
||||
|
||||
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({
|
||||
clientId: token.client_id,
|
||||
@ -54,7 +54,7 @@ function exchangePassword(client, username, password, scope, body, authInfo, don
|
||||
});
|
||||
})
|
||||
.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});
|
||||
});
|
||||
})
|
||||
@ -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({
|
||||
clientId: req.client.id,
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Handles sending email for Ghost
|
||||
var _ = require('lodash'),
|
||||
Promise = require('bluebird'),
|
||||
nodemailer = require('nodemailer'),
|
||||
validator = require('validator'),
|
||||
config = require('../config'),
|
||||
settingsCache = require('../settings/cache'),
|
||||
@ -10,13 +9,12 @@ var _ = require('lodash'),
|
||||
utils = require('../utils');
|
||||
|
||||
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) || {};
|
||||
|
||||
this.state = {};
|
||||
|
||||
this.transport = nodemailer.createTransport(transport, options);
|
||||
|
||||
this.state.usingDirect = transport === 'direct';
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,4 @@
|
||||
var ExpressBrute = require('express-brute'),
|
||||
BruteKnex = require('brute-knex'),
|
||||
knexInstance = require('../../data/db/connection'),
|
||||
store = new BruteKnex({tablename: 'brute', createTable:false, knex: knexInstance}),
|
||||
moment = require('moment'),
|
||||
var moment = require('moment'),
|
||||
errors = require('../../errors'),
|
||||
config = require('../../config'),
|
||||
spam = config.get('spam') || {},
|
||||
@ -14,9 +10,15 @@ var ExpressBrute = require('express-brute'),
|
||||
spamUserLogin = spam.user_login || {},
|
||||
|
||||
i18n = require('../../i18n'),
|
||||
store,
|
||||
handleStoreError,
|
||||
globalBlock,
|
||||
globalReset,
|
||||
privateBlogInstance,
|
||||
globalResetInstance,
|
||||
globalBlockInstance,
|
||||
userLoginInstance,
|
||||
userResetInstance,
|
||||
privateBlog,
|
||||
userLogin,
|
||||
userReset,
|
||||
@ -46,93 +48,163 @@ handleStoreError = function handleStoreError(err) {
|
||||
// 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
|
||||
// Defaults to 50 attempts per hour and locks the endpoint for an hour
|
||||
globalBlock = new ExpressBrute(store,
|
||||
_.extend({
|
||||
attachResetToRequest: false,
|
||||
failCallback: function (req, res, next, nextValidRequestDate) {
|
||||
return next(new errors.TooManyRequestsError({
|
||||
message: 'Too many attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
|
||||
context: i18n.t('errors.middleware.spamprevention.forgottenPasswordIp.error',
|
||||
{rfa: spamGlobalBlock.freeRetries + 1 || 5, rfp: spamGlobalBlock.lifetime || 60 * 60}),
|
||||
help: i18n.t('errors.middleware.spamprevention.tooManyAttempts')
|
||||
}));
|
||||
},
|
||||
handleStoreError: handleStoreError
|
||||
}, _.pick(spamGlobalBlock, spamConfigKeys))
|
||||
);
|
||||
globalBlock = function globalBlock() {
|
||||
var ExpressBrute = require('express-brute'),
|
||||
BruteKnex = require('brute-knex'),
|
||||
db = require('../../data/db');
|
||||
|
||||
globalReset = new ExpressBrute(store,
|
||||
_.extend({
|
||||
attachResetToRequest: false,
|
||||
failCallback: function (req, res, next, nextValidRequestDate) {
|
||||
// TODO use i18n again
|
||||
return next(new errors.TooManyRequestsError({
|
||||
message: 'Too many attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
|
||||
context: i18n.t('errors.middleware.spamprevention.forgottenPasswordIp.error',
|
||||
{rfa: spamGlobalReset.freeRetries + 1 || 5, rfp: spamGlobalReset.lifetime || 60 * 60}),
|
||||
help: i18n.t('errors.middleware.spamprevention.forgottenPasswordIp.context')
|
||||
}));
|
||||
},
|
||||
handleStoreError: handleStoreError
|
||||
}, _.pick(spamGlobalReset, spamConfigKeys))
|
||||
);
|
||||
store = store || new BruteKnex({
|
||||
tablename: 'brute',
|
||||
createTable: false,
|
||||
knex: db.knex
|
||||
});
|
||||
|
||||
globalBlockInstance = globalBlockInstance || new ExpressBrute(store,
|
||||
_.extend({
|
||||
attachResetToRequest: false,
|
||||
failCallback: function (req, res, next, nextValidRequestDate) {
|
||||
return next(new errors.TooManyRequestsError({
|
||||
message: 'Too many attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
|
||||
context: i18n.t('errors.middleware.spamprevention.forgottenPasswordIp.error',
|
||||
{rfa: spamGlobalBlock.freeRetries + 1 || 5, rfp: spamGlobalBlock.lifetime || 60 * 60}),
|
||||
help: i18n.t('errors.middleware.spamprevention.tooManyAttempts')
|
||||
}));
|
||||
},
|
||||
handleStoreError: handleStoreError
|
||||
}, _.pick(spamGlobalBlock, spamConfigKeys))
|
||||
);
|
||||
|
||||
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({
|
||||
attachResetToRequest: false,
|
||||
failCallback: function (req, res, next, nextValidRequestDate) {
|
||||
// TODO use i18n again
|
||||
return next(new errors.TooManyRequestsError({
|
||||
message: 'Too many attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
|
||||
context: i18n.t('errors.middleware.spamprevention.forgottenPasswordIp.error',
|
||||
{rfa: spamGlobalReset.freeRetries + 1 || 5, rfp: spamGlobalReset.lifetime || 60 * 60}),
|
||||
help: i18n.t('errors.middleware.spamprevention.forgottenPasswordIp.context')
|
||||
}));
|
||||
},
|
||||
handleStoreError: handleStoreError
|
||||
}, _.pick(spamGlobalReset, spamConfigKeys))
|
||||
);
|
||||
|
||||
return globalResetInstance;
|
||||
};
|
||||
|
||||
// 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
|
||||
// The user+IP count is reset when on successful login
|
||||
// Default value of 5 attempts per user+IP pair
|
||||
userLogin = new ExpressBrute(store,
|
||||
_.extend({
|
||||
attachResetToRequest: true,
|
||||
failCallback: function (req, res, next, nextValidRequestDate) {
|
||||
return next(new errors.TooManyRequestsError({
|
||||
message: 'Too many sign-in attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
|
||||
// TODO add more options to i18n
|
||||
context: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.context'),
|
||||
help: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.context')
|
||||
}));
|
||||
},
|
||||
handleStoreError: handleStoreError
|
||||
}, _.pick(spamUserLogin, spamConfigKeys))
|
||||
);
|
||||
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({
|
||||
attachResetToRequest: true,
|
||||
failCallback: function (req, res, next, nextValidRequestDate) {
|
||||
return next(new errors.TooManyRequestsError({
|
||||
message: 'Too many sign-in attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
|
||||
// TODO add more options to i18n
|
||||
context: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.context'),
|
||||
help: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.context')
|
||||
}));
|
||||
},
|
||||
handleStoreError: handleStoreError
|
||||
}, _.pick(spamUserLogin, spamConfigKeys))
|
||||
);
|
||||
|
||||
return userLoginInstance;
|
||||
};
|
||||
|
||||
// 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
|
||||
// The endpoint is then locked for an hour
|
||||
userReset = new ExpressBrute(store,
|
||||
_.extend({
|
||||
attachResetToRequest: true,
|
||||
failCallback: function (req, res, next, nextValidRequestDate) {
|
||||
return next(new errors.TooManyRequestsError({
|
||||
message: 'Too many password reset attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
|
||||
context: i18n.t('errors.middleware.spamprevention.forgottenPasswordEmail.error',
|
||||
{rfa: spamUserReset.freeRetries + 1 || 5, rfp: spamUserReset.lifetime || 60 * 60}),
|
||||
help: i18n.t('errors.middleware.spamprevention.forgottenPasswordEmail.context')
|
||||
}));
|
||||
},
|
||||
handleStoreError: handleStoreError
|
||||
}, _.pick(spamUserReset, spamConfigKeys))
|
||||
);
|
||||
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({
|
||||
attachResetToRequest: true,
|
||||
failCallback: function (req, res, next, nextValidRequestDate) {
|
||||
return next(new errors.TooManyRequestsError({
|
||||
message: 'Too many password reset attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
|
||||
context: i18n.t('errors.middleware.spamprevention.forgottenPasswordEmail.error',
|
||||
{rfa: spamUserReset.freeRetries + 1 || 5, rfp: spamUserReset.lifetime || 60 * 60}),
|
||||
help: i18n.t('errors.middleware.spamprevention.forgottenPasswordEmail.context')
|
||||
}));
|
||||
},
|
||||
handleStoreError: handleStoreError
|
||||
}, _.pick(spamUserReset, spamConfigKeys))
|
||||
);
|
||||
|
||||
return userResetInstance;
|
||||
};
|
||||
|
||||
// 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
|
||||
privateBlog = new ExpressBrute(store,
|
||||
_.extend({
|
||||
attachResetToRequest: false,
|
||||
failCallback: function (req, res, next, nextValidRequestDate) {
|
||||
logging.error(new errors.GhostError({
|
||||
message: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.error',
|
||||
{rfa: spamPrivateBlog.freeRetries + 1 || 5, rfp: spamPrivateBlog.lifetime || 60 * 60}),
|
||||
context: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.context')
|
||||
}));
|
||||
privateBlog = function privateBlog() {
|
||||
var ExpressBrute = require('express-brute'),
|
||||
BruteKnex = require('brute-knex'),
|
||||
db = require('../../data/db');
|
||||
|
||||
return next(new errors.GhostError({
|
||||
message: 'Too many private sign-in attempts try again in ' + moment(nextValidRequestDate).fromNow(true)
|
||||
}));
|
||||
},
|
||||
handleStoreError: handleStoreError
|
||||
}, _.pick(spamPrivateBlog, spamConfigKeys))
|
||||
);
|
||||
store = store || new BruteKnex({
|
||||
tablename: 'brute',
|
||||
createTable: false,
|
||||
knex: db.knex
|
||||
});
|
||||
|
||||
privateBlogInstance = privateBlogInstance || new ExpressBrute(store,
|
||||
_.extend({
|
||||
attachResetToRequest: false,
|
||||
failCallback: function (req, res, next, nextValidRequestDate) {
|
||||
logging.error(new errors.GhostError({
|
||||
message: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.error',
|
||||
{rfa: spamPrivateBlog.freeRetries + 1 || 5, rfp: spamPrivateBlog.lifetime || 60 * 60}),
|
||||
context: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.context')
|
||||
}));
|
||||
|
||||
return next(new errors.GhostError({
|
||||
message: 'Too many private sign-in attempts try again in ' + moment(nextValidRequestDate).fromNow(true)
|
||||
}));
|
||||
},
|
||||
handleStoreError: handleStoreError
|
||||
}, _.pick(spamPrivateBlog, spamConfigKeys))
|
||||
);
|
||||
|
||||
return privateBlogInstance;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
globalBlock: globalBlock,
|
||||
|
@ -9,56 +9,69 @@ module.exports = {
|
||||
/**
|
||||
* block per route per ip
|
||||
*/
|
||||
globalBlock: spamPrevention.globalBlock.getMiddleware({
|
||||
ignoreIP: false,
|
||||
key: function (req, res, next) {
|
||||
next(url.parse(req.url).pathname);
|
||||
}
|
||||
}),
|
||||
globalBlock: function (req, res, next) {
|
||||
return spamPrevention.globalBlock().getMiddleware({
|
||||
ignoreIP: false,
|
||||
key: function (req, res, next) {
|
||||
next(url.parse(req.url).pathname);
|
||||
}
|
||||
})(req, res, next);
|
||||
},
|
||||
/**
|
||||
* block per route per ip
|
||||
*/
|
||||
globalReset: spamPrevention.globalReset.getMiddleware({
|
||||
ignoreIP: false,
|
||||
key: function (req, res, next) {
|
||||
next(url.parse(req.url).pathname);
|
||||
}
|
||||
}),
|
||||
globalReset: function (req, res, next) {
|
||||
return spamPrevention.globalReset().getMiddleware({
|
||||
ignoreIP: false,
|
||||
key: function (req, res, next) {
|
||||
next(url.parse(req.url).pathname);
|
||||
}
|
||||
})(req, res, next);
|
||||
},
|
||||
/**
|
||||
* block per user
|
||||
* username === email!
|
||||
*/
|
||||
userLogin: spamPrevention.userLogin.getMiddleware({
|
||||
ignoreIP: false,
|
||||
key: function (req, res, next) {
|
||||
if (req.body.username) {
|
||||
return next(req.body.username + 'login');
|
||||
}
|
||||
userLogin: function (req, res, next) {
|
||||
return spamPrevention.userLogin().getMiddleware({
|
||||
ignoreIP: false,
|
||||
key: function (req, res, next) {
|
||||
if (req.body.username) {
|
||||
return next(req.body.username + 'login');
|
||||
}
|
||||
|
||||
if (req.body.authorizationCode) {
|
||||
return next(req.body.authorizationCode + 'login');
|
||||
}
|
||||
if (req.body.authorizationCode) {
|
||||
return next(req.body.authorizationCode + 'login');
|
||||
}
|
||||
|
||||
if (req.body.refresh_token) {
|
||||
return next(req.body.refresh_token + 'login');
|
||||
}
|
||||
if (req.body.refresh_token) {
|
||||
return next(req.body.refresh_token + 'login');
|
||||
}
|
||||
|
||||
return next();
|
||||
}
|
||||
}),
|
||||
return next();
|
||||
}
|
||||
})(req, res, next);
|
||||
},
|
||||
/**
|
||||
* block per user
|
||||
*/
|
||||
userReset: spamPrevention.userReset.getMiddleware({
|
||||
ignoreIP: false,
|
||||
key: function (req, res, next) {
|
||||
next(req.body.username + 'reset');
|
||||
}
|
||||
}),
|
||||
privateBlog: spamPrevention.privateBlog.getMiddleware({
|
||||
ignoreIP: false,
|
||||
key: function (req, res, next) {
|
||||
next('privateblog');
|
||||
}
|
||||
})
|
||||
userReset: function (req, res, next) {
|
||||
return spamPrevention.userReset().getMiddleware({
|
||||
ignoreIP: false,
|
||||
key: function (req, res, next) {
|
||||
next(req.body.username + 'reset');
|
||||
}
|
||||
})(req, res, next);
|
||||
},
|
||||
/**
|
||||
* block per ip
|
||||
*/
|
||||
privateBlog: function (req, res, next) {
|
||||
return spamPrevention.privateBlog().getMiddleware({
|
||||
ignoreIP: false,
|
||||
key: function (req, res, next) {
|
||||
next('privateblog');
|
||||
}
|
||||
})(req, res, next);
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,5 @@
|
||||
var errors = require('../../errors'),
|
||||
config = require('../../config'),
|
||||
ICO = require('icojs'),
|
||||
fs = require('fs'),
|
||||
Promise = require('bluebird'),
|
||||
sizeOf = require('image-size'),
|
||||
@ -15,7 +14,8 @@ validIconSize = function validIconSize(size) {
|
||||
|
||||
getIconDimensions = function getIconDimensions(icon) {
|
||||
return new Promise(function getImageSize(resolve, reject) {
|
||||
var arrayBuffer;
|
||||
var arrayBuffer,
|
||||
ICO = require('icojs');
|
||||
|
||||
// image-size doesn't support .ico files
|
||||
if (icon.name.match(/.ico$/i)) {
|
||||
|
@ -1,8 +1,8 @@
|
||||
var archiver = require('archiver'),
|
||||
fs = require('fs');
|
||||
var fs = require('fs');
|
||||
|
||||
module.exports = function zipFolder(folderToZip, destination, callback) {
|
||||
var output = fs.createWriteStream(destination),
|
||||
var archiver = require('archiver'),
|
||||
output = fs.createWriteStream(destination),
|
||||
archive = archiver.create('zip', {});
|
||||
|
||||
output.on('close', function () {
|
||||
@ -17,4 +17,3 @@ module.exports = function zipFolder(folderToZip, destination, callback) {
|
||||
archive.pipe(output);
|
||||
archive.finalize();
|
||||
};
|
||||
|
||||
|
@ -22,7 +22,7 @@ describe('OAuth', function () {
|
||||
res = {};
|
||||
next = sandbox.spy();
|
||||
|
||||
sandbox.stub(spamPrevention.userLogin, 'reset');
|
||||
sandbox.stub(spamPrevention.userLogin(), 'reset');
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
@ -80,7 +80,7 @@ describe('OAuth', function () {
|
||||
json.should.have.property('expires_in');
|
||||
json.should.have.property('token_type', 'Bearer');
|
||||
next.called.should.eql(false);
|
||||
spamPrevention.userLogin.reset.called.should.eql(true);
|
||||
spamPrevention.userLogin().reset.called.should.eql(true);
|
||||
done();
|
||||
} catch (err) {
|
||||
done(err);
|
||||
|
Loading…
Reference in New Issue
Block a user