mirror of
https://github.com/TryGhost/Ghost.git
synced 2023-12-13 21:00:40 +01:00
Refactor common pattern in service files
- Use array destructuring - Use @tryghost/errors - Part of the big move towards decoupling, this gives visibility on what's being used where - Biting off manageable chunks / fixing bits of code I'm refactoring for other reasons
This commit is contained in:
parent
c70c49258e
commit
baa8118893
32 changed files with 224 additions and 208 deletions
|
@ -1,7 +1,7 @@
|
||||||
// ## Server Loader
|
// ## Server Loader
|
||||||
// Passes options through the boot process to get a server instance back
|
// Passes options through the boot process to get a server instance back
|
||||||
const server = require('./server');
|
const server = require('./server');
|
||||||
const common = require('./server/lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
const GhostServer = require('./server/ghost-server');
|
const GhostServer = require('./server/ghost-server');
|
||||||
|
|
||||||
// Set the default environment to be `development`
|
// Set the default environment to be `development`
|
||||||
|
@ -12,8 +12,8 @@ function makeGhost(options) {
|
||||||
|
|
||||||
return server(options)
|
return server(options)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (!common.errors.utils.isIgnitionError(err)) {
|
if (!errors.utils.isIgnitionError(err)) {
|
||||||
err = new common.errors.GhostError({message: err.message, err: err});
|
err = new errors.GhostError({message: err.message, err: err});
|
||||||
}
|
}
|
||||||
|
|
||||||
return GhostServer.announceServerStopped(err)
|
return GhostServer.announceServerStopped(err)
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const Analytics = require('analytics-node');
|
const Analytics = require('analytics-node');
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
const common = require('./lib/common');
|
const {events} = require('./lib/common');
|
||||||
let analytics;
|
|
||||||
|
|
||||||
module.exports.init = function () {
|
module.exports.init = function () {
|
||||||
analytics = new Analytics(config.get('segment:key'));
|
const analytics = new Analytics(config.get('segment:key'));
|
||||||
let toTrack;
|
|
||||||
const trackDefaults = config.get('segment:trackDefaults') || {};
|
const trackDefaults = config.get('segment:trackDefaults') || {};
|
||||||
const prefix = config.get('segment:prefix') || '';
|
const prefix = config.get('segment:prefix') || '';
|
||||||
|
|
||||||
toTrack = [
|
const toTrack = [
|
||||||
{
|
{
|
||||||
event: 'post.published',
|
event: 'post.published',
|
||||||
name: 'Post Published'
|
name: 'Post Published'
|
||||||
|
@ -30,7 +28,7 @@ module.exports.init = function () {
|
||||||
];
|
];
|
||||||
|
|
||||||
_.each(toTrack, function (track) {
|
_.each(toTrack, function (track) {
|
||||||
common.events.on(track.event, function () {
|
events.on(track.event, function () {
|
||||||
analytics.track(_.extend(trackDefaults, {event: prefix + track.name}));
|
analytics.track(_.extend(trackDefaults, {event: prefix + track.name}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,8 @@ const path = require('path');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
const urlUtils = require('./lib/url-utils');
|
const urlUtils = require('./lib/url-utils');
|
||||||
const common = require('./lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {events, i18n, logging} = require('./lib/common');
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,16 +87,16 @@ GhostServer.prototype.start = function (externalApp) {
|
||||||
let ghostError;
|
let ghostError;
|
||||||
|
|
||||||
if (error.errno === 'EADDRINUSE') {
|
if (error.errno === 'EADDRINUSE') {
|
||||||
ghostError = new common.errors.GhostError({
|
ghostError = new errors.GhostError({
|
||||||
message: common.i18n.t('errors.httpServer.addressInUse.error'),
|
message: i18n.t('errors.httpServer.addressInUse.error'),
|
||||||
context: common.i18n.t('errors.httpServer.addressInUse.context', {port: config.get('server').port}),
|
context: i18n.t('errors.httpServer.addressInUse.context', {port: config.get('server').port}),
|
||||||
help: common.i18n.t('errors.httpServer.addressInUse.help')
|
help: i18n.t('errors.httpServer.addressInUse.help')
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
ghostError = new common.errors.GhostError({
|
ghostError = new errors.GhostError({
|
||||||
message: common.i18n.t('errors.httpServer.otherError.error', {errorNumber: error.errno}),
|
message: i18n.t('errors.httpServer.otherError.error', {errorNumber: error.errno}),
|
||||||
context: common.i18n.t('errors.httpServer.otherError.context'),
|
context: i18n.t('errors.httpServer.otherError.context'),
|
||||||
help: common.i18n.t('errors.httpServer.otherError.help')
|
help: i18n.t('errors.httpServer.otherError.help')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +129,7 @@ GhostServer.prototype.stop = function () {
|
||||||
resolve(self);
|
resolve(self);
|
||||||
} else {
|
} else {
|
||||||
self.httpServer.close(function () {
|
self.httpServer.close(function () {
|
||||||
common.events.emit('server.stop');
|
events.emit('server.stop');
|
||||||
self.httpServer = null;
|
self.httpServer = null;
|
||||||
self.logShutdownMessages();
|
self.logShutdownMessages();
|
||||||
resolve(self);
|
resolve(self);
|
||||||
|
@ -155,7 +156,7 @@ GhostServer.prototype.restart = function () {
|
||||||
* To be called after `stop`
|
* To be called after `stop`
|
||||||
*/
|
*/
|
||||||
GhostServer.prototype.hammertime = function () {
|
GhostServer.prototype.hammertime = function () {
|
||||||
common.logging.info(common.i18n.t('notices.httpServer.cantTouchThis'));
|
logging.info(i18n.t('notices.httpServer.cantTouchThis'));
|
||||||
|
|
||||||
return Promise.resolve(this);
|
return Promise.resolve(this);
|
||||||
};
|
};
|
||||||
|
@ -202,27 +203,27 @@ GhostServer.prototype.closeConnections = function () {
|
||||||
GhostServer.prototype.logStartMessages = function () {
|
GhostServer.prototype.logStartMessages = function () {
|
||||||
// Startup & Shutdown messages
|
// Startup & Shutdown messages
|
||||||
if (config.get('env') === 'production') {
|
if (config.get('env') === 'production') {
|
||||||
common.logging.info(common.i18n.t('notices.httpServer.ghostIsRunningIn', {env: config.get('env')}));
|
logging.info(i18n.t('notices.httpServer.ghostIsRunningIn', {env: config.get('env')}));
|
||||||
common.logging.info(common.i18n.t('notices.httpServer.yourBlogIsAvailableOn', {url: urlUtils.urlFor('home', true)}));
|
logging.info(i18n.t('notices.httpServer.yourBlogIsAvailableOn', {url: urlUtils.urlFor('home', true)}));
|
||||||
common.logging.info(common.i18n.t('notices.httpServer.ctrlCToShutDown'));
|
logging.info(i18n.t('notices.httpServer.ctrlCToShutDown'));
|
||||||
} else {
|
} else {
|
||||||
common.logging.info(common.i18n.t('notices.httpServer.ghostIsRunningIn', {env: config.get('env')}));
|
logging.info(i18n.t('notices.httpServer.ghostIsRunningIn', {env: config.get('env')}));
|
||||||
common.logging.info(common.i18n.t('notices.httpServer.listeningOn', {
|
logging.info(i18n.t('notices.httpServer.listeningOn', {
|
||||||
host: config.get('server').socket || config.get('server').host,
|
host: config.get('server').socket || config.get('server').host,
|
||||||
port: config.get('server').port
|
port: config.get('server').port
|
||||||
}));
|
}));
|
||||||
common.logging.info(common.i18n.t('notices.httpServer.urlConfiguredAs', {url: urlUtils.urlFor('home', true)}));
|
logging.info(i18n.t('notices.httpServer.urlConfiguredAs', {url: urlUtils.urlFor('home', true)}));
|
||||||
common.logging.info(common.i18n.t('notices.httpServer.ctrlCToShutDown'));
|
logging.info(i18n.t('notices.httpServer.ctrlCToShutDown'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function shutdown() {
|
function shutdown() {
|
||||||
common.logging.warn(common.i18n.t('notices.httpServer.ghostHasShutdown'));
|
logging.warn(i18n.t('notices.httpServer.ghostHasShutdown'));
|
||||||
|
|
||||||
if (config.get('env') === 'production') {
|
if (config.get('env') === 'production') {
|
||||||
common.logging.warn(common.i18n.t('notices.httpServer.yourBlogIsNowOffline'));
|
logging.warn(i18n.t('notices.httpServer.yourBlogIsNowOffline'));
|
||||||
} else {
|
} else {
|
||||||
common.logging.warn(
|
logging.warn(
|
||||||
common.i18n.t('notices.httpServer.ghostWasRunningFor'),
|
i18n.t('notices.httpServer.ghostWasRunningFor'),
|
||||||
moment.duration(process.uptime(), 'seconds').humanize()
|
moment.duration(process.uptime(), 'seconds').humanize()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -238,7 +239,7 @@ GhostServer.prototype.logStartMessages = function () {
|
||||||
* ### Log Shutdown Messages
|
* ### Log Shutdown Messages
|
||||||
*/
|
*/
|
||||||
GhostServer.prototype.logShutdownMessages = function () {
|
GhostServer.prototype.logShutdownMessages = function () {
|
||||||
common.logging.warn(common.i18n.t('notices.httpServer.ghostIsClosingConnections'));
|
logging.warn(i18n.t('notices.httpServer.ghostIsClosingConnections'));
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = GhostServer;
|
module.exports = GhostServer;
|
||||||
|
@ -253,7 +254,7 @@ const connectToBootstrapSocket = (message) => {
|
||||||
let wasResolved = false;
|
let wasResolved = false;
|
||||||
|
|
||||||
const waitTimeout = setTimeout(() => {
|
const waitTimeout = setTimeout(() => {
|
||||||
common.logging.info('Bootstrap socket timed out.');
|
logging.info('Bootstrap socket timed out.');
|
||||||
|
|
||||||
if (!client.destroyed) {
|
if (!client.destroyed) {
|
||||||
client.destroy();
|
client.destroy();
|
||||||
|
@ -283,7 +284,7 @@ const connectToBootstrapSocket = (message) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('close', () => {
|
client.on('close', () => {
|
||||||
common.logging.info('Bootstrap client was closed.');
|
logging.info('Bootstrap client was closed.');
|
||||||
|
|
||||||
if (waitTimeout) {
|
if (waitTimeout) {
|
||||||
clearTimeout(waitTimeout);
|
clearTimeout(waitTimeout);
|
||||||
|
@ -291,7 +292,7 @@ const connectToBootstrapSocket = (message) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('error', (err) => {
|
client.on('error', (err) => {
|
||||||
common.logging.warn(`Can't connect to the bootstrap socket (${socketAddress.host} ${socketAddress.port}) ${err.code}`);
|
logging.warn(`Can't connect to the bootstrap socket (${socketAddress.host} ${socketAddress.port}) ${err.code}`);
|
||||||
|
|
||||||
client.removeAllListeners();
|
client.removeAllListeners();
|
||||||
|
|
||||||
|
@ -300,10 +301,10 @@ const connectToBootstrapSocket = (message) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.tries < 3) {
|
if (options.tries < 3) {
|
||||||
common.logging.warn(`Tries: ${options.tries}`);
|
logging.warn(`Tries: ${options.tries}`);
|
||||||
|
|
||||||
// retry
|
// retry
|
||||||
common.logging.warn('Retrying...');
|
logging.warn('Retrying...');
|
||||||
|
|
||||||
options.tries = options.tries + 1;
|
options.tries = options.tries + 1;
|
||||||
const retryTimeout = setTimeout(() => {
|
const retryTimeout = setTimeout(() => {
|
||||||
|
@ -338,7 +339,7 @@ module.exports.announceServerStart = function announceServerStart() {
|
||||||
}
|
}
|
||||||
announceServerStartCalled = true;
|
announceServerStartCalled = true;
|
||||||
|
|
||||||
common.events.emit('server.start');
|
events.emit('server.start');
|
||||||
|
|
||||||
// CASE: IPC communication to the CLI via child process.
|
// CASE: IPC communication to the CLI via child process.
|
||||||
if (process.send) {
|
if (process.send) {
|
||||||
|
|
|
@ -12,7 +12,7 @@ require('./overrides');
|
||||||
const debug = require('ghost-ignition').debug('boot:init');
|
const debug = require('ghost-ignition').debug('boot:init');
|
||||||
const Promise = require('bluebird');
|
const Promise = require('bluebird');
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
const common = require('./lib/common');
|
const {events, i18n, logging} = require('./lib/common');
|
||||||
const migrator = require('./data/db/migrator');
|
const migrator = require('./data/db/migrator');
|
||||||
const urlUtils = require('./lib/url-utils');
|
const urlUtils = require('./lib/url-utils');
|
||||||
let parentApp;
|
let parentApp;
|
||||||
|
@ -84,7 +84,7 @@ const minimalRequiredSetupToStartGhost = (dbState) => {
|
||||||
let ghostServer;
|
let ghostServer;
|
||||||
|
|
||||||
// Initialize Ghost core internationalization
|
// Initialize Ghost core internationalization
|
||||||
common.i18n.init();
|
i18n.init();
|
||||||
debug('Default i18n done for core');
|
debug('Default i18n done for core');
|
||||||
|
|
||||||
models.init();
|
models.init();
|
||||||
|
@ -113,7 +113,7 @@ const minimalRequiredSetupToStartGhost = (dbState) => {
|
||||||
|
|
||||||
// CASE: all good or db was just initialised
|
// CASE: all good or db was just initialised
|
||||||
if (dbState === 1 || dbState === 2) {
|
if (dbState === 1 || dbState === 2) {
|
||||||
common.events.emit('db.ready');
|
events.emit('db.ready');
|
||||||
|
|
||||||
return initialiseServices()
|
return initialiseServices()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -123,24 +123,24 @@ const minimalRequiredSetupToStartGhost = (dbState) => {
|
||||||
|
|
||||||
// CASE: migrations required, put blog into maintenance mode
|
// CASE: migrations required, put blog into maintenance mode
|
||||||
if (dbState === 4) {
|
if (dbState === 4) {
|
||||||
common.logging.info('Blog is in maintenance mode.');
|
logging.info('Blog is in maintenance mode.');
|
||||||
|
|
||||||
config.set('maintenance:enabled', true);
|
config.set('maintenance:enabled', true);
|
||||||
|
|
||||||
migrator.migrate()
|
migrator.migrate()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
common.events.emit('db.ready');
|
events.emit('db.ready');
|
||||||
return initialiseServices();
|
return initialiseServices();
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
config.set('maintenance:enabled', false);
|
config.set('maintenance:enabled', false);
|
||||||
common.logging.info('Blog is out of maintenance mode.');
|
logging.info('Blog is out of maintenance mode.');
|
||||||
return GhostServer.announceServerStart();
|
return GhostServer.announceServerStart();
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
return GhostServer.announceServerStopped(err)
|
return GhostServer.announceServerStopped(err)
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
common.logging.error(err);
|
logging.error(err);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
process.exit(-1);
|
process.exit(-1);
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
const Promise = require('bluebird');
|
const Promise = require('bluebird');
|
||||||
|
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
const common = require('../../common');
|
const {i18n} = require('../../common');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse package.json and validate it has
|
* Parse package.json and validate it has
|
||||||
|
@ -15,7 +15,7 @@ const common = require('../../common');
|
||||||
function parsePackageJson(path) {
|
function parsePackageJson(path) {
|
||||||
return fs.readFile(path)
|
return fs.readFile(path)
|
||||||
.catch(function () {
|
.catch(function () {
|
||||||
const err = new Error(common.i18n.t('errors.utils.parsepackagejson.couldNotReadPackage'));
|
const err = new Error(i18n.t('errors.utils.parsepackagejson.couldNotReadPackage'));
|
||||||
err.context = path;
|
err.context = path;
|
||||||
|
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
|
@ -31,18 +31,18 @@ function parsePackageJson(path) {
|
||||||
hasRequiredKeys = json.name && json.version;
|
hasRequiredKeys = json.name && json.version;
|
||||||
|
|
||||||
if (!hasRequiredKeys) {
|
if (!hasRequiredKeys) {
|
||||||
err = new Error(common.i18n.t('errors.utils.parsepackagejson.nameOrVersionMissing'));
|
err = new Error(i18n.t('errors.utils.parsepackagejson.nameOrVersionMissing'));
|
||||||
err.context = path;
|
err.context = path;
|
||||||
err.help = common.i18n.t('errors.utils.parsepackagejson.willBeRequired', {url: 'https://ghost.org/docs/api/handlebars-themes/'});
|
err.help = i18n.t('errors.utils.parsepackagejson.willBeRequired', {url: 'https://ghost.org/docs/api/handlebars-themes/'});
|
||||||
|
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
} catch (parseError) {
|
} catch (parseError) {
|
||||||
err = new Error(common.i18n.t('errors.utils.parsepackagejson.themeFileIsMalformed'));
|
err = new Error(i18n.t('errors.utils.parsepackagejson.themeFileIsMalformed'));
|
||||||
err.context = path;
|
err.context = path;
|
||||||
err.help = common.i18n.t('errors.utils.parsepackagejson.willBeRequired', {url: 'https://ghost.org/docs/api/handlebars-themes/'});
|
err.help = i18n.t('errors.utils.parsepackagejson.willBeRequired', {url: 'https://ghost.org/docs/api/handlebars-themes/'});
|
||||||
|
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ const _ = require('lodash');
|
||||||
const join = require('path').join;
|
const join = require('path').join;
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
const parsePackageJson = require('./parse');
|
const parsePackageJson = require('./parse');
|
||||||
const common = require('../../common');
|
const errors = require('@tryghost/errors');
|
||||||
const notAPackageRegex = /^\.|_messages|README.md|node_modules|bower_components/i;
|
const notAPackageRegex = /^\.|_messages|README.md|node_modules|bower_components/i;
|
||||||
const packageJSONPath = 'package.json';
|
const packageJSONPath = 'package.json';
|
||||||
let readPackage;
|
let readPackage;
|
||||||
|
@ -53,7 +53,7 @@ readPackage = function readPackage(packagePath, packageName) {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(function (err) {
|
.catch(function (err) {
|
||||||
return Promise.reject(new common.errors.NotFoundError({
|
return Promise.reject(new errors.NotFoundError({
|
||||||
message: 'Package not found',
|
message: 'Package not found',
|
||||||
err: err,
|
err: err,
|
||||||
help: 'path: ' + packagePath,
|
help: 'path: ' + packagePath,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const common = require('./common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {logging} = require('./common');
|
||||||
const config = require('../config');
|
const config = require('../config');
|
||||||
|
|
||||||
let cardFactory;
|
let cardFactory;
|
||||||
|
@ -49,7 +50,7 @@ module.exports = {
|
||||||
cards: this.cards,
|
cards: this.cards,
|
||||||
atoms: this.atoms,
|
atoms: this.atoms,
|
||||||
unknownCardHandler(args) {
|
unknownCardHandler(args) {
|
||||||
common.logging.error(new common.errors.InternalServerError({
|
logging.error(new errors.InternalServerError({
|
||||||
message: 'Mobiledoc card \'' + args.env.name + '\' not found.'
|
message: 'Mobiledoc card \'' + args.env.name + '\' not found.'
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -64,7 +65,7 @@ module.exports = {
|
||||||
return require('@tryghost/html-to-mobiledoc').toMobiledoc;
|
return require('@tryghost/html-to-mobiledoc').toMobiledoc;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return () => {
|
return () => {
|
||||||
throw new common.errors.InternalServerError({
|
throw new errors.InternalServerError({
|
||||||
message: 'Unable to convert from source HTML to Mobiledoc',
|
message: 'Unable to convert from source HTML to Mobiledoc',
|
||||||
context: 'The html-to-mobiledoc package was not installed',
|
context: 'The html-to-mobiledoc package was not installed',
|
||||||
help: 'Please review any errors from the install process by checking the Ghost logs',
|
help: 'Please review any errors from the install process by checking the Ghost logs',
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
const models = require('../../../models');
|
const models = require('../../../models');
|
||||||
const common = require('../../../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {i18n} = require('../../../lib/common');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
let JWT_OPTIONS = {
|
let JWT_OPTIONS = {
|
||||||
|
@ -42,8 +43,8 @@ const authenticate = (req, res, next) => {
|
||||||
const token = _extractTokenFromHeader(req.headers.authorization);
|
const token = _extractTokenFromHeader(req.headers.authorization);
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return next(new common.errors.UnauthorizedError({
|
return next(new errors.UnauthorizedError({
|
||||||
message: common.i18n.t('errors.middleware.auth.incorrectAuthHeaderFormat'),
|
message: i18n.t('errors.middleware.auth.incorrectAuthHeaderFormat'),
|
||||||
code: 'INVALID_AUTH_HEADER'
|
code: 'INVALID_AUTH_HEADER'
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -54,8 +55,8 @@ const authenticate = (req, res, next) => {
|
||||||
const authenticateWithUrl = (req, res, next) => {
|
const authenticateWithUrl = (req, res, next) => {
|
||||||
const token = _extractTokenFromUrl(req.originalUrl);
|
const token = _extractTokenFromUrl(req.originalUrl);
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return next(new common.errors.UnauthorizedError({
|
return next(new errors.UnauthorizedError({
|
||||||
message: common.i18n.t('errors.middleware.auth.invalidTokenWithMessage', {message: 'No token found in URL'}),
|
message: i18n.t('errors.middleware.auth.invalidTokenWithMessage', {message: 'No token found in URL'}),
|
||||||
code: 'INVALID_JWT'
|
code: 'INVALID_JWT'
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -81,8 +82,8 @@ const authenticateWithToken = (req, res, next, {token, JWT_OPTIONS}) => {
|
||||||
const decoded = jwt.decode(token, {complete: true});
|
const decoded = jwt.decode(token, {complete: true});
|
||||||
|
|
||||||
if (!decoded || !decoded.header) {
|
if (!decoded || !decoded.header) {
|
||||||
return next(new common.errors.BadRequestError({
|
return next(new errors.BadRequestError({
|
||||||
message: common.i18n.t('errors.middleware.auth.invalidToken'),
|
message: i18n.t('errors.middleware.auth.invalidToken'),
|
||||||
code: 'INVALID_JWT'
|
code: 'INVALID_JWT'
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -90,23 +91,23 @@ const authenticateWithToken = (req, res, next, {token, JWT_OPTIONS}) => {
|
||||||
const apiKeyId = decoded.header.kid;
|
const apiKeyId = decoded.header.kid;
|
||||||
|
|
||||||
if (!apiKeyId) {
|
if (!apiKeyId) {
|
||||||
return next(new common.errors.BadRequestError({
|
return next(new errors.BadRequestError({
|
||||||
message: common.i18n.t('errors.middleware.auth.adminApiKidMissing'),
|
message: i18n.t('errors.middleware.auth.adminApiKidMissing'),
|
||||||
code: 'MISSING_ADMIN_API_KID'
|
code: 'MISSING_ADMIN_API_KID'
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
models.ApiKey.findOne({id: apiKeyId}).then((apiKey) => {
|
models.ApiKey.findOne({id: apiKeyId}).then((apiKey) => {
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
return next(new common.errors.UnauthorizedError({
|
return next(new errors.UnauthorizedError({
|
||||||
message: common.i18n.t('errors.middleware.auth.unknownAdminApiKey'),
|
message: i18n.t('errors.middleware.auth.unknownAdminApiKey'),
|
||||||
code: 'UNKNOWN_ADMIN_API_KEY'
|
code: 'UNKNOWN_ADMIN_API_KEY'
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (apiKey.get('type') !== 'admin') {
|
if (apiKey.get('type') !== 'admin') {
|
||||||
return next(new common.errors.UnauthorizedError({
|
return next(new errors.UnauthorizedError({
|
||||||
message: common.i18n.t('errors.middleware.auth.invalidApiKeyType'),
|
message: i18n.t('errors.middleware.auth.invalidApiKeyType'),
|
||||||
code: 'INVALID_API_KEY_TYPE'
|
code: 'INVALID_API_KEY_TYPE'
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -129,22 +130,22 @@ const authenticateWithToken = (req, res, next, {token, JWT_OPTIONS}) => {
|
||||||
jwt.verify(token, secret, options);
|
jwt.verify(token, secret, options);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.name === 'TokenExpiredError' || err.name === 'JsonWebTokenError') {
|
if (err.name === 'TokenExpiredError' || err.name === 'JsonWebTokenError') {
|
||||||
return next(new common.errors.UnauthorizedError({
|
return next(new errors.UnauthorizedError({
|
||||||
message: common.i18n.t('errors.middleware.auth.invalidTokenWithMessage', {message: err.message}),
|
message: i18n.t('errors.middleware.auth.invalidTokenWithMessage', {message: err.message}),
|
||||||
code: 'INVALID_JWT',
|
code: 'INVALID_JWT',
|
||||||
err
|
err
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// unknown error
|
// unknown error
|
||||||
return next(new common.errors.InternalServerError({err}));
|
return next(new errors.InternalServerError({err}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// authenticated OK, store the api key on the request for later checks and logging
|
// authenticated OK, store the api key on the request for later checks and logging
|
||||||
req.api_key = apiKey;
|
req.api_key = apiKey;
|
||||||
next();
|
next();
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
next(new common.errors.InternalServerError({err}));
|
next(new errors.InternalServerError({err}));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const models = require('../../../models');
|
const models = require('../../../models');
|
||||||
const common = require('../../../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {i18n} = require('../../../lib/common');
|
||||||
|
|
||||||
const authenticateContentApiKey = function authenticateContentApiKey(req, res, next) {
|
const authenticateContentApiKey = function authenticateContentApiKey(req, res, next) {
|
||||||
// allow fallthrough to other auth methods or final ensureAuthenticated check
|
// allow fallthrough to other auth methods or final ensureAuthenticated check
|
||||||
|
@ -8,8 +9,8 @@ const authenticateContentApiKey = function authenticateContentApiKey(req, res, n
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.query.key.constructor === Array) {
|
if (req.query.key.constructor === Array) {
|
||||||
return next(new common.errors.BadRequestError({
|
return next(new errors.BadRequestError({
|
||||||
message: common.i18n.t('errors.middleware.auth.invalidRequest'),
|
message: i18n.t('errors.middleware.auth.invalidRequest'),
|
||||||
code: 'INVALID_REQUEST'
|
code: 'INVALID_REQUEST'
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -18,15 +19,15 @@ const authenticateContentApiKey = function authenticateContentApiKey(req, res, n
|
||||||
|
|
||||||
models.ApiKey.findOne({secret: key}).then((apiKey) => {
|
models.ApiKey.findOne({secret: key}).then((apiKey) => {
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
return next(new common.errors.UnauthorizedError({
|
return next(new errors.UnauthorizedError({
|
||||||
message: common.i18n.t('errors.middleware.auth.unknownContentApiKey'),
|
message: i18n.t('errors.middleware.auth.unknownContentApiKey'),
|
||||||
code: 'UNKNOWN_CONTENT_API_KEY'
|
code: 'UNKNOWN_CONTENT_API_KEY'
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (apiKey.get('type') !== 'content') {
|
if (apiKey.get('type') !== 'content') {
|
||||||
return next(new common.errors.UnauthorizedError({
|
return next(new errors.UnauthorizedError({
|
||||||
message: common.i18n.t('errors.middleware.auth.invalidApiKeyType'),
|
message: i18n.t('errors.middleware.auth.invalidApiKeyType'),
|
||||||
code: 'INVALID_API_KEY_TYPE'
|
code: 'INVALID_API_KEY_TYPE'
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -35,7 +36,7 @@ const authenticateContentApiKey = function authenticateContentApiKey(req, res, n
|
||||||
req.api_key = apiKey;
|
req.api_key = apiKey;
|
||||||
next();
|
next();
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
next(new common.errors.InternalServerError({err}));
|
next(new errors.InternalServerError({err}));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const labs = require('../labs');
|
const labs = require('../labs');
|
||||||
const common = require('../../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {i18n} = require('../../lib/common');
|
||||||
|
|
||||||
const authorize = {
|
const authorize = {
|
||||||
authorizeContentApi(req, res, next) {
|
authorizeContentApi(req, res, next) {
|
||||||
|
@ -11,9 +12,9 @@ const authorize = {
|
||||||
if (labs.isSet('members') && hasMember) {
|
if (labs.isSet('members') && hasMember) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
return next(new common.errors.NoPermissionError({
|
return next(new errors.NoPermissionError({
|
||||||
message: common.i18n.t('errors.middleware.auth.authorizationFailed'),
|
message: i18n.t('errors.middleware.auth.authorizationFailed'),
|
||||||
context: common.i18n.t('errors.middleware.auth.missingContentMemberOrIntegration')
|
context: i18n.t('errors.middleware.auth.missingContentMemberOrIntegration')
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -24,9 +25,9 @@ const authorize = {
|
||||||
if (hasUser || hasApiKey) {
|
if (hasUser || hasApiKey) {
|
||||||
return next();
|
return next();
|
||||||
} else {
|
} else {
|
||||||
return next(new common.errors.NoPermissionError({
|
return next(new errors.NoPermissionError({
|
||||||
message: common.i18n.t('errors.middleware.auth.authorizationFailed'),
|
message: i18n.t('errors.middleware.auth.authorizationFailed'),
|
||||||
context: common.i18n.t('errors.middleware.auth.missingAdminUserOrIntegration')
|
context: i18n.t('errors.middleware.auth.missingAdminUserOrIntegration')
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const security = require('../../lib/security');
|
const security = require('../../lib/security');
|
||||||
const constants = require('../../lib/constants');
|
const constants = require('../../lib/constants');
|
||||||
const common = require('../../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {i18n} = require('../../lib/common');
|
||||||
const models = require('../../models');
|
const models = require('../../models');
|
||||||
const urlUtils = require('../../lib/url-utils');
|
const urlUtils = require('../../lib/url-utils');
|
||||||
const mail = require('../mail');
|
const mail = require('../mail');
|
||||||
|
@ -21,7 +22,7 @@ function generateToken(email, settingsAPI) {
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new common.errors.NotFoundError({message: common.i18n.t('errors.api.users.userNotFound')});
|
throw new errors.NotFoundError({message: i18n.t('errors.api.users.userNotFound')});
|
||||||
}
|
}
|
||||||
|
|
||||||
token = security.tokens.resetToken.generateHash({
|
token = security.tokens.resetToken.generateHash({
|
||||||
|
@ -46,8 +47,8 @@ function extractTokenParts(options) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!tokenParts) {
|
if (!tokenParts) {
|
||||||
return Promise.reject(new common.errors.UnauthorizedError({
|
return Promise.reject(new errors.UnauthorizedError({
|
||||||
message: common.i18n.t('errors.api.common.invalidTokenStructure')
|
message: i18n.t('errors.api.common.invalidTokenStructure')
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,8 +59,8 @@ function extractTokenParts(options) {
|
||||||
function protectBruteForce({options, tokenParts}) {
|
function protectBruteForce({options, tokenParts}) {
|
||||||
if (tokenSecurity[`${tokenParts.email}+${tokenParts.expires}`] &&
|
if (tokenSecurity[`${tokenParts.email}+${tokenParts.expires}`] &&
|
||||||
tokenSecurity[`${tokenParts.email}+${tokenParts.expires}`].count >= 10) {
|
tokenSecurity[`${tokenParts.email}+${tokenParts.expires}`].count >= 10) {
|
||||||
return Promise.reject(new common.errors.NoPermissionError({
|
return Promise.reject(new errors.NoPermissionError({
|
||||||
message: common.i18n.t('errors.models.user.tokenLocked')
|
message: i18n.t('errors.models.user.tokenLocked')
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ function doReset(options, tokenParts, settingsAPI) {
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new common.errors.NotFoundError({message: common.i18n.t('errors.api.users.userNotFound')});
|
throw new errors.NotFoundError({message: i18n.t('errors.api.users.userNotFound')});
|
||||||
}
|
}
|
||||||
|
|
||||||
let tokenIsCorrect = security.tokens.resetToken.compare({
|
let tokenIsCorrect = security.tokens.resetToken.compare({
|
||||||
|
@ -92,8 +93,8 @@ function doReset(options, tokenParts, settingsAPI) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!tokenIsCorrect) {
|
if (!tokenIsCorrect) {
|
||||||
return Promise.reject(new common.errors.BadRequestError({
|
return Promise.reject(new errors.BadRequestError({
|
||||||
message: common.i18n.t('errors.api.common.invalidTokenStructure')
|
message: i18n.t('errors.api.common.invalidTokenStructure')
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,14 +108,14 @@ function doReset(options, tokenParts, settingsAPI) {
|
||||||
updatedUser.set('status', 'active');
|
updatedUser.set('status', 'active');
|
||||||
return updatedUser.save(options);
|
return updatedUser.save(options);
|
||||||
})
|
})
|
||||||
.catch(common.errors.ValidationError, (err) => {
|
.catch(errors.ValidationError, (err) => {
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (common.errors.utils.isIgnitionError(err)) {
|
if (errors.utils.isIgnitionError(err)) {
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
}
|
}
|
||||||
return Promise.reject(new common.errors.UnauthorizedError({err: err}));
|
return Promise.reject(new errors.UnauthorizedError({err: err}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +134,7 @@ async function sendResetNotification(data, mailAPI) {
|
||||||
mail: [{
|
mail: [{
|
||||||
message: {
|
message: {
|
||||||
to: data.email,
|
to: data.email,
|
||||||
subject: common.i18n.t('common.api.authentication.mail.resetPassword'),
|
subject: i18n.t('common.api.authentication.mail.resetPassword'),
|
||||||
html: content.html,
|
html: content.html,
|
||||||
text: content.text
|
text: content.text
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const config = require('../../config');
|
const config = require('../../config');
|
||||||
const common = require('../../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {i18n, logging} = require('../../lib/common');
|
||||||
const models = require('../../models');
|
const models = require('../../models');
|
||||||
const mail = require('../mail');
|
const mail = require('../mail');
|
||||||
|
|
||||||
|
@ -27,11 +28,11 @@ function assertSetupCompleted(status) {
|
||||||
return __;
|
return __;
|
||||||
}
|
}
|
||||||
|
|
||||||
const completed = common.i18n.t('errors.api.authentication.setupAlreadyCompleted');
|
const completed = i18n.t('errors.api.authentication.setupAlreadyCompleted');
|
||||||
const notCompleted = common.i18n.t('errors.api.authentication.setupMustBeCompleted');
|
const notCompleted = i18n.t('errors.api.authentication.setupMustBeCompleted');
|
||||||
|
|
||||||
function throwReason(reason) {
|
function throwReason(reason) {
|
||||||
throw new common.errors.NoPermissionError({message: reason});
|
throw new errors.NoPermissionError({message: reason});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSetup) {
|
if (isSetup) {
|
||||||
|
@ -48,8 +49,8 @@ async function setupUser(userData) {
|
||||||
const owner = await models.User.findOne({role: 'Owner', status: 'all'});
|
const owner = await models.User.findOne({role: 'Owner', status: 'all'});
|
||||||
|
|
||||||
if (!owner) {
|
if (!owner) {
|
||||||
throw new common.errors.GhostError({
|
throw new errors.GhostError({
|
||||||
message: common.i18n.t('errors.api.authentication.setupUnableToRun')
|
message: i18n.t('errors.api.authentication.setupUnableToRun')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +75,7 @@ async function doSettings(data, settingsAPI) {
|
||||||
|
|
||||||
userSettings = [
|
userSettings = [
|
||||||
{key: 'title', value: blogTitle.trim()},
|
{key: 'title', value: blogTitle.trim()},
|
||||||
{key: 'description', value: common.i18n.t('common.api.authentication.sampleBlogDescription')}
|
{key: 'description', value: i18n.t('common.api.authentication.sampleBlogDescription')}
|
||||||
];
|
];
|
||||||
|
|
||||||
await settingsAPI.edit({settings: userSettings}, context);
|
await settingsAPI.edit({settings: userSettings}, context);
|
||||||
|
@ -92,7 +93,7 @@ function sendWelcomeEmail(email, mailAPI) {
|
||||||
.then((content) => {
|
.then((content) => {
|
||||||
const message = {
|
const message = {
|
||||||
to: email,
|
to: email,
|
||||||
subject: common.i18n.t('common.api.authentication.mail.yourNewGhostBlog'),
|
subject: i18n.t('common.api.authentication.mail.yourNewGhostBlog'),
|
||||||
html: content.html,
|
html: content.html,
|
||||||
text: content.text
|
text: content.text
|
||||||
};
|
};
|
||||||
|
@ -106,8 +107,8 @@ function sendWelcomeEmail(email, mailAPI) {
|
||||||
|
|
||||||
mailAPI.send(payload, {context: {internal: true}})
|
mailAPI.send(payload, {context: {internal: true}})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
err.context = common.i18n.t('errors.api.authentication.unableToSendWelcomeEmail');
|
err.context = i18n.t('errors.api.authentication.unableToSendWelcomeEmail');
|
||||||
common.logging.error(err);
|
logging.error(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const common = require('../../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {i18n, logging} = require('../../lib/common');
|
||||||
const mailgunProvider = require('./mailgun');
|
const mailgunProvider = require('./mailgun');
|
||||||
const configService = require('../../config');
|
const configService = require('../../config');
|
||||||
const settingsCache = require('../settings/cache');
|
const settingsCache = require('../settings/cache');
|
||||||
|
@ -64,7 +65,7 @@ module.exports = {
|
||||||
let fromAddress = message.from;
|
let fromAddress = message.from;
|
||||||
if (/@localhost$/.test(message.from) || /@ghost.local$/.test(message.from)) {
|
if (/@localhost$/.test(message.from) || /@ghost.local$/.test(message.from)) {
|
||||||
fromAddress = 'localhost@example.com';
|
fromAddress = 'localhost@example.com';
|
||||||
common.logging.warn(`Rewriting bulk email from address ${message.from} to ${fromAddress}`);
|
logging.warn(`Rewriting bulk email from address ${message.from} to ${fromAddress}`);
|
||||||
|
|
||||||
BATCH_SIZE = 2;
|
BATCH_SIZE = 2;
|
||||||
}
|
}
|
||||||
|
@ -101,13 +102,13 @@ module.exports = {
|
||||||
if (error) {
|
if (error) {
|
||||||
// NOTE: logging an error here only but actual handling should happen in more sophisticated batch retry handler
|
// NOTE: logging an error here only but actual handling should happen in more sophisticated batch retry handler
|
||||||
// REF: possible mailgun errors https://documentation.mailgun.com/en/latest/api-intro.html#errors
|
// REF: possible mailgun errors https://documentation.mailgun.com/en/latest/api-intro.html#errors
|
||||||
let ghostError = new common.errors.EmailError({
|
let ghostError = new errors.EmailError({
|
||||||
err: error,
|
err: error,
|
||||||
context: common.i18n.t('errors.services.mega.requestFailed.error')
|
context: i18n.t('errors.services.mega.requestFailed.error')
|
||||||
});
|
});
|
||||||
|
|
||||||
sentry.captureException(ghostError);
|
sentry.captureException(ghostError);
|
||||||
common.logging.warn(ghostError);
|
logging.warn(ghostError);
|
||||||
|
|
||||||
// NOTE: these are generated variables, so can be regenerated when retry is done
|
// NOTE: these are generated variables, so can be regenerated when retry is done
|
||||||
const data = _.omit(batchData, ['recipient-variables']);
|
const data = _.omit(batchData, ['recipient-variables']);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const {URL} = require('url');
|
const {URL} = require('url');
|
||||||
const mailgun = require('mailgun-js');
|
const mailgun = require('mailgun-js');
|
||||||
const common = require('../../lib/common');
|
const {logging} = require('../../lib/common');
|
||||||
const configService = require('../../config');
|
const configService = require('../../config');
|
||||||
const settingsCache = require('../settings/cache');
|
const settingsCache = require('../settings/cache');
|
||||||
|
|
||||||
|
@ -24,13 +24,13 @@ function getInstance() {
|
||||||
const hasMailgunConfig = !!(bulkEmailConfig && bulkEmailConfig.mailgun);
|
const hasMailgunConfig = !!(bulkEmailConfig && bulkEmailConfig.mailgun);
|
||||||
const hasMailgunSetting = !!(bulkEmailSetting && bulkEmailSetting.apiKey && bulkEmailSetting.baseUrl && bulkEmailSetting.domain);
|
const hasMailgunSetting = !!(bulkEmailSetting && bulkEmailSetting.apiKey && bulkEmailSetting.baseUrl && bulkEmailSetting.domain);
|
||||||
if (!hasMailgunConfig && !hasMailgunSetting) {
|
if (!hasMailgunConfig && !hasMailgunSetting) {
|
||||||
common.logging.warn(`Bulk email service is not configured`);
|
logging.warn(`Bulk email service is not configured`);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
let mailgunConfig = hasMailgunConfig ? bulkEmailConfig.mailgun : bulkEmailSetting;
|
let mailgunConfig = hasMailgunConfig ? bulkEmailConfig.mailgun : bulkEmailSetting;
|
||||||
return createMailgun(mailgunConfig);
|
return createMailgun(mailgunConfig);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
common.logging.warn(`Bulk email service is not configured`);
|
logging.warn(`Bulk email service is not configured`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const common = require('../../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {i18n} = require('../../lib/common');
|
||||||
const models = require('../../models');
|
const models = require('../../models');
|
||||||
const security = require('../../lib/security');
|
const security = require('../../lib/security');
|
||||||
|
|
||||||
|
@ -10,11 +11,11 @@ async function accept(invitation) {
|
||||||
let invite = await models.Invite.findOne({token: inviteToken, status: 'sent'}, options);
|
let invite = await models.Invite.findOne({token: inviteToken, status: 'sent'}, options);
|
||||||
|
|
||||||
if (!invite) {
|
if (!invite) {
|
||||||
throw new common.errors.NotFoundError({message: common.i18n.t('errors.api.invites.inviteNotFound')});
|
throw new errors.NotFoundError({message: i18n.t('errors.api.invites.inviteNotFound')});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (invite.get('expires') < Date.now()) {
|
if (invite.get('expires') < Date.now()) {
|
||||||
throw new common.errors.NotFoundError({message: common.i18n.t('errors.api.invites.inviteExpired')});
|
throw new errors.NotFoundError({message: i18n.t('errors.api.invites.inviteExpired')});
|
||||||
}
|
}
|
||||||
|
|
||||||
await models.User.add({
|
await models.User.add({
|
||||||
|
|
|
@ -2,7 +2,8 @@ const settingsCache = require('./settings/cache');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const Promise = require('bluebird');
|
const Promise = require('bluebird');
|
||||||
const SafeString = require('../../frontend/services/themes/engine').SafeString;
|
const SafeString = require('../../frontend/services/themes/engine').SafeString;
|
||||||
const common = require('../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {i18n, logging} = require('../lib/common');
|
||||||
const deprecatedFeatures = ['subscribers', 'publicAPI'];
|
const deprecatedFeatures = ['subscribers', 'publicAPI'];
|
||||||
|
|
||||||
module.exports.getAll = () => {
|
module.exports.getAll = () => {
|
||||||
|
@ -31,14 +32,14 @@ module.exports.enabledHelper = function enabledHelper(options, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Else, the helper is not active and we need to handle this as an error
|
// Else, the helper is not active and we need to handle this as an error
|
||||||
errDetails.message = common.i18n.t(options.errMessagePath || 'warnings.helpers.helperNotAvailable', {helperName: options.helperName}),
|
errDetails.message = i18n.t(options.errMessagePath || 'warnings.helpers.helperNotAvailable', {helperName: options.helperName}),
|
||||||
errDetails.context = common.i18n.t(options.errContextPath || 'warnings.helpers.flagMustBeEnabled', {
|
errDetails.context = i18n.t(options.errContextPath || 'warnings.helpers.flagMustBeEnabled', {
|
||||||
helperName: options.helperName,
|
helperName: options.helperName,
|
||||||
flagName: options.flagName
|
flagName: options.flagName
|
||||||
});
|
});
|
||||||
errDetails.help = common.i18n.t(options.errHelpPath || 'warnings.helpers.seeLink', {url: options.helpUrl});
|
errDetails.help = i18n.t(options.errHelpPath || 'warnings.helpers.seeLink', {url: options.helpUrl});
|
||||||
|
|
||||||
common.logging.error(new common.errors.DisabledFeatureError(errDetails));
|
logging.error(new errors.DisabledFeatureError(errDetails));
|
||||||
|
|
||||||
errString = new SafeString(`<script>console.error("${_.values(errDetails).join(' ')}");</script>`);
|
errString = new SafeString(`<script>console.error("${_.values(errDetails).join(' ')}");</script>`);
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,13 @@ const _ = require('lodash');
|
||||||
const Promise = require('bluebird');
|
const Promise = require('bluebird');
|
||||||
const validator = require('validator');
|
const validator = require('validator');
|
||||||
const config = require('../../config');
|
const config = require('../../config');
|
||||||
const common = require('../../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {i18n} = require('../../lib/common');
|
||||||
const settingsCache = require('../settings/cache');
|
const settingsCache = require('../settings/cache');
|
||||||
const urlUtils = require('../../lib/url-utils');
|
const urlUtils = require('../../lib/url-utils');
|
||||||
|
|
||||||
const helpMessage = common.i18n.t('errors.api.authentication.checkEmailConfigInstructions', {url: 'https://ghost.org/docs/concepts/config/#mail'});
|
const helpMessage = i18n.t('errors.api.authentication.checkEmailConfigInstructions', {url: 'https://ghost.org/docs/concepts/config/#mail'});
|
||||||
const defaultErrorMessage = common.i18n.t('errors.mail.failedSendingEmail.error');
|
const defaultErrorMessage = i18n.t('errors.mail.failedSendingEmail.error');
|
||||||
|
|
||||||
function getDomain() {
|
function getDomain() {
|
||||||
const domain = urlUtils.urlFor('home', true).match(new RegExp('^https?://([^/:?#]+)(?:[/:?#]|$)', 'i'));
|
const domain = urlUtils.urlFor('home', true).match(new RegExp('^https?://([^/:?#]+)(?:[/:?#]|$)', 'i'));
|
||||||
|
@ -28,7 +29,7 @@ function getFromAddress(requestedFromAddress) {
|
||||||
|
|
||||||
// If we do have a from address, and it's just an email
|
// If we do have a from address, and it's just an email
|
||||||
if (validator.isEmail(address, {require_tld: false})) {
|
if (validator.isEmail(address, {require_tld: false})) {
|
||||||
const defaultBlogTitle = settingsCache.get('title') ? settingsCache.get('title').replace(/"/g, '\\"') : common.i18n.t('common.mail.title', {domain: getDomain()});
|
const defaultBlogTitle = settingsCache.get('title') ? settingsCache.get('title').replace(/"/g, '\\"') : i18n.t('common.mail.title', {domain: getDomain()});
|
||||||
return `"${defaultBlogTitle}" <${address}>`;
|
return `"${defaultBlogTitle}" <${address}>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ function createMessage(message) {
|
||||||
|
|
||||||
function createMailError({message, err, ignoreDefaultMessage} = {message: ''}) {
|
function createMailError({message, err, ignoreDefaultMessage} = {message: ''}) {
|
||||||
const fullErrorMessage = defaultErrorMessage + message;
|
const fullErrorMessage = defaultErrorMessage + message;
|
||||||
return new common.errors.EmailError({
|
return new errors.EmailError({
|
||||||
message: ignoreDefaultMessage ? message : fullErrorMessage,
|
message: ignoreDefaultMessage ? message : fullErrorMessage,
|
||||||
err: err,
|
err: err,
|
||||||
help: helpMessage
|
help: helpMessage
|
||||||
|
@ -70,7 +71,7 @@ module.exports = class GhostMailer {
|
||||||
send(message) {
|
send(message) {
|
||||||
if (!(message && message.subject && message.html && message.to)) {
|
if (!(message && message.subject && message.html && message.to)) {
|
||||||
return Promise.reject(createMailError({
|
return Promise.reject(createMailError({
|
||||||
message: common.i18n.t('errors.mail.incompleteMessageData.error'),
|
message: i18n.t('errors.mail.incompleteMessageData.error'),
|
||||||
ignoreDefaultMessage: true
|
ignoreDefaultMessage: true
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -90,7 +91,7 @@ module.exports = class GhostMailer {
|
||||||
this.transport.sendMail(message, (err, response) => {
|
this.transport.sendMail(message, (err, response) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(createMailError({
|
reject(createMailError({
|
||||||
message: common.i18n.t('errors.mail.reason', {reason: err.message || err}),
|
message: i18n.t('errors.mail.reason', {reason: err.message || err}),
|
||||||
err
|
err
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -104,7 +105,7 @@ module.exports = class GhostMailer {
|
||||||
response.statusHandler.once('failed', function (data) {
|
response.statusHandler.once('failed', function (data) {
|
||||||
if (data.error && data.error.errno === 'ENOTFOUND') {
|
if (data.error && data.error.errno === 'ENOTFOUND') {
|
||||||
reject(createMailError({
|
reject(createMailError({
|
||||||
message: common.i18n.t('errors.mail.noMailServerAtAddress.error', {domain: data.domain})
|
message: i18n.t('errors.mail.noMailServerAtAddress.error', {domain: data.domain})
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +115,7 @@ module.exports = class GhostMailer {
|
||||||
response.statusHandler.once('requeue', function (data) {
|
response.statusHandler.once('requeue', function (data) {
|
||||||
if (data.error && data.error.message) {
|
if (data.error && data.error.message) {
|
||||||
reject(createMailError({
|
reject(createMailError({
|
||||||
message: common.i18n.t('errors.mail.reason', {reason: data.error.message})
|
message: i18n.t('errors.mail.reason', {reason: data.error.message})
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +123,7 @@ module.exports = class GhostMailer {
|
||||||
});
|
});
|
||||||
|
|
||||||
response.statusHandler.once('sent', function () {
|
response.statusHandler.once('sent', function () {
|
||||||
resolve(common.i18n.t('notices.mail.messageSent'));
|
resolve(i18n.t('notices.mail.messageSent'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const common = require('../../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {events, i18n, logging} = require('../../lib/common');
|
||||||
const membersService = require('../members');
|
const membersService = require('../members');
|
||||||
const bulkEmailService = require('../bulk-email');
|
const bulkEmailService = require('../bulk-email');
|
||||||
const models = require('../../models');
|
const models = require('../../models');
|
||||||
|
@ -147,14 +148,14 @@ const retryFailedEmail = async (model) => {
|
||||||
*/
|
*/
|
||||||
async function handleUnsubscribeRequest(req) {
|
async function handleUnsubscribeRequest(req) {
|
||||||
if (!req.url) {
|
if (!req.url) {
|
||||||
throw new common.errors.BadRequestError({
|
throw new errors.BadRequestError({
|
||||||
message: 'Unsubscribe failed! Could not find member'
|
message: 'Unsubscribe failed! Could not find member'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const {query} = url.parse(req.url, true);
|
const {query} = url.parse(req.url, true);
|
||||||
if (!query || !query.uuid) {
|
if (!query || !query.uuid) {
|
||||||
throw new common.errors.BadRequestError({
|
throw new errors.BadRequestError({
|
||||||
message: (query.preview ? 'Unsubscribe preview' : 'Unsubscribe failed! Could not find member')
|
message: (query.preview ? 'Unsubscribe preview' : 'Unsubscribe failed! Could not find member')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -164,7 +165,7 @@ async function handleUnsubscribeRequest(req) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!member) {
|
if (!member) {
|
||||||
throw new common.errors.BadRequestError({
|
throw new errors.BadRequestError({
|
||||||
message: 'Unsubscribe failed! Could not find member'
|
message: 'Unsubscribe failed! Could not find member'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -172,7 +173,7 @@ async function handleUnsubscribeRequest(req) {
|
||||||
try {
|
try {
|
||||||
return await membersService.api.members.update({subscribed: false}, {id: member.id});
|
return await membersService.api.members.update({subscribed: false}, {id: member.id});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new common.errors.InternalServerError({
|
throw new errors.InternalServerError({
|
||||||
message: 'Failed to unsubscribe member'
|
message: 'Failed to unsubscribe member'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -184,7 +185,7 @@ function checkHostLimitForMembers(members = []) {
|
||||||
const allowedMembersLimit = membersHostLimit.max;
|
const allowedMembersLimit = membersHostLimit.max;
|
||||||
const hostUpgradeLink = config.get('host_settings:limits').upgrade_url;
|
const hostUpgradeLink = config.get('host_settings:limits').upgrade_url;
|
||||||
if (members.length > allowedMembersLimit) {
|
if (members.length > allowedMembersLimit) {
|
||||||
throw new common.errors.HostLimitError({
|
throw new errors.HostLimitError({
|
||||||
message: `Your current plan allows you to send email to up to ${allowedMembersLimit} members, but you currently have ${members.length} members`,
|
message: `Your current plan allows you to send email to up to ${allowedMembersLimit} members, but you currently have ${members.length} members`,
|
||||||
help: hostUpgradeLink,
|
help: hostUpgradeLink,
|
||||||
errorDetails: {
|
errorDetails: {
|
||||||
|
@ -230,9 +231,9 @@ async function pendingEmailHandler(emailModel, options) {
|
||||||
// needs filtering and saving objects of {error, batchData} form to separate property
|
// needs filtering and saving objects of {error, batchData} form to separate property
|
||||||
meta = await sendEmail(postModel, members);
|
meta = await sendEmail(postModel, members);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
common.logging.error(new common.errors.GhostError({
|
logging.error(new errors.GhostError({
|
||||||
err: err,
|
err: err,
|
||||||
context: common.i18n.t('errors.services.mega.requestFailed.error')
|
context: i18n.t('errors.services.mega.requestFailed.error')
|
||||||
}));
|
}));
|
||||||
error = err.message;
|
error = err.message;
|
||||||
}
|
}
|
||||||
|
@ -260,7 +261,7 @@ async function pendingEmailHandler(emailModel, options) {
|
||||||
id: emailModel.id
|
id: emailModel.id
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
common.logging.error(err);
|
logging.error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,8 +276,8 @@ const statusChangedHandler = (emailModel, options) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
function listen() {
|
function listen() {
|
||||||
common.events.on('email.added', pendingEmailHandler);
|
events.on('email.added', pendingEmailHandler);
|
||||||
common.events.on('email.edited', statusChangedHandler);
|
events.on('email.edited', statusChangedHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public API
|
// Public API
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const settingsCache = require('../settings/cache');
|
const settingsCache = require('../settings/cache');
|
||||||
const MembersApi = require('@tryghost/members-api');
|
const MembersApi = require('@tryghost/members-api');
|
||||||
const common = require('../../lib/common');
|
const {logging} = require('../../lib/common');
|
||||||
const mail = require('../mail');
|
const mail = require('../mail');
|
||||||
const models = require('../../models');
|
const models = require('../../models');
|
||||||
const signinEmail = require('./emails/signin');
|
const signinEmail = require('./emails/signin');
|
||||||
|
@ -24,7 +24,7 @@ function createApiInstance() {
|
||||||
transporter: {
|
transporter: {
|
||||||
sendMail(message) {
|
sendMail(message) {
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
common.logging.warn(message.text);
|
logging.warn(message.text);
|
||||||
}
|
}
|
||||||
let msg = Object.assign({
|
let msg = Object.assign({
|
||||||
from: config.getEmailFromAddress(),
|
from: config.getEmailFromAddress(),
|
||||||
|
@ -126,7 +126,7 @@ function createApiInstance() {
|
||||||
memberStripeCustomerModel: models.MemberStripeCustomer,
|
memberStripeCustomerModel: models.MemberStripeCustomer,
|
||||||
stripeCustomerSubscriptionModel: models.StripeCustomerSubscription,
|
stripeCustomerSubscriptionModel: models.StripeCustomerSubscription,
|
||||||
memberModel: models.Member,
|
memberModel: models.Member,
|
||||||
logger: common.logging
|
logger: logging
|
||||||
});
|
});
|
||||||
|
|
||||||
return membersApiInstance;
|
return membersApiInstance;
|
||||||
|
|
|
@ -3,7 +3,7 @@ const settingsCache = require('../settings/cache');
|
||||||
const ghostVersion = require('../../lib/ghost-version');
|
const ghostVersion = require('../../lib/ghost-version');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const common = require('../../lib/common');
|
const {logging} = require('../../lib/common');
|
||||||
const urlUtils = require('../../lib/url-utils');
|
const urlUtils = require('../../lib/url-utils');
|
||||||
|
|
||||||
const COMPLIMENTARY_PLAN = {
|
const COMPLIMENTARY_PLAN = {
|
||||||
|
@ -130,12 +130,12 @@ function getStripePaymentConfig() {
|
||||||
function getAuthSecret() {
|
function getAuthSecret() {
|
||||||
const hexSecret = settingsCache.get('members_email_auth_secret');
|
const hexSecret = settingsCache.get('members_email_auth_secret');
|
||||||
if (!hexSecret) {
|
if (!hexSecret) {
|
||||||
common.logging.warn('Could not find members_email_auth_secret, using dynamically generated secret');
|
logging.warn('Could not find members_email_auth_secret, using dynamically generated secret');
|
||||||
return crypto.randomBytes(64);
|
return crypto.randomBytes(64);
|
||||||
}
|
}
|
||||||
const secret = Buffer.from(hexSecret, 'hex');
|
const secret = Buffer.from(hexSecret, 'hex');
|
||||||
if (secret.length < 64) {
|
if (secret.length < 64) {
|
||||||
common.logging.warn('members_email_auth_secret not large enough (64 bytes), using dynamically generated secret');
|
logging.warn('members_email_auth_secret not large enough (64 bytes), using dynamically generated secret');
|
||||||
return crypto.randomBytes(64);
|
return crypto.randomBytes(64);
|
||||||
}
|
}
|
||||||
return secret;
|
return secret;
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
const MembersSSR = require('@tryghost/members-ssr');
|
const MembersSSR = require('@tryghost/members-ssr');
|
||||||
|
|
||||||
const createMembersApiInstance = require('./api');
|
const createMembersApiInstance = require('./api');
|
||||||
const common = require('../../lib/common');
|
const {events, logging} = require('../../lib/common');
|
||||||
const urlUtils = require('../../lib/url-utils');
|
const urlUtils = require('../../lib/url-utils');
|
||||||
const settingsCache = require('../settings/cache');
|
const settingsCache = require('../settings/cache');
|
||||||
|
|
||||||
let membersApi;
|
let membersApi;
|
||||||
|
|
||||||
// Bind to events to automatically keep subscription info up-to-date from settings
|
// Bind to events to automatically keep subscription info up-to-date from settings
|
||||||
common.events.on('settings.edited', function updateSettingFromModel(settingModel) {
|
events.on('settings.edited', function updateSettingFromModel(settingModel) {
|
||||||
if (!['members_subscription_settings'].includes(settingModel.get('key'))) {
|
if (!['members_subscription_settings'].includes(settingModel.get('key'))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ common.events.on('settings.edited', function updateSettingFromModel(settingModel
|
||||||
membersApi = reconfiguredMembersAPI;
|
membersApi = reconfiguredMembersAPI;
|
||||||
});
|
});
|
||||||
reconfiguredMembersAPI.bus.on('error', function (err) {
|
reconfiguredMembersAPI.bus.on('error', function (err) {
|
||||||
common.logging.error(err);
|
logging.error(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ const membersService = {
|
||||||
membersApi = createMembersApiInstance();
|
membersApi = createMembersApiInstance();
|
||||||
|
|
||||||
membersApi.bus.on('error', function (err) {
|
membersApi.bus.on('error', function (err) {
|
||||||
common.logging.error(err);
|
logging.error(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return membersApi;
|
return membersApi;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const common = require('../../lib/common');
|
const {logging} = require('../../lib/common');
|
||||||
const config = require('../../config');
|
const config = require('../../config');
|
||||||
const labsService = require('../labs');
|
const labsService = require('../labs');
|
||||||
const membersService = require('./index');
|
const membersService = require('./index');
|
||||||
|
@ -19,7 +19,7 @@ const loadMemberSession = async function (req, res, next) {
|
||||||
res.locals.member = req.member;
|
res.locals.member = req.member;
|
||||||
next();
|
next();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
common.logging.warn(err.message);
|
logging.warn(err.message);
|
||||||
Object.assign(req, {member: null});
|
Object.assign(req, {member: null});
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ const getIdentityToken = async function (req, res) {
|
||||||
res.writeHead(200);
|
res.writeHead(200);
|
||||||
res.end(token);
|
res.end(token);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
common.logging.warn(err.message);
|
logging.warn(err.message);
|
||||||
res.writeHead(err.statusCode);
|
res.writeHead(err.statusCode);
|
||||||
res.end(err.message);
|
res.end(err.message);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ const deleteSession = async function (req, res) {
|
||||||
res.writeHead(204);
|
res.writeHead(204);
|
||||||
res.end();
|
res.end();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
common.logging.warn(err.message);
|
logging.warn(err.message);
|
||||||
res.writeHead(err.statusCode);
|
res.writeHead(err.statusCode);
|
||||||
res.end(err.message);
|
res.end(err.message);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ const getMemberData = async function (req, res) {
|
||||||
res.json(null);
|
res.json(null);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
common.logging.warn(err.message);
|
logging.warn(err.message);
|
||||||
res.writeHead(err.statusCode);
|
res.writeHead(err.statusCode);
|
||||||
res.end(err.message);
|
res.end(err.message);
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ const createSessionFromMagicLink = async function (req, res, next) {
|
||||||
// Do a standard 302 redirect
|
// Do a standard 302 redirect
|
||||||
res.redirect(redirectPath);
|
res.redirect(redirectPath);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
common.logging.warn(err.message);
|
logging.warn(err.message);
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const Promise = require('bluebird');
|
const Promise = require('bluebird');
|
||||||
const models = require('../../models');
|
const models = require('../../models');
|
||||||
const common = require('../../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {i18n} = require('../../lib/common');
|
||||||
const providers = require('./providers');
|
const providers = require('./providers');
|
||||||
const parseContext = require('./parse-context');
|
const parseContext = require('./parse-context');
|
||||||
const actionsMap = require('./actions-map-cache');
|
const actionsMap = require('./actions-map-cache');
|
||||||
|
@ -102,7 +103,7 @@ CanThisResult.prototype.buildObjectTypeHandlers = function (objTypes, actType, c
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject(new common.errors.NoPermissionError({message: common.i18n.t('errors.permissions.noPermissionToAction')}));
|
return Promise.reject(new errors.NoPermissionError({message: i18n.t('errors.permissions.noPermissionToAction')}));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -120,7 +121,7 @@ CanThisResult.prototype.beginCheck = function (context) {
|
||||||
context = parseContext(context);
|
context = parseContext(context);
|
||||||
|
|
||||||
if (actionsMap.empty()) {
|
if (actionsMap.empty()) {
|
||||||
throw new Error(common.i18n.t('errors.permissions.noActionsMapFound.error'));
|
throw new Error(i18n.t('errors.permissions.noActionsMapFound.error'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kick off loading of user permissions if necessary
|
// Kick off loading of user permissions if necessary
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const Promise = require('bluebird');
|
const Promise = require('bluebird');
|
||||||
const models = require('../../models');
|
const models = require('../../models');
|
||||||
const common = require('../../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {i18n} = require('../../lib/common');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
user: function (id) {
|
user: function (id) {
|
||||||
|
@ -9,8 +10,8 @@ module.exports = {
|
||||||
.then(function (foundUser) {
|
.then(function (foundUser) {
|
||||||
// CASE: {context: {user: id}} where the id is not in our database
|
// CASE: {context: {user: id}} where the id is not in our database
|
||||||
if (!foundUser) {
|
if (!foundUser) {
|
||||||
return Promise.reject(new common.errors.NotFoundError({
|
return Promise.reject(new errors.NotFoundError({
|
||||||
message: common.i18n.t('errors.models.user.userNotFound')
|
message: i18n.t('errors.models.user.userNotFound')
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,8 +51,8 @@ module.exports = {
|
||||||
return models.ApiKey.findOne({id}, {withRelated: ['role', 'role.permissions']})
|
return models.ApiKey.findOne({id}, {withRelated: ['role', 'role.permissions']})
|
||||||
.then((foundApiKey) => {
|
.then((foundApiKey) => {
|
||||||
if (!foundApiKey) {
|
if (!foundApiKey) {
|
||||||
throw new common.errors.NotFoundError({
|
throw new errors.NotFoundError({
|
||||||
message: common.i18n.t('errors.models.api_key.apiKeyNotFound')
|
message: i18n.t('errors.models.api_key.apiKeyNotFound')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const Promise = require('bluebird');
|
const Promise = require('bluebird');
|
||||||
const common = require('../../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {i18n} = require('../../lib/common');
|
||||||
const parseContext = require('./parse-context');
|
const parseContext = require('./parse-context');
|
||||||
const _private = {};
|
const _private = {};
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ const _private = {};
|
||||||
* - public context cannot fetch draft/scheduled posts
|
* - public context cannot fetch draft/scheduled posts
|
||||||
*/
|
*/
|
||||||
_private.applyStatusRules = function applyStatusRules(docName, method, opts) {
|
_private.applyStatusRules = function applyStatusRules(docName, method, opts) {
|
||||||
const err = new common.errors.NoPermissionError({message: common.i18n.t('errors.permissions.applyStatusRules.error', {docName: docName})});
|
const err = new errors.NoPermissionError({message: i18n.t('errors.permissions.applyStatusRules.error', {docName: docName})});
|
||||||
|
|
||||||
// Enforce status 'active' for users
|
// Enforce status 'active' for users
|
||||||
if (docName === 'users') {
|
if (docName === 'users') {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// circular dependency bugs.
|
// circular dependency bugs.
|
||||||
const debug = require('ghost-ignition').debug('settings:cache');
|
const debug = require('ghost-ignition').debug('settings:cache');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const common = require('../../lib/common');
|
const {events} = require('../../lib/common');
|
||||||
const publicSettings = require('./public');
|
const publicSettings = require('./public');
|
||||||
|
|
||||||
// Local function, only ever used for initialising
|
// Local function, only ever used for initialising
|
||||||
|
@ -123,17 +123,17 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind to events to automatically keep up-to-date
|
// Bind to events to automatically keep up-to-date
|
||||||
common.events.on('settings.edited', updateSettingFromModel);
|
events.on('settings.edited', updateSettingFromModel);
|
||||||
common.events.on('settings.added', updateSettingFromModel);
|
events.on('settings.added', updateSettingFromModel);
|
||||||
common.events.on('settings.deleted', updateSettingFromModel);
|
events.on('settings.deleted', updateSettingFromModel);
|
||||||
|
|
||||||
return settingsCache;
|
return settingsCache;
|
||||||
},
|
},
|
||||||
|
|
||||||
shutdown() {
|
shutdown() {
|
||||||
common.events.removeListener('settings.edited', updateSettingFromModel);
|
events.removeListener('settings.edited', updateSettingFromModel);
|
||||||
common.events.removeListener('settings.added', updateSettingFromModel);
|
events.removeListener('settings.added', updateSettingFromModel);
|
||||||
common.events.removeListener('settings.deleted', updateSettingFromModel);
|
events.removeListener('settings.deleted', updateSettingFromModel);
|
||||||
},
|
},
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const common = require('../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {events, i18n, logging} = require('../lib/common');
|
||||||
const request = require('../lib/request');
|
const request = require('../lib/request');
|
||||||
const imageLib = require('../lib/image');
|
const imageLib = require('../lib/image');
|
||||||
const urlUtils = require('../lib/url-utils');
|
const urlUtils = require('../lib/url-utils');
|
||||||
|
@ -123,10 +124,10 @@ function ping(post) {
|
||||||
'Content-type': 'application/json'
|
'Content-type': 'application/json'
|
||||||
}
|
}
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
common.logging.error(new common.errors.GhostError({
|
logging.error(new errors.GhostError({
|
||||||
err: err,
|
err: err,
|
||||||
context: common.i18n.t('errors.services.ping.requestFailed.error', {service: 'slack'}),
|
context: i18n.t('errors.services.ping.requestFailed.error', {service: 'slack'}),
|
||||||
help: common.i18n.t('errors.services.ping.requestFailed.help', {url: 'https://ghost.org/docs/'})
|
help: i18n.t('errors.services.ping.requestFailed.help', {url: 'https://ghost.org/docs/'})
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -149,8 +150,8 @@ function testPing() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function listen() {
|
function listen() {
|
||||||
common.events.on('post.published', listener);
|
events.on('post.published', listener);
|
||||||
common.events.on('slack.test', testPing);
|
events.on('slack.test', testPing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public API
|
// Public API
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const common = require('../../lib/common');
|
const {events} = require('../../lib/common');
|
||||||
const trigger = require('./trigger');
|
const trigger = require('./trigger');
|
||||||
|
|
||||||
const WEBHOOKS = [
|
const WEBHOOKS = [
|
||||||
|
@ -41,7 +41,7 @@ const WEBHOOKS = [
|
||||||
|
|
||||||
const listen = () => {
|
const listen = () => {
|
||||||
_.each(WEBHOOKS, (event) => {
|
_.each(WEBHOOKS, (event) => {
|
||||||
common.events.on(event, (model, options) => {
|
events.on(event, (model, options) => {
|
||||||
// CASE: avoid triggering webhooks when importing
|
// CASE: avoid triggering webhooks when importing
|
||||||
if (options && options.importing) {
|
if (options && options.importing) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const debug = require('ghost-ignition').debug('services:webhooks:trigger');
|
const debug = require('ghost-ignition').debug('services:webhooks:trigger');
|
||||||
const common = require('../../lib/common');
|
const {logging} = require('../../lib/common');
|
||||||
const request = require('../../../server/lib/request');
|
const request = require('../../../server/lib/request');
|
||||||
const models = require('../../models');
|
const models = require('../../models');
|
||||||
const payload = require('./payload');
|
const payload = require('./payload');
|
||||||
|
@ -21,7 +21,7 @@ const webhooks = {
|
||||||
last_triggered_error: data.error || null
|
last_triggered_error: data.error || null
|
||||||
}, {id: webhook.id})
|
}, {id: webhook.id})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
common.logging.warn(`Unable to update "last_triggered" for webhook: ${webhook.id}`);
|
logging.warn(`Unable to update "last_triggered" for webhook: ${webhook.id}`);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ const webhooks = {
|
||||||
.Webhook
|
.Webhook
|
||||||
.destroy({id: webhook.id}, {context: {internal: true}})
|
.destroy({id: webhook.id}, {context: {internal: true}})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
common.logging.warn(`Unable to destroy webhook ${webhook.id}.`);
|
logging.warn(`Unable to destroy webhook ${webhook.id}.`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -47,7 +47,7 @@ const response = {
|
||||||
onError(webhook) {
|
onError(webhook) {
|
||||||
return (err) => {
|
return (err) => {
|
||||||
if (err.statusCode === 410) {
|
if (err.statusCode === 410) {
|
||||||
common.logging.info(`Webhook destroyed (410 response) for "${webhook.get('event')}" with url "${webhook.get('target_url')}".`);
|
logging.info(`Webhook destroyed (410 response) for "${webhook.get('event')}" with url "${webhook.get('target_url')}".`);
|
||||||
|
|
||||||
return webhooks.destroy(webhook);
|
return webhooks.destroy(webhook);
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ const response = {
|
||||||
error: `Request failed: ${err.code || 'unknown'}`
|
error: `Request failed: ${err.code || 'unknown'}`
|
||||||
});
|
});
|
||||||
|
|
||||||
common.logging.warn(`Request to ${webhook.get('target_url') || null} failed because of: ${err.code || ''}.`);
|
logging.warn(`Request to ${webhook.get('target_url') || null} failed because of: ${err.code || ''}.`);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -82,7 +82,7 @@ module.exports = (event, model) => {
|
||||||
retry: 5
|
retry: 5
|
||||||
};
|
};
|
||||||
|
|
||||||
common.logging.info(`Trigger Webhook for "${webhook.get('event')}" with url "${url}".`);
|
logging.info(`Trigger Webhook for "${webhook.get('event')}" with url "${url}".`);
|
||||||
|
|
||||||
request(url, opts)
|
request(url, opts)
|
||||||
.then(response.onSuccess(webhook))
|
.then(response.onSuccess(webhook))
|
||||||
|
|
|
@ -2,7 +2,8 @@ const _ = require('lodash');
|
||||||
const xml = require('xml');
|
const xml = require('xml');
|
||||||
const config = require('../config');
|
const config = require('../config');
|
||||||
const urlService = require('../../frontend/services/url');
|
const urlService = require('../../frontend/services/url');
|
||||||
const common = require('../lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {events, i18n, logging} = require('../lib/common');
|
||||||
const request = require('../lib/request');
|
const request = require('../lib/request');
|
||||||
const settingsCache = require('./settings/cache');
|
const settingsCache = require('./settings/cache');
|
||||||
|
|
||||||
|
@ -80,11 +81,11 @@ function ping(post) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(function (err) {
|
.catch(function (err) {
|
||||||
common.logging.error(new common.errors.GhostError({
|
logging.error(new errors.GhostError({
|
||||||
err: err,
|
err: err,
|
||||||
message: err.message,
|
message: err.message,
|
||||||
context: common.i18n.t('errors.services.ping.requestFailed.error', {service: 'xmlrpc'}),
|
context: i18n.t('errors.services.ping.requestFailed.error', {service: 'xmlrpc'}),
|
||||||
help: common.i18n.t('errors.services.ping.requestFailed.help', {url: 'https://ghost.org/docs/'})
|
help: i18n.t('errors.services.ping.requestFailed.help', {url: 'https://ghost.org/docs/'})
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -101,7 +102,7 @@ function listener(model, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function listen() {
|
function listen() {
|
||||||
common.events.on('post.published', listener);
|
events.on('post.published', listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
|
@ -18,7 +18,8 @@ const debug = require('ghost-ignition').debug('update-check');
|
||||||
const api = require('./api').v2;
|
const api = require('./api').v2;
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
const urlUtils = require('./lib/url-utils');
|
const urlUtils = require('./lib/url-utils');
|
||||||
const common = require('./lib/common');
|
const errors = require('@tryghost/errors');
|
||||||
|
const {i18n, logging} = require('./lib/common');
|
||||||
const request = require('./lib/request');
|
const request = require('./lib/request');
|
||||||
const ghostVersion = require('./lib/ghost-version');
|
const ghostVersion = require('./lib/ghost-version');
|
||||||
const internal = {context: {internal: true}};
|
const internal = {context: {internal: true}};
|
||||||
|
@ -49,9 +50,9 @@ function updateCheckError(err) {
|
||||||
}]
|
}]
|
||||||
}, internal);
|
}, internal);
|
||||||
|
|
||||||
err.context = common.i18n.t('errors.updateCheck.checkingForUpdatesFailed.error');
|
err.context = i18n.t('errors.updateCheck.checkingForUpdatesFailed.error');
|
||||||
err.help = common.i18n.t('errors.updateCheck.checkingForUpdatesFailed.help', {url: 'https://ghost.org/docs/'});
|
err.help = i18n.t('errors.updateCheck.checkingForUpdatesFailed.help', {url: 'https://ghost.org/docs/'});
|
||||||
common.logging.error(err);
|
logging.error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -178,7 +179,7 @@ function updateCheckRequest() {
|
||||||
|
|
||||||
// CASE: service returns JSON error, deserialize into JS error
|
// CASE: service returns JSON error, deserialize into JS error
|
||||||
if (err.response && err.response.body && typeof err.response.body === 'object') {
|
if (err.response && err.response.body && typeof err.response.body === 'object') {
|
||||||
err = common.errors.utils.deserialize(err.response.body);
|
err = errors.utils.deserialize(err.response.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw err;
|
throw err;
|
||||||
|
|
6
index.js
6
index.js
|
@ -13,7 +13,7 @@ const ghost = require('./core');
|
||||||
debug('Required ghost');
|
debug('Required ghost');
|
||||||
|
|
||||||
const express = require('./core/shared/express');
|
const express = require('./core/shared/express');
|
||||||
const common = require('./core/server/lib/common');
|
const {logging} = require('./core/server/lib/common');
|
||||||
const urlService = require('./core/frontend/services/url');
|
const urlService = require('./core/frontend/services/url');
|
||||||
const ghostApp = express();
|
const ghostApp = express();
|
||||||
|
|
||||||
|
@ -31,10 +31,10 @@ ghost().then(function (ghostServer) {
|
||||||
// Let Ghost handle starting our server instance.
|
// Let Ghost handle starting our server instance.
|
||||||
return ghostServer.start(ghostApp)
|
return ghostServer.start(ghostApp)
|
||||||
.then(function afterStart() {
|
.then(function afterStart() {
|
||||||
common.logging.info('Ghost boot', (Date.now() - startTime) / 1000 + 's');
|
logging.info('Ghost boot', (Date.now() - startTime) / 1000 + 's');
|
||||||
});
|
});
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
common.logging.error(err);
|
logging.error(err);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
process.exit(-1);
|
process.exit(-1);
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
Loading…
Reference in a new issue