From 97c68dd388d1cf5e9d6857eb264556e15ea97f72 Mon Sep 17 00:00:00 2001 From: Sam Lord Date: Tue, 14 Dec 2021 15:18:46 +0000 Subject: [PATCH] Replace error handler middleware with @tryghost/mw-error-handler (#13879) refs: https://github.com/TryGhost/Toolbox/issues/137 Extract error handling middleware and replace with a package. --- core/frontend/web/middleware/error-handler.js | 4 +- core/frontend/web/site.js | 3 +- core/server/services/members/config.js | 3 - core/server/services/members/service.js | 4 +- core/server/services/notifications/index.js | 2 - .../services/notifications/notifications.js | 9 +- core/server/web/admin/app.js | 6 +- core/server/web/api/app.js | 5 +- core/server/web/api/canary/admin/app.js | 6 +- core/server/web/api/canary/content/app.js | 6 +- core/server/web/api/v2/admin/app.js | 6 +- core/server/web/api/v2/content/app.js | 6 +- core/server/web/api/v3/admin/app.js | 6 +- core/server/web/api/v3/content/app.js | 6 +- core/server/web/members/app.js | 10 +- .../web/shared/middleware/error-handler.js | 224 ------------------ core/server/web/shared/middleware/index.js | 4 - package.json | 3 +- .../notifications/notifications.test.js | 32 +-- yarn.lock | 24 +- 20 files changed, 84 insertions(+), 285 deletions(-) delete mode 100644 core/server/web/shared/middleware/error-handler.js diff --git a/core/frontend/web/middleware/error-handler.js b/core/frontend/web/middleware/error-handler.js index 220c6a134d..5452511636 100644 --- a/core/frontend/web/middleware/error-handler.js +++ b/core/frontend/web/middleware/error-handler.js @@ -7,7 +7,7 @@ const config = require('../../../shared/config'); const helpers = require('../../services/routing/helpers'); // @TODO: make this properly shared code -const shared = require('../../../server/web/shared/middleware/error-handler'); +const {prepareError} = require('@tryghost/mw-error-handler'); const messages = { oopsErrorTemplateHasError: 'Oops, seems there is an error in the error template.', @@ -85,7 +85,7 @@ const themeErrorRenderer = (err, req, res, next) => { module.exports.handleThemeResponse = [ // Make sure the error can be served - shared.prepareError, + prepareError, // Handle the error in Sentry sentry.errorHandler, // Render the error using theme template diff --git a/core/frontend/web/site.js b/core/frontend/web/site.js index 69669cd4d1..dfe75b488a 100644 --- a/core/frontend/web/site.js +++ b/core/frontend/web/site.js @@ -20,6 +20,7 @@ const offersService = require('../../server/services/offers'); const customRedirects = require('../../server/services/redirects'); const siteRoutes = require('./routes'); const shared = require('../../server/web/shared'); +const errorHandler = require('@tryghost/mw-error-handler'); const mw = require('./middleware'); const labs = require('../../shared/labs'); @@ -176,7 +177,7 @@ module.exports = function setupSiteApp(options = {}) { siteApp.use(SiteRouter); // ### Error handlers - siteApp.use(shared.middleware.errorHandler.pageNotFound); + siteApp.use(errorHandler.pageNotFound); config.get('apps:internal').forEach((appName) => { const app = require(path.join(config.get('paths').internalAppPath, appName)); diff --git a/core/server/services/members/config.js b/core/server/services/members/config.js index 94b210fc3e..d068caaefc 100644 --- a/core/server/services/members/config.js +++ b/core/server/services/members/config.js @@ -16,14 +16,11 @@ class MembersConfigProvider { * @param {{get: (key: string) => any}} options.settingsCache * @param {{get: (key: string) => any}} options.config * @param {any} options.urlUtils - * @param {any} options.logging - * @param {{original: string}} options.ghostVersion */ constructor(options) { this._settingsCache = options.settingsCache; this._config = options.config; this._urlUtils = options.urlUtils; - this._ghostVersion = options.ghostVersion; } /** diff --git a/core/server/services/members/service.js b/core/server/services/members/service.js index 3503c62fd9..c18b81713b 100644 --- a/core/server/services/members/service.js +++ b/core/server/services/members/service.js @@ -13,7 +13,6 @@ const labsService = require('../../../shared/labs'); const settingsCache = require('../../../shared/settings-cache'); const config = require('../../../shared/config'); const models = require('../../models'); -const ghostVersion = require('@tryghost/version'); const _ = require('lodash'); const {GhostMailer} = require('../mail'); const jobsService = require('../jobs'); @@ -35,8 +34,7 @@ const ghostMailer = new GhostMailer(); const membersConfig = new MembersConfigProvider({ config, settingsCache, - urlUtils, - ghostVersion + urlUtils }); let membersApi; diff --git a/core/server/services/notifications/index.js b/core/server/services/notifications/index.js index 781d92e280..9fee2240e4 100644 --- a/core/server/services/notifications/index.js +++ b/core/server/services/notifications/index.js @@ -1,10 +1,8 @@ const settingsCache = require('../../../shared/settings-cache'); -const ghostVersion = require('@tryghost/version'); const Notifications = require('./notifications'); const models = require('../../models'); module.exports.notifications = new Notifications({ settingsCache, - ghostVersion: ghostVersion.full, SettingsModel: models.Settings }); diff --git a/core/server/services/notifications/notifications.js b/core/server/services/notifications/notifications.js index b437d0f64b..15e0298d7a 100644 --- a/core/server/services/notifications/notifications.js +++ b/core/server/services/notifications/notifications.js @@ -3,6 +3,7 @@ const semver = require('semver'); const Promise = require('bluebird'); const _ = require('lodash'); const errors = require('@tryghost/errors'); +const ghostVersion = require('@tryghost/version'); const tpl = require('@tryghost/tpl'); const ObjectId = require('bson-objectid'); @@ -16,12 +17,10 @@ class Notifications { * * @param {Object} options * @param {Object} options.settingsCache - settings cache instance - * @param {String} options.ghostVersion - Ghost instance version in "full" format - major.minor.patch * @param {Object} options.SettingsModel - Ghost's Setting model instance */ - constructor({settingsCache, ghostVersion, SettingsModel}) { + constructor({settingsCache, SettingsModel}) { this.settingsCache = settingsCache; - this.ghostVersion = ghostVersion; this.SettingsModel = SettingsModel; } @@ -74,7 +73,7 @@ class Notifications { browse({user}) { let allNotifications = this.fetchAllNotifications(); allNotifications = _.orderBy(allNotifications, 'addedAt', 'desc'); - const blogVersion = this.ghostVersion.match(/^(\d+\.)(\d+\.)(\d+)/); + const blogVersion = ghostVersion.full.match(/^(\d+\.)(\d+\.)(\d+)/); allNotifications = allNotifications.filter((notification) => { if (notification.createdAtVersion && !this.wasSeen(notification, user)) { @@ -128,7 +127,7 @@ class Notifications { location: 'bottom', status: 'alert', id: ObjectId().toHexString(), - createdAtVersion: this.ghostVersion + createdAtVersion: ghostVersion.full }; const overrides = { diff --git a/core/server/web/admin/app.js b/core/server/web/admin/app.js index 6f56ba58eb..e4743d0864 100644 --- a/core/server/web/admin/app.js +++ b/core/server/web/admin/app.js @@ -5,6 +5,8 @@ const config = require('../../../shared/config'); const constants = require('@tryghost/constants'); const urlUtils = require('../../../shared/url-utils'); const shared = require('../shared'); +const errorHandler = require('@tryghost/mw-error-handler'); +const sentry = require('../../../shared/sentry'); const redirectAdminUrls = require('./middleware/redirect-admin-urls'); module.exports = function setupAdminApp() { @@ -44,8 +46,8 @@ module.exports = function setupAdminApp() { // Finally, routing adminApp.get('*', require('./controller')); - adminApp.use(shared.middleware.errorHandler.pageNotFound); - adminApp.use(shared.middleware.errorHandler.handleHTMLResponse); + adminApp.use(errorHandler.pageNotFound); + adminApp.use(errorHandler.handleHTMLResponse(sentry)); debug('Admin setup end'); diff --git a/core/server/web/api/app.js b/core/server/web/api/app.js index 5a55da0759..13006b2011 100644 --- a/core/server/web/api/app.js +++ b/core/server/web/api/app.js @@ -2,7 +2,8 @@ const debug = require('@tryghost/debug')('web:api:default:app'); const config = require('../../../shared/config'); const express = require('../../../shared/express'); const urlUtils = require('../../../shared/url-utils'); -const errorHandler = require('../shared/middleware/error-handler'); +const sentry = require('../../../shared/sentry'); +const errorHandler = require('@tryghost/mw-error-handler'); module.exports = function setupApiApp() { debug('Parent API setup start'); @@ -26,7 +27,7 @@ module.exports = function setupApiApp() { // Error handling for requests to non-existent API versions apiApp.use(errorHandler.resourceNotFound); - apiApp.use(errorHandler.handleJSONResponse); + apiApp.use(errorHandler.handleJSONResponse(sentry)); debug('Parent API setup end'); return apiApp; diff --git a/core/server/web/api/canary/admin/app.js b/core/server/web/api/canary/admin/app.js index da008f5560..5c8a5ac11a 100644 --- a/core/server/web/api/canary/admin/app.js +++ b/core/server/web/api/canary/admin/app.js @@ -4,6 +4,8 @@ const express = require('../../../../../shared/express'); const bodyParser = require('body-parser'); const shared = require('../../../shared'); const apiMw = require('../../middleware'); +const errorHandler = require('@tryghost/mw-error-handler'); +const sentry = require('../../../../../shared/sentry'); const routes = require('./routes'); module.exports = function setupApiApp() { @@ -30,8 +32,8 @@ module.exports = function setupApiApp() { apiApp.use(routes()); // API error handling - apiApp.use(shared.middleware.errorHandler.resourceNotFound); - apiApp.use(shared.middleware.errorHandler.handleJSONResponseV2); + apiApp.use(errorHandler.resourceNotFound); + apiApp.use(errorHandler.handleJSONResponseV2(sentry)); debug('Admin API canary setup end'); diff --git a/core/server/web/api/canary/content/app.js b/core/server/web/api/canary/content/app.js index 33ff6eb1b7..906e31c30e 100644 --- a/core/server/web/api/canary/content/app.js +++ b/core/server/web/api/canary/content/app.js @@ -2,8 +2,10 @@ const debug = require('@tryghost/debug')('web:api:canary:content:app'); const boolParser = require('express-query-boolean'); const bodyParser = require('body-parser'); const express = require('../../../../../shared/express'); +const sentry = require('../../../../../shared/sentry'); const shared = require('../../../shared'); const routes = require('./routes'); +const errorHandler = require('@tryghost/mw-error-handler'); module.exports = function setupApiApp() { debug('Content API canary setup start'); @@ -24,8 +26,8 @@ module.exports = function setupApiApp() { apiApp.use(routes()); // API error handling - apiApp.use(shared.middleware.errorHandler.resourceNotFound); - apiApp.use(shared.middleware.errorHandler.handleJSONResponse); + apiApp.use(errorHandler.resourceNotFound); + apiApp.use(errorHandler.handleJSONResponse(sentry)); debug('Content API canary setup end'); diff --git a/core/server/web/api/v2/admin/app.js b/core/server/web/api/v2/admin/app.js index 73518ebbd9..cbc8a3cb1d 100644 --- a/core/server/web/api/v2/admin/app.js +++ b/core/server/web/api/v2/admin/app.js @@ -1,10 +1,12 @@ const debug = require('@tryghost/debug')('web:v2:admin:app'); const boolParser = require('express-query-boolean'); const express = require('../../../../../shared/express'); +const sentry = require('../../../../../shared/sentry'); const bodyParser = require('body-parser'); const shared = require('../../../shared'); const apiMw = require('../../middleware'); const routes = require('./routes'); +const errorHandler = require('@tryghost/mw-error-handler'); module.exports = function setupApiApp() { debug('Admin API v2 setup start'); @@ -30,8 +32,8 @@ module.exports = function setupApiApp() { apiApp.use(routes()); // API error handling - apiApp.use(shared.middleware.errorHandler.resourceNotFound); - apiApp.use(shared.middleware.errorHandler.handleJSONResponseV2); + apiApp.use(errorHandler.resourceNotFound); + apiApp.use(errorHandler.handleJSONResponseV2(sentry)); debug('Admin API v2 setup end'); diff --git a/core/server/web/api/v2/content/app.js b/core/server/web/api/v2/content/app.js index 10722576e6..93294c018d 100644 --- a/core/server/web/api/v2/content/app.js +++ b/core/server/web/api/v2/content/app.js @@ -2,8 +2,10 @@ const debug = require('@tryghost/debug')('web:api:v2:content:app'); const boolParser = require('express-query-boolean'); const bodyParser = require('body-parser'); const express = require('../../../../../shared/express'); +const sentry = require('../../../../../shared/sentry'); const shared = require('../../../shared'); const routes = require('./routes'); +const errorHandler = require('@tryghost/mw-error-handler'); module.exports = function setupApiApp() { debug('Content API v2 setup start'); @@ -24,8 +26,8 @@ module.exports = function setupApiApp() { apiApp.use(routes()); // API error handling - apiApp.use(shared.middleware.errorHandler.resourceNotFound); - apiApp.use(shared.middleware.errorHandler.handleJSONResponse); + apiApp.use(errorHandler.resourceNotFound); + apiApp.use(errorHandler.handleJSONResponse(sentry)); debug('Content API v2 setup end'); diff --git a/core/server/web/api/v3/admin/app.js b/core/server/web/api/v3/admin/app.js index e039f21f44..08a906cba6 100644 --- a/core/server/web/api/v3/admin/app.js +++ b/core/server/web/api/v3/admin/app.js @@ -1,10 +1,12 @@ const debug = require('@tryghost/debug')('web:v3:admin:app'); const boolParser = require('express-query-boolean'); const express = require('../../../../../shared/express'); +const sentry = require('../../../../../shared/sentry'); const bodyParser = require('body-parser'); const shared = require('../../../shared'); const apiMw = require('../../middleware'); const routes = require('./routes'); +const errorHandler = require('@tryghost/mw-error-handler'); module.exports = function setupApiApp() { debug('Admin API v3 setup start'); @@ -30,8 +32,8 @@ module.exports = function setupApiApp() { apiApp.use(routes()); // API error handling - apiApp.use(shared.middleware.errorHandler.resourceNotFound); - apiApp.use(shared.middleware.errorHandler.handleJSONResponseV2); + apiApp.use(errorHandler.resourceNotFound); + apiApp.use(errorHandler.handleJSONResponseV2(sentry)); debug('Admin API v3 setup end'); diff --git a/core/server/web/api/v3/content/app.js b/core/server/web/api/v3/content/app.js index 2af8f3b614..4fd2b34836 100644 --- a/core/server/web/api/v3/content/app.js +++ b/core/server/web/api/v3/content/app.js @@ -2,8 +2,10 @@ const debug = require('@tryghost/debug')('web:api:v3:content:app'); const boolParser = require('express-query-boolean'); const bodyParser = require('body-parser'); const express = require('../../../../../shared/express'); +const sentry = require('../../../../../shared/sentry'); const shared = require('../../../shared'); const routes = require('./routes'); +const errorHandler = require('@tryghost/mw-error-handler'); module.exports = function setupApiApp() { debug('Content API v3 setup start'); @@ -24,8 +26,8 @@ module.exports = function setupApiApp() { apiApp.use(routes()); // API error handling - apiApp.use(shared.middleware.errorHandler.resourceNotFound); - apiApp.use(shared.middleware.errorHandler.handleJSONResponse); + apiApp.use(errorHandler.resourceNotFound); + apiApp.use(errorHandler.handleJSONResponse(sentry)); debug('Content API v3 setup end'); diff --git a/core/server/web/members/app.js b/core/server/web/members/app.js index f054a6b4bf..ecf2f8b4ca 100644 --- a/core/server/web/members/app.js +++ b/core/server/web/members/app.js @@ -4,10 +4,12 @@ const cors = require('cors'); const bodyParser = require('body-parser'); const express = require('../../../shared/express'); const urlUtils = require('../../../shared/url-utils'); +const sentry = require('../../../shared/sentry'); const membersService = require('../../services/members'); const middleware = membersService.middleware; const shared = require('../shared'); const labs = require('../../../shared/labs'); +const errorHandler = require('@tryghost/mw-error-handler'); module.exports = function setupMembersApp() { debug('Members App setup start'); @@ -46,12 +48,12 @@ module.exports = function setupMembersApp() { membersApp.post('/api/events', labs.enabledMiddleware('membersActivity'), middleware.loadMemberSession, (req, res, next) => membersService.api.middleware.createEvents(req, res, next)); // API error handling - membersApp.use('/api', shared.middleware.errorHandler.resourceNotFound); - membersApp.use('/api', shared.middleware.errorHandler.handleJSONResponseV2); + membersApp.use('/api', errorHandler.resourceNotFound); + membersApp.use('/api', errorHandler.handleJSONResponseV2(sentry)); // Webhook error handling - membersApp.use('/webhooks', shared.middleware.errorHandler.resourceNotFound); - membersApp.use('/webhooks', shared.middleware.errorHandler.handleJSONResponseV2); + membersApp.use('/webhooks', errorHandler.resourceNotFound); + membersApp.use('/webhooks', errorHandler.handleJSONResponseV2(sentry)); debug('Members App setup end'); diff --git a/core/server/web/shared/middleware/error-handler.js b/core/server/web/shared/middleware/error-handler.js deleted file mode 100644 index 6584ea384e..0000000000 --- a/core/server/web/shared/middleware/error-handler.js +++ /dev/null @@ -1,224 +0,0 @@ -const _ = require('lodash'); -const debug = require('@tryghost/debug')('error-handler'); -const errors = require('@tryghost/errors'); -const tpl = require('@tryghost/tpl'); -const sentry = require('../../../../shared/sentry'); - -const messages = { - pageNotFound: 'Page not found', - resourceNotFound: 'Resource not found', - actions: { - images: { - upload: 'upload image' - } - }, - userMessages: { - BookshelfRelationsError: 'Database error, cannot {action}.', - InternalServerError: 'Internal server error, cannot {action}.', - IncorrectUsageError: 'Incorrect usage error, cannot {action}.', - NotFoundError: 'Resource not found error, cannot {action}.', - BadRequestError: 'Request not understood error, cannot {action}.', - UnauthorizedError: 'Authorisation error, cannot {action}.', - NoPermissionError: 'Permission error, cannot {action}.', - ValidationError: 'Validation error, cannot {action}.', - UnsupportedMediaTypeError: 'Unsupported media error, cannot {action}.', - TooManyRequestsError: 'Too many requests error, cannot {action}.', - MaintenanceError: 'Server down for maintenance, cannot {action}.', - MethodNotAllowedError: 'Method not allowed, cannot {action}.', - RequestEntityTooLargeError: 'Request too large, cannot {action}.', - TokenRevocationError: 'Token is not available, cannot {action}.', - VersionMismatchError: 'Version mismatch error, cannot {action}.', - DataExportError: 'Error exporting content.', - DataImportError: 'Duplicated entry, cannot save {action}.', - DatabaseVersionError: 'Database version compatibility error, cannot {action}.', - EmailError: 'Error sending email!', - ThemeValidationError: 'Theme validation error, cannot {action}.', - HostLimitError: 'Host Limit error, cannot {action}.', - DisabledFeatureError: 'Theme validation error, the {{{helperName}}} helper is not available. Cannot {action}.', - UpdateCollisionError: 'Saving failed! Someone else is editing this post.' - } -}; - -const updateStack = (err) => { - let stackbits = err.stack.split(/\n/g); - - // We build this up backwards, so we always insert at position 1 - - if (process.env.NODE_ENV === 'production' || err.statusCode === 404) { - // In production mode, remove the stack trace - stackbits.splice(1, stackbits.length - 1); - } else { - // In dev mode, clearly mark the strack trace - stackbits.splice(1, 0, `Stack Trace:`); - } - - // Add in our custom cotext and help methods - - if (err.help) { - stackbits.splice(1, 0, `${err.help}`); - } - - if (err.context) { - stackbits.splice(1, 0, `${err.context}`); - } - - return stackbits.join('\n'); -}; - -/** - * Get an error ready to be shown the the user - */ -module.exports.prepareError = (err, req, res, next) => { - debug(err); - - if (Array.isArray(err)) { - err = err[0]; - } - - if (!errors.utils.isGhostError(err)) { - // We need a special case for 404 errors - if (err.statusCode && err.statusCode === 404) { - err = new errors.NotFoundError({ - err: err - }); - } else if (err.stack.match(/node_modules\/handlebars\//)) { - // Temporary handling of theme errors from handlebars - // @TODO remove this when #10496 is solved properly - err = new errors.IncorrectUsageError({ - err: err, - message: err.message, - statusCode: err.statusCode - }); - } else { - err = new errors.InternalServerError({ - err: err, - message: err.message, - statusCode: err.statusCode - }); - } - } - - // used for express logging middleware see core/server/app.js - req.err = err; - - // alternative for res.status(); - res.statusCode = err.statusCode; - - err.stack = updateStack(err); - - // never cache errors - res.set({ - 'Cache-Control': 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0' - }); - - next(err); -}; - -const jsonErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars - res.json({ - errors: [{ - message: err.message, - context: err.context, - help: err.help, - errorType: err.errorType, - errorDetails: err.errorDetails, - ghostErrorCode: err.ghostErrorCode - }] - }); -}; - -const jsonErrorRendererV2 = (err, req, res, next) => { // eslint-disable-line no-unused-vars - const userError = prepareUserMessage(err, req); - - res.json({ - errors: [{ - message: userError.message || null, - context: userError.context || null, - type: err.errorType || null, - details: err.errorDetails || null, - property: err.property || null, - help: err.help || null, - code: err.code || null, - id: err.id || null - }] - }); -}; - -const prepareUserMessage = (err, res) => { - const userError = { - message: err.message, - context: err.context - }; - - const docName = _.get(res, 'frameOptions.docName'); - const method = _.get(res, 'frameOptions.method'); - - if (docName && method) { - let action; - - const actionMap = { - browse: 'list', - read: 'read', - add: 'save', - edit: 'edit', - destroy: 'delete' - }; - - if (_.get(messages.actions, [docName, method])) { - action = tpl(messages.actions[docName][method]); - } else if (Object.keys(actionMap).includes(method)) { - let resource = docName; - - if (method !== 'browse') { - resource = resource.replace(/s$/, ''); - } - - action = `${actionMap[method]} ${resource}`; - } - - if (action) { - if (err.context) { - userError.context = `${err.message} ${err.context}`; - } else { - userError.context = err.message; - } - - userError.message = tpl(messages.userMessages[err.name], {action: action}); - } - } - - return userError; -}; - -module.exports.resourceNotFound = (req, res, next) => { - next(new errors.NotFoundError({message: tpl(messages.resourceNotFound)})); -}; - -module.exports.pageNotFound = (req, res, next) => { - next(new errors.NotFoundError({message: tpl(messages.pageNotFound)})); -}; - -module.exports.handleJSONResponse = [ - // Make sure the error can be served - module.exports.prepareError, - // Handle the error in Sentry - sentry.errorHandler, - // Render the error using JSON format - jsonErrorRenderer -]; - -module.exports.handleJSONResponseV2 = [ - // Make sure the error can be served - module.exports.prepareError, - // Handle the error in Sentry - sentry.errorHandler, - // Render the error using JSON format - jsonErrorRendererV2 -]; - -module.exports.handleHTMLResponse = [ - // Make sure the error can be served - module.exports.prepareError, - // Handle the error in Sentry - sentry.errorHandler -]; diff --git a/core/server/web/shared/middleware/index.js b/core/server/web/shared/middleware/index.js index 768f1314b7..4c8faf4438 100644 --- a/core/server/web/shared/middleware/index.js +++ b/core/server/web/shared/middleware/index.js @@ -11,10 +11,6 @@ module.exports = { return require('./cache-control'); }, - get errorHandler() { - return require('./error-handler'); - }, - get prettyUrls() { return require('./pretty-urls'); }, diff --git a/package.json b/package.json index 8e262d25ec..a93bae218b 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "@tryghost/debug": "0.1.9", "@tryghost/email-analytics-provider-mailgun": "1.0.7", "@tryghost/email-analytics-service": "1.0.5", - "@tryghost/errors": "1.1.1", + "@tryghost/errors": "1.2.0", "@tryghost/express-dynamic-redirects": "0.2.2", "@tryghost/helpers": "1.1.54", "@tryghost/image-transform": "1.0.25", @@ -86,6 +86,7 @@ "@tryghost/members-ssr": "1.0.16", "@tryghost/metrics": "1.0.1", "@tryghost/minifier": "0.1.8", + "@tryghost/mw-error-handler": "0.1.1", "@tryghost/mw-session-from-token": "0.1.26", "@tryghost/nodemailer": "0.3.8", "@tryghost/package-json": "1.0.13", diff --git a/test/unit/server/services/notifications/notifications.test.js b/test/unit/server/services/notifications/notifications.test.js index a423c4fa37..92adc5c24e 100644 --- a/test/unit/server/services/notifications/notifications.test.js +++ b/test/unit/server/services/notifications/notifications.test.js @@ -1,6 +1,7 @@ const should = require('should'); const sinon = require('sinon'); +const ghostVersion = require('@tryghost/version'); const moment = require('moment'); const Notifications = require('../../../../../core/server/services/notifications/notifications'); const {owner} = require('../../../../utils/fixtures/context'); @@ -13,9 +14,9 @@ describe('Notifications Service', function () { get: sinon.fake.returns(existingNotifications) }; + sinon.stub(ghostVersion, 'full').value('4.1.0'); const notificationsSvc = new Notifications({ - settingsCache, - ghostVersion: '4.1.0' + settingsCache }); const {allNotifications, notificationsToAdd} = notificationsSvc.add({ @@ -60,9 +61,9 @@ describe('Notifications Service', function () { }]) }; + sinon.stub(ghostVersion, 'full').value('4.1.0'); const notificationSvc = new Notifications({ - settingsCache, - ghostVersion: '4.1.0' + settingsCache }); const notifications = notificationSvc.browse({user: owner}); @@ -89,9 +90,9 @@ describe('Notifications Service', function () { }]) }; + sinon.stub(ghostVersion, 'full').value('4.0.0'); const notificationSvc = new Notifications({ - settingsCache, - ghostVersion: '4.0.0' + settingsCache }); const notifications = notificationSvc.browse({user: owner}); @@ -118,9 +119,9 @@ describe('Notifications Service', function () { }]) }; + sinon.stub(ghostVersion, 'full').value('3.0.0'); const notificationSvc = new Notifications({ - settingsCache, - ghostVersion: '3.0.0' + settingsCache }); const notifications = notificationSvc.browse({user: owner}); @@ -147,9 +148,9 @@ describe('Notifications Service', function () { }]) }; + sinon.stub(ghostVersion, 'full').value('4.0.0'); const notificationSvc = new Notifications({ - settingsCache, - ghostVersion: '4.0.0' + settingsCache }); const notifications = notificationSvc.browse({user: owner}); @@ -176,9 +177,9 @@ describe('Notifications Service', function () { }]) }; + sinon.stub(ghostVersion, 'full').value('5.0.0'); const notificationSvc = new Notifications({ - settingsCache, - ghostVersion: '5.0.0' + settingsCache }); const notifications = notificationSvc.browse({user: owner}); @@ -218,9 +219,9 @@ describe('Notifications Service', function () { }]) }; + sinon.stub(ghostVersion, 'full').value('4.1.0'); const notificationSvc = new Notifications({ - settingsCache, - ghostVersion: '4.1.0' + settingsCache }); const notifications = notificationSvc.browse({user: owner}); @@ -243,7 +244,6 @@ describe('Notifications Service', function () { const notificationSvc = new Notifications({ settingsCache, - ghostVersion: '5.0.0', SettingsModel: { edit: settingsModelStub } @@ -269,9 +269,9 @@ describe('Notifications Service', function () { }; const settingsModelStub = sinon.stub().resolves(); + sinon.stub(ghostVersion, 'full').value('5.0.0'); const notificationSvc = new Notifications({ settingsCache, - ghostVersion: '5.0.0', SettingsModel: { edit: settingsModelStub } diff --git a/yarn.lock b/yarn.lock index 0782758beb..97f1e19925 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1412,10 +1412,10 @@ "@tryghost/debug" "^0.1.9" lodash "^4.17.20" -"@tryghost/errors@1.1.1", "@tryghost/errors@^1.0.0", "@tryghost/errors@^1.1.0", "@tryghost/errors@^1.1.1": - version "1.1.1" - resolved "https://registry.npmjs.org/@tryghost/errors/-/errors-1.1.1.tgz" - integrity sha512-na0qB5sdy1BWgquzn+m530ohJ3fTeF451xUTR7I8b76TBEL9snnIkXCv5Qdjmnevmgod7aAGsHi2syyKFlvEvQ== +"@tryghost/errors@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@tryghost/errors/-/errors-1.2.0.tgz#989f10434a17286e952b5a9434e50846ea4ad87c" + integrity sha512-80I7LmRgPQt380Bm/90hF8KPkkNqOFHF2T6oO+NXkLd+UTc1qLOfe6nZS17WD9glMmHrqv6IF8U1MjPMDa4VOQ== dependencies: lodash "^4.17.21" uuid "^8.3.2" @@ -1428,6 +1428,14 @@ "@tryghost/ignition-errors" "^0.1.0" lodash "^4.17.21" +"@tryghost/errors@^1.0.0", "@tryghost/errors@^1.1.0", "@tryghost/errors@^1.1.1": + version "1.1.1" + resolved "https://registry.npmjs.org/@tryghost/errors/-/errors-1.1.1.tgz" + integrity sha512-na0qB5sdy1BWgquzn+m530ohJ3fTeF451xUTR7I8b76TBEL9snnIkXCv5Qdjmnevmgod7aAGsHi2syyKFlvEvQ== + dependencies: + lodash "^4.17.21" + uuid "^8.3.2" + "@tryghost/express-dynamic-redirects@0.2.2": version "0.2.2" resolved "https://registry.npmjs.org/@tryghost/express-dynamic-redirects/-/express-dynamic-redirects-0.2.2.tgz" @@ -1712,6 +1720,14 @@ mobiledoc-dom-renderer "0.7.0" mobiledoc-text-renderer "0.4.0" +"@tryghost/mw-error-handler@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@tryghost/mw-error-handler/-/mw-error-handler-0.1.1.tgz#47ad5f534b21ec71db00706f47622d660cde894b" + integrity sha512-c1EMdeU5k6FpB640GxjA2sUsyCuTPW8qlWJu1eZAbX/63YBMZOoBkvGNadUM5hdJ1fGwwFQME2j1vzkQ+qRMHg== + dependencies: + "@tryghost/debug" "^0.1.9" + "@tryghost/tpl" "^0.1.8" + "@tryghost/mw-session-from-token@0.1.26": version "0.1.26" resolved "https://registry.npmjs.org/@tryghost/mw-session-from-token/-/mw-session-from-token-0.1.26.tgz"