From 2887e416da396394ac8b6a15dd4407fbe700f63c Mon Sep 17 00:00:00 2001 From: Sam Lord Date: Wed, 1 Dec 2021 10:22:01 +0000 Subject: [PATCH] Switch to @tryghost/errors from ignition errors package (#13807) refs: TryGhost/Toolbox#147 * Replaces all references to isIgnitionError with isGhostError * Switches use of GhostError to InternalServerError - as GhostError is no longer public There are places where InternalServerError is not the valid error, and new errors should be added to the @tryghost/errors package to ensure that we can use semantically correct errors in those cases. --- core/boot.js | 4 ++-- core/frontend/apps/amp/lib/helpers/amp_content.js | 4 ++-- core/frontend/apps/private-blogging/index.js | 2 +- core/frontend/services/apps/index.js | 2 +- core/frontend/services/helpers/handlebars.js | 2 +- core/frontend/web/middleware/handle-image-sizes.js | 7 ++----- core/server/adapters/scheduling/SchedulingDefault.js | 4 ++-- core/server/adapters/storage/LocalStorageBase.js | 4 ++-- core/server/api/canary/db.js | 4 ++-- core/server/api/canary/session.js | 2 +- core/server/api/canary/slugs.js | 2 +- core/server/api/canary/utils/permissions.js | 4 ++-- core/server/api/v2/db.js | 4 ++-- core/server/api/v2/session.js | 2 +- core/server/api/v2/slugs.js | 2 +- core/server/api/v2/utils/permissions.js | 4 ++-- core/server/api/v3/db.js | 4 ++-- core/server/api/v3/session.js | 2 +- core/server/api/v3/slugs.js | 2 +- core/server/api/v3/utils/permissions.js | 4 ++-- core/server/data/db/state-manager.js | 8 ++++---- core/server/data/exporter/export-filename.js | 2 +- core/server/data/importer/handlers/json.js | 2 +- core/server/data/importer/import-manager.js | 2 +- core/server/data/importer/importers/data/base.js | 2 +- core/server/data/migrations/utils.js | 4 ++-- ...-populate-members-paid-subscription-events-table.js | 2 +- core/server/data/schema/commands.js | 4 ++-- core/server/ghost-server.js | 4 ++-- core/server/lib/image/image-size.js | 4 ++-- core/server/models/base/listeners.js | 4 ++-- core/server/models/relations/authors.js | 2 +- core/server/services/auth/passwordreset.js | 2 +- core/server/services/auth/setup.js | 2 +- core/server/services/mega/mega.js | 6 +++--- core/server/services/oembed.js | 4 ++-- core/server/services/permissions/can-this.js | 2 +- core/server/services/redirects/api.js | 4 ++-- .../route-settings/default-settings-manager.js | 2 +- core/server/services/route-settings/route-settings.js | 2 +- core/server/services/route-settings/settings-loader.js | 8 ++++---- core/server/services/route-settings/yaml-parser.js | 2 +- core/server/services/slack.js | 2 +- core/server/services/themes/storage.js | 4 ++-- core/server/services/xmlrpc.js | 4 ++-- core/server/web/api/canary/admin/middleware.js | 2 +- core/server/web/api/v2/admin/middleware.js | 2 +- core/server/web/api/v3/admin/middleware.js | 2 +- core/server/web/shared/middleware/error-handler.js | 4 ++-- core/shared/sentry.js | 2 +- package.json | 2 +- test/regression/models/model_posts.test.js | 2 +- test/unit/frontend/services/url/UrlService.test.js | 2 +- test/unit/server/data/migrations/utils.test.js | 4 ++-- test/unit/server/data/schema/commands.test.js | 4 ++-- test/unit/server/services/mega/mega.test.js | 8 ++++---- .../server/services/settings/settings-loader.test.js | 2 +- test/utils/api.js | 4 ++-- yarn.lock | 10 +++++++++- 59 files changed, 102 insertions(+), 97 deletions(-) diff --git a/core/boot.js b/core/boot.js index c633fbc193..57e308d85e 100644 --- a/core/boot.js +++ b/core/boot.js @@ -404,8 +404,8 @@ async function bootGhost({backend = true, frontend = true} = {}) { // Ensure the error we have is an ignition error let serverStartError = error; - if (!errors.utils.isIgnitionError(serverStartError)) { - serverStartError = new errors.GhostError({message: serverStartError.message, err: serverStartError}); + if (!errors.utils.isGhostError(serverStartError)) { + serverStartError = new errors.InternalServerError({message: serverStartError.message, err: serverStartError}); } logging.error(serverStartError); diff --git a/core/frontend/apps/amp/lib/helpers/amp_content.js b/core/frontend/apps/amp/lib/helpers/amp_content.js index 68fd196397..f5f48b0322 100644 --- a/core/frontend/apps/amp/lib/helpers/amp_content.js +++ b/core/frontend/apps/amp/lib/helpers/amp_content.js @@ -143,7 +143,7 @@ function getAmperizeHTML(html, post) { if (err) { if (err.src) { // This is a valid 500 GhostError because it means the amperize parser is unable to handle some Ghost HTML. - logging.error(new errors.GhostError({ + logging.error(new errors.InternalServerError({ message: `AMP HTML couldn't be parsed: ${err.src}`, code: 'AMP_PARSER_ERROR', err: err, @@ -151,7 +151,7 @@ function getAmperizeHTML(html, post) { help: 'Please share this error on GitHub or https://forum.ghost.org' })); } else { - logging.error(new errors.GhostError({err, code: 'AMP_PARSER_ERROR'})); + logging.error(new errors.InternalServerError({err, code: 'AMP_PARSER_ERROR'})); } // save it in cache to prevent multiple calls to Amperize until diff --git a/core/frontend/apps/private-blogging/index.js b/core/frontend/apps/private-blogging/index.js index 12904385d8..baf21f234d 100644 --- a/core/frontend/apps/private-blogging/index.js +++ b/core/frontend/apps/private-blogging/index.js @@ -24,7 +24,7 @@ let checkSubdir = function checkSubdir() { paths = urlUtils.getSubdir().split('/'); if (paths.pop() === PRIVATE_KEYWORD) { - logging.error(new errors.GhostError({ + logging.error(new errors.InternalServerError({ message: tpl(messages.urlCannotContainPrivateSubdir.error), context: tpl(messages.urlCannotContainPrivateSubdir.description), help: tpl(messages.urlCannotContainPrivateSubdir.help) diff --git a/core/frontend/services/apps/index.js b/core/frontend/services/apps/index.js index 33880a02c1..a8bcc2c84b 100644 --- a/core/frontend/services/apps/index.js +++ b/core/frontend/services/apps/index.js @@ -18,7 +18,7 @@ module.exports = { return Promise.map(appsToLoad, appName => loader.activateAppByName(appName)) .catch(function (err) { - logging.error(new errors.GhostError({ + logging.error(new errors.InternalServerError({ err: err, context: tpl(messages.appWillNotBeLoadedError), help: tpl(messages.appWillNotBeLoadedHelp) diff --git a/core/frontend/services/helpers/handlebars.js b/core/frontend/services/helpers/handlebars.js index a071ec7d75..f9a29624ba 100644 --- a/core/frontend/services/helpers/handlebars.js +++ b/core/frontend/services/helpers/handlebars.js @@ -17,7 +17,7 @@ function asyncHelperWrapper(hbsInstance, name, fn) { Promise.resolve(fn.call(this, context, options)).then(function asyncHelperSuccess(result) { cb(result); }).catch(function asyncHelperError(err) { - const wrappedErr = err instanceof errors.GhostError ? err : new errors.IncorrectUsageError({ + const wrappedErr = errors.utils.isGhostError(err) ? err : new errors.IncorrectUsageError({ err: err, context: 'registerAsyncThemeHelper: ' + name, errorDetails: { diff --git a/core/frontend/web/middleware/handle-image-sizes.js b/core/frontend/web/middleware/handle-image-sizes.js index d147cc79c9..963ca25e06 100644 --- a/core/frontend/web/middleware/handle-image-sizes.js +++ b/core/frontend/web/middleware/handle-image-sizes.js @@ -1,6 +1,6 @@ const _ = require('lodash'); const path = require('path'); -const {GhostError} = require('@tryghost/errors'); +const {NoContentError} = require('@tryghost/errors'); const imageTransform = require('@tryghost/image-transform'); const storage = require('../../../server/adapters/storage'); const activeTheme = require('../../services/theme-engine/active'); @@ -102,10 +102,7 @@ module.exports = function (req, res, next) { }) .then((originalImageBuffer) => { if (originalImageBuffer.length <= 0) { - throw new GhostError({ - errorType: 'NoContentError', - statusCode: 204 - }); + throw new NoContentError(); } return imageTransform.resizeFromBuffer(originalImageBuffer, imageDimensionConfig); }) diff --git a/core/server/adapters/scheduling/SchedulingDefault.js b/core/server/adapters/scheduling/SchedulingDefault.js index 95f4f75042..b54a336c4b 100644 --- a/core/server/adapters/scheduling/SchedulingDefault.js +++ b/core/server/adapters/scheduling/SchedulingDefault.js @@ -307,7 +307,7 @@ SchedulingDefault.prototype._pingUrl = function (object) { this._pingUrl(object); }, this.retryTimeoutInMs); - logging.error(new errors.GhostError({ + logging.error(new errors.InternalServerError({ err, context: 'Retrying...', level: 'normal' @@ -316,7 +316,7 @@ SchedulingDefault.prototype._pingUrl = function (object) { return; } - logging.error(new errors.GhostError({ + logging.error(new errors.InternalServerError({ err, level: 'critical' })); diff --git a/core/server/adapters/storage/LocalStorageBase.js b/core/server/adapters/storage/LocalStorageBase.js index 8ac5d81fe6..bc2969a19b 100644 --- a/core/server/adapters/storage/LocalStorageBase.js +++ b/core/server/adapters/storage/LocalStorageBase.js @@ -147,7 +147,7 @@ class LocalStorageBase extends StorageBase { return next(new errors.NoPermissionError({err: err})); } - return next(new errors.GhostError({err: err})); + return next(new errors.InternalServerError({err: err})); } next(); @@ -196,7 +196,7 @@ class LocalStorageBase extends StorageBase { return reject(new errors.NoPermissionError({err: err})); } - return reject(new errors.GhostError({ + return reject(new errors.InternalServerError({ err: err, message: tpl(this.errorMessages.cannotRead, {file: options.path}) })); diff --git a/core/server/api/canary/db.js b/core/server/api/canary/db.js index e4d3104af9..8203166936 100644 --- a/core/server/api/canary/db.js +++ b/core/server/api/canary/db.js @@ -62,7 +62,7 @@ module.exports = { return Promise.resolve() .then(() => exporter.doExport({include: frame.options.withRelated})) .catch((err) => { - return Promise.reject(new errors.GhostError({err: err})); + return Promise.reject(new errors.InternalServerError({err: err})); }); } }, @@ -124,7 +124,7 @@ module.exports = { }, {concurrency: 100}); }) .catch((err) => { - throw new errors.GhostError({ + throw new errors.InternalServerError({ err: err }); }); diff --git a/core/server/api/canary/session.js b/core/server/api/canary/session.js index b77c1d5e3b..2ef3bd51d5 100644 --- a/core/server/api/canary/session.js +++ b/core/server/api/canary/session.js @@ -42,7 +42,7 @@ const session = { }); }); }).catch(async (err) => { - if (!errors.utils.isIgnitionError(err)) { + if (!errors.utils.isGhostError(err)) { throw new errors.UnauthorizedError({ message: tpl(messages.accessDenied), err diff --git a/core/server/api/canary/slugs.js b/core/server/api/canary/slugs.js index b29904c46f..f423824061 100644 --- a/core/server/api/canary/slugs.js +++ b/core/server/api/canary/slugs.js @@ -43,7 +43,7 @@ module.exports = { return models.Base.Model.generateSlug(allowedTypes[frame.options.type], frame.data.name, {status: 'all'}) .then((slug) => { if (!slug) { - return Promise.reject(new errors.GhostError({ + return Promise.reject(new errors.InternalServerError({ message: tpl(messages.couldNotGenerateSlug) })); } diff --git a/core/server/api/canary/utils/permissions.js b/core/server/api/canary/utils/permissions.js index 17634397df..5529fbca37 100644 --- a/core/server/api/canary/utils/permissions.js +++ b/core/server/api/canary/utils/permissions.js @@ -66,11 +66,11 @@ const nonePublicAuth = (apiConfig, frame) => { return Promise.reject(err); } - if (errors.utils.isIgnitionError(err)) { + if (errors.utils.isGhostError(err)) { return Promise.reject(err); } - return Promise.reject(new errors.GhostError({ + return Promise.reject(new errors.InternalServerError({ err: err })); }); diff --git a/core/server/api/v2/db.js b/core/server/api/v2/db.js index e6b1a07ab6..a4bff75ae1 100644 --- a/core/server/api/v2/db.js +++ b/core/server/api/v2/db.js @@ -51,7 +51,7 @@ module.exports = { return Promise.resolve() .then(() => exporter.doExport({include: frame.options.withRelated})) .catch((err) => { - return Promise.reject(new errors.GhostError({err: err})); + return Promise.reject(new errors.InternalServerError({err: err})); }); } }, @@ -107,7 +107,7 @@ module.exports = { }, {concurrency: 100}); }) .catch((err) => { - throw new errors.GhostError({ + throw new errors.InternalServerError({ err: err }); }); diff --git a/core/server/api/v2/session.js b/core/server/api/v2/session.js index 9687a71921..b5cd8d452d 100644 --- a/core/server/api/v2/session.js +++ b/core/server/api/v2/session.js @@ -42,7 +42,7 @@ const session = { }); }); }).catch(async (err) => { - if (!errors.utils.isIgnitionError(err)) { + if (!errors.utils.isGhostError(err)) { throw new errors.UnauthorizedError({ message: tpl(messages.authAccessDenied), err diff --git a/core/server/api/v2/slugs.js b/core/server/api/v2/slugs.js index abe2aa2a22..5d491c9385 100644 --- a/core/server/api/v2/slugs.js +++ b/core/server/api/v2/slugs.js @@ -40,7 +40,7 @@ module.exports = { return models.Base.Model.generateSlug(allowedTypes[frame.options.type], frame.data.name, {status: 'all'}) .then((slug) => { if (!slug) { - return Promise.reject(new errors.GhostError({ + return Promise.reject(new errors.InternalServerError({ message: tpl(messages.couldNotGenerateSlug) })); } diff --git a/core/server/api/v2/utils/permissions.js b/core/server/api/v2/utils/permissions.js index 3880db95d2..9e54391a19 100644 --- a/core/server/api/v2/utils/permissions.js +++ b/core/server/api/v2/utils/permissions.js @@ -62,11 +62,11 @@ const nonePublicAuth = (apiConfig, frame) => { return Promise.reject(err); } - if (errors.utils.isIgnitionError(err)) { + if (errors.utils.isGhostError(err)) { return Promise.reject(err); } - return Promise.reject(new errors.GhostError({ + return Promise.reject(new errors.InternalServerError({ err: err })); }); diff --git a/core/server/api/v3/db.js b/core/server/api/v3/db.js index 9c391b2144..6edab7500a 100644 --- a/core/server/api/v3/db.js +++ b/core/server/api/v3/db.js @@ -62,7 +62,7 @@ module.exports = { return Promise.resolve() .then(() => exporter.doExport({include: frame.options.withRelated})) .catch((err) => { - return Promise.reject(new errors.GhostError({err: err})); + return Promise.reject(new errors.InternalServerError({err: err})); }); } }, @@ -118,7 +118,7 @@ module.exports = { }, {concurrency: 100}); }) .catch((err) => { - throw new errors.GhostError({ + throw new errors.InternalServerError({ err: err }); }); diff --git a/core/server/api/v3/session.js b/core/server/api/v3/session.js index f69a9af77c..657ab5a366 100644 --- a/core/server/api/v3/session.js +++ b/core/server/api/v3/session.js @@ -42,7 +42,7 @@ const session = { }); }); }).catch(async (err) => { - if (!errors.utils.isIgnitionError(err)) { + if (!errors.utils.isGhostError(err)) { throw new errors.UnauthorizedError({ message: tpl(messages.accessDenied), err diff --git a/core/server/api/v3/slugs.js b/core/server/api/v3/slugs.js index 459b7ce41e..187baaf8b7 100644 --- a/core/server/api/v3/slugs.js +++ b/core/server/api/v3/slugs.js @@ -39,7 +39,7 @@ module.exports = { return models.Base.Model.generateSlug(allowedTypes[frame.options.type], frame.data.name, {status: 'all'}) .then((slug) => { if (!slug) { - return Promise.reject(new errors.GhostError({message: tpl(messages.couldNotGenerateSlug)})); + return Promise.reject(new errors.InternalServerError({message: tpl(messages.couldNotGenerateSlug)})); } return slug; }); diff --git a/core/server/api/v3/utils/permissions.js b/core/server/api/v3/utils/permissions.js index ad3a4da105..5834425300 100644 --- a/core/server/api/v3/utils/permissions.js +++ b/core/server/api/v3/utils/permissions.js @@ -66,11 +66,11 @@ const nonePublicAuth = (apiConfig, frame) => { return Promise.reject(err); } - if (errors.utils.isIgnitionError(err)) { + if (errors.utils.isGhostError(err)) { return Promise.reject(err); } - return Promise.reject(new errors.GhostError({ + return Promise.reject(new errors.InternalServerError({ err: err })); }); diff --git a/core/server/data/db/state-manager.js b/core/server/data/db/state-manager.js index 86482cece3..cb7bd8ae27 100644 --- a/core/server/data/db/state-manager.js +++ b/core/server/data/db/state-manager.js @@ -59,8 +59,8 @@ class DatabaseStateManager { // CASE: database connection errors, unknown cases let errorToThrow = error; - if (!errors.utils.isIgnitionError(errorToThrow)) { - errorToThrow = new errors.GhostError({message: errorToThrow.message, err: errorToThrow}); + if (!errors.utils.isGhostError(errorToThrow)) { + errorToThrow = new errors.InternalServerError({message: errorToThrow.message, err: errorToThrow}); } throw errorToThrow; @@ -94,8 +94,8 @@ class DatabaseStateManager { } } catch (error) { let errorToThrow = error; - if (!errors.utils.isIgnitionError(error)) { - errorToThrow = new errors.GhostError({message: errorToThrow.message, err: errorToThrow}); + if (!errors.utils.isGhostError(error)) { + errorToThrow = new errors.InternalServerError({message: errorToThrow.message, err: errorToThrow}); } throw errorToThrow; diff --git a/core/server/data/exporter/export-filename.js b/core/server/data/exporter/export-filename.js index dbc0d3e065..c2564d941a 100644 --- a/core/server/data/exporter/export-filename.js +++ b/core/server/data/exporter/export-filename.js @@ -26,7 +26,7 @@ const exportFileName = async function exportFileName(options) { return title + 'ghost.' + datetime + '.json'; } catch (err) { - logging.error(new errors.GhostError({err: err})); + logging.error(new errors.InternalServerError({err: err})); return 'ghost.' + datetime + '.json'; } }; diff --git a/core/server/data/importer/handlers/json.js b/core/server/data/importer/handlers/json.js index 8e00a2a02d..3055f1b700 100644 --- a/core/server/data/importer/handlers/json.js +++ b/core/server/data/importer/handlers/json.js @@ -30,7 +30,7 @@ JSONHandler = { // if importData follows JSON-API format `{ db: [exportedData] }` if (_.keys(importData).length === 1) { if (!importData.db || !Array.isArray(importData.db)) { - throw new errors.GhostError({ + throw new errors.InternalServerError({ message: tpl(messages.invalidJsonFormat) }); } diff --git a/core/server/data/importer/import-manager.js b/core/server/data/importer/import-manager.js index 150b25a484..db28683c95 100644 --- a/core/server/data/importer/import-manager.js +++ b/core/server/data/importer/import-manager.js @@ -121,7 +121,7 @@ class ImportManager { fs.remove(self.fileToDelete, function (err) { if (err) { - logging.error(new errors.GhostError({ + logging.error(new errors.InternalServerError({ err: err, context: tpl(messages.couldNotCleanUpFile.error), help: tpl(messages.couldNotCleanUpFile.context) diff --git a/core/server/data/importer/importers/data/base.js b/core/server/data/importer/importers/data/base.js index 8c96da89e3..5447a406ed 100644 --- a/core/server/data/importer/importers/data/base.js +++ b/core/server/data/importer/importers/data/base.js @@ -145,7 +145,7 @@ class Base { }); } } else { - if (!errors.utils.isIgnitionError(err)) { + if (!errors.utils.isGhostError(err)) { err = new errors.DataImportError({ message: err.message, context: JSON.stringify(obj), diff --git a/core/server/data/migrations/utils.js b/core/server/data/migrations/utils.js index 5517fa6dd0..3980f43e22 100644 --- a/core/server/data/migrations/utils.js +++ b/core/server/data/migrations/utils.js @@ -143,7 +143,7 @@ function addPermissionToRole(config) { }).first(); if (!permission) { - throw new errors.GhostError({ + throw new errors.InternalServerError({ message: tpl(messages.permissionRoleActionError, { action: 'add', permission: config.permission, @@ -158,7 +158,7 @@ function addPermissionToRole(config) { }).first(); if (!role) { - throw new errors.GhostError({ + throw new errors.InternalServerError({ message: tpl(messages.permissionRoleActionError, { action: 'add', permission: config.permission, diff --git a/core/server/data/migrations/versions/4.0/25-populate-members-paid-subscription-events-table.js b/core/server/data/migrations/versions/4.0/25-populate-members-paid-subscription-events-table.js index 41880fe4da..5a4e4691c3 100644 --- a/core/server/data/migrations/versions/4.0/25-populate-members-paid-subscription-events-table.js +++ b/core/server/data/migrations/versions/4.0/25-populate-members-paid-subscription-events-table.js @@ -44,7 +44,7 @@ module.exports = createTransactionalMigration( return amount * 30; } - throw new errors.GhostError({ + throw new errors.InternalServerError({ message: tpl(messages.unknownSubscriptionIntervalError , { interval }) diff --git a/core/server/data/schema/commands.js b/core/server/data/schema/commands.js index 7743619f2c..c6c53be4f5 100644 --- a/core/server/data/schema/commands.js +++ b/core/server/data/schema/commands.js @@ -139,7 +139,7 @@ async function hasForeignSQLite({fromTable, fromColumn, toTable, toColumn, trans const client = knex.client.config.client; if (client !== 'sqlite3') { - throw new errors.GhostError({ + throw new errors.InternalServerError({ message: tpl(messages.hasForeignSQLite3) }); } @@ -265,7 +265,7 @@ async function hasPrimaryKeySQLite(tableName, transaction) { const client = knex.client.config.client; if (client !== 'sqlite3') { - throw new errors.GhostError({ + throw new errors.InternalServerError({ message: tpl(messages.hasPrimaryKeySQLiteError) }); } diff --git a/core/server/ghost-server.js b/core/server/ghost-server.js index 6627f0ca2a..0b52fdb3fd 100644 --- a/core/server/ghost-server.js +++ b/core/server/ghost-server.js @@ -107,13 +107,13 @@ class GhostServer { let ghostError; if (error.code === 'EADDRINUSE') { - ghostError = new errors.GhostError({ + ghostError = new errors.InternalServerError({ message: tpl(messages.addressInUse.error), context: tpl(messages.addressInUse.context, {port: config.get('server').port}), help: tpl(messages.addressInUse.help) }); } else { - ghostError = new errors.GhostError({ + ghostError = new errors.InternalServerError({ message: tpl(messages.otherError.error, {errorNumber: error.errno}), context: tpl(messages.otherError.context), help: tpl(messages.otherError.help) diff --git a/core/server/lib/image/image-size.js b/core/server/lib/image/image-size.js index 0efc20940f..0c8672d12f 100644 --- a/core/server/lib/image/image-size.js +++ b/core/server/lib/image/image-size.js @@ -177,7 +177,7 @@ class ImageSize { context: err.url || imagePath })); }).catch(function (err) { - if (errors.utils.isIgnitionError(err)) { + if (errors.utils.isGhostError(err)) { return Promise.reject(err); } @@ -241,7 +241,7 @@ class ImageSize { } })); }).catch((err) => { - if (errors.utils.isIgnitionError(err)) { + if (errors.utils.isGhostError(err)) { return Promise.reject(err); } diff --git a/core/server/models/base/listeners.js b/core/server/models/base/listeners.js index 3e357d908c..23d64e91b7 100644 --- a/core/server/models/base/listeners.js +++ b/core/server/models/base/listeners.js @@ -69,13 +69,13 @@ events.on('settings.timezone.edited', function (settingModel, options) { try { await models.Post.edit(post.toJSON(), _.merge({id: post.id}, options)); } catch (err) { - logging.error(new errors.GhostError({ + logging.error(new errors.InternalServerError({ err })); } }); } catch (err) { - logging.error(new errors.GhostError({ + logging.error(new errors.InternalServerError({ err: err, level: 'critical' })); diff --git a/core/server/models/relations/authors.js b/core/server/models/relations/authors.js index c252a2054a..6469dcaeb3 100644 --- a/core/server/models/relations/authors.js +++ b/core/server/models/relations/authors.js @@ -324,7 +324,7 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) { .then(() => response); }) .catch((err) => { - throw new errors.GhostError({err: err}); + throw new errors.InternalServerError({err: err}); }); }); diff --git a/core/server/services/auth/passwordreset.js b/core/server/services/auth/passwordreset.js index 47c4117f19..d44fc4f565 100644 --- a/core/server/services/auth/passwordreset.js +++ b/core/server/services/auth/passwordreset.js @@ -148,7 +148,7 @@ function doReset(options, tokenParts, settingsAPI) { return Promise.reject(err); }) .catch((err) => { - if (errors.utils.isIgnitionError(err)) { + if (errors.utils.isGhostError(err)) { return Promise.reject(err); } return Promise.reject(new errors.UnauthorizedError({err: err})); diff --git a/core/server/services/auth/setup.js b/core/server/services/auth/setup.js index a76ee0cfca..07943f6075 100644 --- a/core/server/services/auth/setup.js +++ b/core/server/services/auth/setup.js @@ -59,7 +59,7 @@ async function setupUser(userData) { const owner = await models.User.findOne({role: 'Owner', status: 'all'}); if (!owner) { - throw new errors.GhostError({ + throw new errors.InternalServerError({ message: tpl(messages.setupUnableToRun) }); } diff --git a/core/server/services/mega/mega.js b/core/server/services/mega/mega.js index e7bfcf3d93..621bbc5f30 100644 --- a/core/server/services/mega/mega.js +++ b/core/server/services/mega/mega.js @@ -131,7 +131,7 @@ const transformEmailRecipientFilter = (emailRecipientFilter, {errorProperty = 'e // `paid` and `free` were swapped out for NQL filters in 4.5.0, we shouldn't see them here now case 'paid': case 'free': - throw new errors.GhostError({ + throw new errors.InternalServerError({ message: tpl(messages.unexpectedFilterError, { property: errorProperty, value: emailRecipientFilter @@ -140,7 +140,7 @@ const transformEmailRecipientFilter = (emailRecipientFilter, {errorProperty = 'e case 'all': return 'subscribed:true'; case 'none': - throw new errors.GhostError({ + throw new errors.InternalServerError({ message: tpl(messages.noneFilterError, { property: errorProperty }) @@ -352,7 +352,7 @@ async function sendEmailJob({emailModel, options}) { error: errorMessage }, {patch: true}); - throw new errors.GhostError({ + throw new errors.InternalServerError({ err: error, context: tpl(messages.sendEmailRequestFailed) }); diff --git a/core/server/services/oembed.js b/core/server/services/oembed.js index d5a3bf5c95..ccf86682e7 100644 --- a/core/server/services/oembed.js +++ b/core/server/services/oembed.js @@ -314,12 +314,12 @@ class OEmbed { return data; } catch (err) { // allow specific validation errors through for better error messages - if (errors.utils.isIgnitionError(err) && err.errorType === 'ValidationError') { + if (errors.utils.isGhostError(err) && err.errorType === 'ValidationError') { throw err; } // log the real error because we're going to throw a generic "Unknown provider" error - logging.error(new errors.GhostError({ + logging.error(new errors.InternalServerError({ message: 'Encountered error when fetching oembed', err })); diff --git a/core/server/services/permissions/can-this.js b/core/server/services/permissions/can-this.js index a7324f3488..d8cc99aba1 100644 --- a/core/server/services/permissions/can-this.js +++ b/core/server/services/permissions/can-this.js @@ -128,7 +128,7 @@ CanThisResult.prototype.beginCheck = function (context) { context = parseContext(context); if (actionsMap.empty()) { - throw new errors.GhostError({message: tpl(messages.noActionsMapFoundError)}); + throw new errors.InternalServerError({message: tpl(messages.noActionsMapFoundError)}); } // Kick off loading of user permissions if necessary diff --git a/core/server/services/redirects/api.js b/core/server/services/redirects/api.js index 05aa00cb25..5241f35d90 100644 --- a/core/server/services/redirects/api.js +++ b/core/server/services/redirects/api.js @@ -34,7 +34,7 @@ const readRedirectsFile = async (redirectsPath) => { return ''; } - if (errors.utils.isIgnitionError(err)) { + if (errors.utils.isGhostError(err)) { throw err; } @@ -162,7 +162,7 @@ class CustomRedirectsAPI { } } } catch (err) { - if (errors.utils.isIgnitionError(err)) { + if (errors.utils.isGhostError(err)) { logging.error(err); } else { logging.error(new errors.IncorrectUsageError({ diff --git a/core/server/services/route-settings/default-settings-manager.js b/core/server/services/route-settings/default-settings-manager.js index b2f0628279..67e3d3a086 100644 --- a/core/server/services/route-settings/default-settings-manager.js +++ b/core/server/services/route-settings/default-settings-manager.js @@ -48,7 +48,7 @@ class DefaultSettingsManager { }); }).catch((error) => { // CASE: we might have a permission error, as we can't access the directory - throw new errors.GhostError({ + throw new errors.InternalServerError({ message: tpl(messages.ensureSettings, { path: this.destinationFolderPath }), diff --git a/core/server/services/route-settings/route-settings.js b/core/server/services/route-settings/route-settings.js index cc4dbef5b0..cc7ada5117 100644 --- a/core/server/services/route-settings/route-settings.js +++ b/core/server/services/route-settings/route-settings.js @@ -90,7 +90,7 @@ class RouteSettings { return Promise.resolve([]); } - if (errors.utils.isIgnitionError(err)) { + if (errors.utils.isGhostError(err)) { throw err; } diff --git a/core/server/services/route-settings/settings-loader.js b/core/server/services/route-settings/settings-loader.js index f2799fc0fb..bcd6a12869 100644 --- a/core/server/services/route-settings/settings-loader.js +++ b/core/server/services/route-settings/settings-loader.js @@ -36,11 +36,11 @@ class SettingsLoader { return validate(object); } catch (err) { - if (errors.utils.isIgnitionError(err)) { + if (errors.utils.isGhostError(err)) { throw err; } - throw new errors.GhostError({ + throw new errors.InternalServerError({ message: tpl(messages.settingsLoaderError, { setting: 'routes', path: this.settingFilePath @@ -66,11 +66,11 @@ class SettingsLoader { return validate(object); } catch (err) { - if (errors.utils.isIgnitionError(err)) { + if (errors.utils.isGhostError(err)) { throw err; } - throw new errors.GhostError({ + throw new errors.InternalServerError({ message: tpl(messages.settingsLoaderError, { setting: 'routes', path: this.settingFilePath diff --git a/core/server/services/route-settings/yaml-parser.js b/core/server/services/route-settings/yaml-parser.js index 70908fa618..b851d8664b 100644 --- a/core/server/services/route-settings/yaml-parser.js +++ b/core/server/services/route-settings/yaml-parser.js @@ -35,7 +35,7 @@ module.exports = function parseYaml(file) { return parsed; } catch (error) { - if (errors.utils.isIgnitionError(error)) { + if (errors.utils.isGhostError(error)) { throw error; } diff --git a/core/server/services/slack.js b/core/server/services/slack.js index 8be914ba1f..8bdbed5e3e 100644 --- a/core/server/services/slack.js +++ b/core/server/services/slack.js @@ -136,7 +136,7 @@ function ping(post) { 'Content-type': 'application/json' } }).catch(function (err) { - logging.error(new errors.GhostError({ + logging.error(new errors.InternalServerError({ err: err, context: tpl(messages.requestFailedError, {service: 'slack'}), help: tpl(messages.requestFailedHelp, {url: 'https://ghost.org/docs/'}) diff --git a/core/server/services/themes/storage.js b/core/server/services/themes/storage.js index a190ad2edb..9a95981c30 100644 --- a/core/server/services/themes/storage.js +++ b/core/server/services/themes/storage.js @@ -112,7 +112,7 @@ module.exports = { if (checkedTheme) { fs.remove(checkedTheme.path) .catch((err) => { - logging.error(new errors.GhostError({err: err})); + logging.error(new errors.InternalServerError({err: err})); }); } @@ -120,7 +120,7 @@ module.exports = { getStorage() .delete(backupName) .catch((err) => { - logging.error(new errors.GhostError({err: err})); + logging.error(new errors.InternalServerError({err: err})); }); } }, diff --git a/core/server/services/xmlrpc.js b/core/server/services/xmlrpc.js index a1f219c84c..85e80c261f 100644 --- a/core/server/services/xmlrpc.js +++ b/core/server/services/xmlrpc.js @@ -87,7 +87,7 @@ function ping(post) { if (!goodResponse.test(res.body)) { const matches = res.body.match(errorMessage); const message = matches ? matches[1] : res.body; - throw new errors.GhostError({message}); + throw new errors.InternalServerError({message}); } }) .catch(function (err) { @@ -100,7 +100,7 @@ function ping(post) { help: tpl(messages.requestFailedHelp, {url: 'https://ghost.org/docs/'}) }); } else { - error = new errors.GhostError({ + error = new errors.InternalServerError({ err: err, message: err.message, context: tpl(messages.requestFailedError, {service: 'xmlrpc'}), diff --git a/core/server/web/api/canary/admin/middleware.js b/core/server/web/api/canary/admin/middleware.js index 823103ab59..2fb250e3a7 100644 --- a/core/server/web/api/canary/admin/middleware.js +++ b/core/server/web/api/canary/admin/middleware.js @@ -44,7 +44,7 @@ const notImplemented = function (req, res, next) { } } - next(new errors.GhostError({ + next(new errors.InternalServerError({ errorType: 'NotImplementedError', message: tpl(messages.notImplemented), statusCode: '501' diff --git a/core/server/web/api/v2/admin/middleware.js b/core/server/web/api/v2/admin/middleware.js index f80454a91c..4a43d0e8bd 100644 --- a/core/server/web/api/v2/admin/middleware.js +++ b/core/server/web/api/v2/admin/middleware.js @@ -40,7 +40,7 @@ const notImplemented = function (req, res, next) { } } - next(new errors.GhostError({ + next(new errors.InternalServerError({ errorType: 'NotImplementedError', message: tpl(messages.notImplemented), statusCode: '501' diff --git a/core/server/web/api/v3/admin/middleware.js b/core/server/web/api/v3/admin/middleware.js index 823103ab59..2fb250e3a7 100644 --- a/core/server/web/api/v3/admin/middleware.js +++ b/core/server/web/api/v3/admin/middleware.js @@ -44,7 +44,7 @@ const notImplemented = function (req, res, next) { } } - next(new errors.GhostError({ + next(new errors.InternalServerError({ errorType: 'NotImplementedError', message: tpl(messages.notImplemented), statusCode: '501' diff --git a/core/server/web/shared/middleware/error-handler.js b/core/server/web/shared/middleware/error-handler.js index db74f5112d..6421adc468 100644 --- a/core/server/web/shared/middleware/error-handler.js +++ b/core/server/web/shared/middleware/error-handler.js @@ -75,14 +75,14 @@ module.exports.prepareError = (err, req, res, next) => { err = err[0]; } - if (!errors.utils.isIgnitionError(err)) { + 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 { - err = new errors.GhostError({ + err = new errors.InternalServerError({ err: err, message: err.message, statusCode: err.statusCode diff --git a/core/shared/sentry.js b/core/shared/sentry.js index 71223caadc..8c62ee85c6 100644 --- a/core/shared/sentry.js +++ b/core/shared/sentry.js @@ -18,7 +18,7 @@ if (sentryConfig && !sentryConfig.disabled) { shouldHandleError(error) { // Sometimes non-Ghost issues will come into here but they won't // have a statusCode so we should always handle them - if (!errors.utils.isIgnitionError(error)) { + if (!errors.utils.isGhostError(error)) { return true; } diff --git a/package.json b/package.json index e1e34e5912..85877f7a0b 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "@tryghost/debug": "0.1.9", "@tryghost/email-analytics-provider-mailgun": "1.0.5", "@tryghost/email-analytics-service": "1.0.4", - "@tryghost/errors": "0.2.17", + "@tryghost/errors": "1.0.4", "@tryghost/express-dynamic-redirects": "0.2.1", "@tryghost/helpers": "1.1.54", "@tryghost/image-transform": "1.0.18", diff --git a/test/regression/models/model_posts.test.js b/test/regression/models/model_posts.test.js index 5cc92a7f90..cac27a2c09 100644 --- a/test/regression/models/model_posts.test.js +++ b/test/regression/models/model_posts.test.js @@ -308,7 +308,7 @@ describe('Post Model', function () { }).then(function () { done(new Error('expected validation error')); }).catch(function (err) { - (err[0] instanceof errors.ValidationError).should.eql(true); + err[0].name.should.eql('ValidationError'); done(); }); }); diff --git a/test/unit/frontend/services/url/UrlService.test.js b/test/unit/frontend/services/url/UrlService.test.js index e96b40fc3e..9a5a14f23a 100644 --- a/test/unit/frontend/services/url/UrlService.test.js +++ b/test/unit/frontend/services/url/UrlService.test.js @@ -102,7 +102,7 @@ describe('Unit: services/url/UrlService', function () { urlService.getResource('/blog-post/'); throw new Error('Expected error.'); } catch (err) { - (err instanceof errors.InternalServerError).should.be.true(); + errors.utils.isGhostError(err).should.be.true(); } }); diff --git a/test/unit/server/data/migrations/utils.test.js b/test/unit/server/data/migrations/utils.test.js index d4f56229a2..160a5dd2b2 100644 --- a/test/unit/server/data/migrations/utils.test.js +++ b/test/unit/server/data/migrations/utils.test.js @@ -375,7 +375,7 @@ describe('migrations/utils/permissions', function () { runDownMigration = await runUpMigration(knex, migration); should.fail('addPermissionToRole up migration did not throw'); } catch (err) { - should.equal(err instanceof errors.GhostError, true); + should.equal(errors.utils.isGhostError(err), true); err.message.should.equal('Cannot add permission(Unimaginable) with role(Not there) - permission does not exist'); } }); @@ -408,7 +408,7 @@ describe('migrations/utils/permissions', function () { await runUpMigration(knex, migration); should.fail('addPermissionToRole did not throw'); } catch (err) { - should.equal(err instanceof errors.GhostError, true); + should.equal(errors.utils.isGhostError(err), true); err.message.should.equal('Cannot add permission(Permission Name) with role(Not there) - role does not exist'); } }); diff --git a/test/unit/server/data/schema/commands.test.js b/test/unit/server/data/schema/commands.test.js index 51cf3e421e..6a3f30535c 100644 --- a/test/unit/server/data/schema/commands.test.js +++ b/test/unit/server/data/schema/commands.test.js @@ -14,7 +14,7 @@ describe('schema commands', function () { await commands._hasForeignSQLite({transaction: knex}); should.fail('addForeign did not throw'); } catch (err) { - should.equal(err instanceof errors.GhostError, true); + should.equal(errors.utils.isGhostError(err), true); err.message.should.equal('Must use hasForeignSQLite3 on an SQLite3 database'); } }); @@ -29,7 +29,7 @@ describe('schema commands', function () { await commands._hasPrimaryKeySQLite(null, knex); should.fail('hasPrimaryKeySQLite did not throw'); } catch (err) { - should.equal(err instanceof errors.GhostError, true); + should.equal(errors.utils.isGhostError(err), true); err.message.should.equal('Must use hasPrimaryKeySQLite on an SQLite3 database'); } }); diff --git a/test/unit/server/services/mega/mega.test.js b/test/unit/server/services/mega/mega.test.js index 5153457f10..154475b741 100644 --- a/test/unit/server/services/mega/mega.test.js +++ b/test/unit/server/services/mega/mega.test.js @@ -16,7 +16,7 @@ describe('MEGA', function () { await addEmail(postModel); should.fail('addEmail did not throw'); } catch (err) { - should.equal(err instanceof errors.GhostError, true); + should.equal(errors.utils.isGhostError(err), true); err.message.should.equal('Unexpected email_recipient_filter value "free", expected an NQL equivalent'); } }); @@ -31,7 +31,7 @@ describe('MEGA', function () { await addEmail(postModel); should.fail('addEmail did not throw'); } catch (err) { - should.equal(err instanceof errors.GhostError, true); + should.equal(errors.utils.isGhostError(err), true); err.message.should.equal('Cannot send email to "none" email_recipient_filter'); } }); @@ -54,7 +54,7 @@ describe('MEGA', function () { await _getEmailMemberRows({emailModel}); should.fail('getEmailMemberRows did not throw'); } catch (err) { - should.equal(err instanceof errors.GhostError, true); + should.equal(errors.utils.isGhostError(err), true); err.message.should.equal('Unexpected recipient_filter value "paid", expected an NQL equivalent'); } }); @@ -68,7 +68,7 @@ describe('MEGA', function () { await _getEmailMemberRows({emailModel}); should.fail('getEmailMemberRows did not throw'); } catch (err) { - should.equal(err instanceof errors.GhostError, true); + should.equal(errors.utils.isGhostError(err), true); err.message.should.equal('Cannot send email to "none" recipient_filter'); } }); diff --git a/test/unit/server/services/settings/settings-loader.test.js b/test/unit/server/services/settings/settings-loader.test.js index cca5b3f84a..493a215a7b 100644 --- a/test/unit/server/services/settings/settings-loader.test.js +++ b/test/unit/server/services/settings/settings-loader.test.js @@ -82,7 +82,7 @@ describe('UNIT > SettingsLoader:', function () { it('can handle errors from YAML parser', function (done) { const storageFolderPath = path.join(__dirname, '../../../../utils/fixtures/settings/'); - yamlParserStub.throws(new errors.GhostError({ + yamlParserStub.throws(new errors.InternalServerError({ message: 'could not parse yaml file', context: 'bad indentation of a mapping entry at line 5, column 10' })); diff --git a/test/utils/api.js b/test/utils/api.js index c758f95cfe..8a10f2de6c 100644 --- a/test/utils/api.js +++ b/test/utils/api.js @@ -100,11 +100,11 @@ const login = (request, API_URL) => { .then(function then(res) { if (res.statusCode === 302) { // This can happen if you already have an instance running e.g. if you've been using Ghost CLI recently - return reject(new errors.GhostError({ + return reject(new errors.InternalServerError({ message: 'Ghost is redirecting, do you have an instance already running on port 2369?' })); } else if (res.statusCode !== 200 && res.statusCode !== 201) { - return reject(new errors.GhostError({ + return reject(new errors.InternalServerError({ message: res.body.errors[0].message })); } diff --git a/yarn.lock b/yarn.lock index c0345b5293..83cb949154 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1348,7 +1348,15 @@ ghost-ignition "^4.2.4" lodash "^4.17.20" -"@tryghost/errors@0.2.17", "@tryghost/errors@^0.2.10", "@tryghost/errors@^0.2.11", "@tryghost/errors@^0.2.12", "@tryghost/errors@^0.2.13", "@tryghost/errors@^0.2.14", "@tryghost/errors@^0.2.16", "@tryghost/errors@^0.2.17", "@tryghost/errors@^0.2.9": +"@tryghost/errors@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tryghost/errors/-/errors-1.0.4.tgz#9692cfd4c27a269ddbce77d93d02cfa8c52cc7ad" + integrity sha512-ImfwkOc54Ur9zjYgPaG3Y9wFeH00eJnqClYBZSB5/K0T6nqTXnIOyFIq33vZkmXuxQLX1xRb82OeWYxHxgFWDA== + dependencies: + lodash "^4.17.21" + uuid "^8.3.2" + +"@tryghost/errors@^0.2.10", "@tryghost/errors@^0.2.11", "@tryghost/errors@^0.2.12", "@tryghost/errors@^0.2.13", "@tryghost/errors@^0.2.14", "@tryghost/errors@^0.2.16", "@tryghost/errors@^0.2.17", "@tryghost/errors@^0.2.9": version "0.2.17" resolved "https://registry.yarnpkg.com/@tryghost/errors/-/errors-0.2.17.tgz#9b89f3845256ace5650593f41cc86d64965b56ed" integrity sha512-Mj+bedWOwfooNA8fQdp6gIcRvWcKhJ/hOyGzu6OLFDLgEosFEeuFgXE6SsAWkf9+9NTYX30w88qGIWZqOhEAmQ==