ghost 4.22.3 → 4.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.c8rc.json +24 -0
- package/.eslintrc.js +39 -0
- package/Gruntfile.js +0 -1
- package/content/public/README.md +3 -0
- package/content/themes/casper/assets/built/casper.js +1 -1
- package/content/themes/casper/assets/built/casper.js.map +1 -1
- package/content/themes/casper/assets/built/global.css +1 -1
- package/content/themes/casper/assets/built/global.css.map +1 -1
- package/content/themes/casper/assets/built/screen.css +1 -1
- package/content/themes/casper/assets/built/screen.css.map +1 -1
- package/content/themes/casper/assets/css/global.css +6 -1
- package/content/themes/casper/assets/css/screen.css +32 -216
- package/content/themes/casper/default.hbs +2 -2
- package/content/themes/casper/package.json +3 -2
- package/content/themes/casper/post.hbs +1 -1
- package/content/themes/casper/yarn.lock +173 -123
- package/core/app.js +12 -1
- package/core/boot.js +47 -28
- package/core/bridge.js +10 -10
- package/core/built/assets/{chunk.3.324fd0cc598c73650219.js → chunk.3.8f95b516d88ff4eec64c.js} +18 -18
- package/core/built/assets/ghost-dark-d690e732e17ffc794e2e59c1467ca282.css +1 -0
- package/core/built/assets/ghost.min-043bb7480a0810109b130f13b2a4235e.css +1 -0
- package/core/built/assets/{ghost.min-7da921f6c6cac3fe10da1ba104575440.js → ghost.min-bc72f685c1c9adc9885925c1412435a5.js} +563 -605
- package/core/built/assets/icons/audio-upload.svg +8 -0
- package/core/built/assets/icons/powered-by-tenor.svg +35 -0
- package/core/built/assets/icons/tenor.svg +7 -0
- package/core/built/assets/{vendor.min-413f887176a041e6dbf88214ca9a7481.js → vendor.min-d1234c632a54502777c34e50752fa3fc.js} +4622 -3631
- package/core/frontend/apps/amp/lib/helpers/amp_content.js +2 -2
- package/core/frontend/apps/amp/lib/views/amp.hbs +112 -0
- package/core/frontend/apps/private-blogging/index.js +1 -1
- package/core/frontend/apps/private-blogging/lib/router.js +1 -1
- package/core/frontend/services/apps/index.js +1 -1
- package/core/frontend/services/apps/loader.js +3 -3
- package/core/frontend/services/card-assets/index.js +0 -12
- package/core/frontend/services/card-assets/service.js +29 -28
- package/core/frontend/services/helpers/handlebars.js +1 -1
- package/core/frontend/services/routing/CollectionRouter.js +4 -5
- package/core/frontend/services/routing/EmailRouter.js +1 -1
- package/core/frontend/services/routing/ParentRouter.js +0 -8
- package/core/frontend/services/routing/PreviewRouter.js +1 -1
- package/core/frontend/services/routing/StaticPagesRouter.js +1 -1
- package/core/frontend/services/routing/StaticRoutesRouter.js +4 -4
- package/core/frontend/services/routing/TaxonomyRouter.js +3 -3
- package/core/frontend/services/routing/{middlewares → middleware}/index.js +0 -0
- package/core/frontend/services/routing/{middlewares → middleware}/page-param.js +0 -0
- package/core/frontend/services/routing/router-manager.js +7 -2
- package/core/frontend/services/rss/generate-feed.js +2 -1
- package/core/frontend/services/theme-engine/middleware/ensure-active-theme.js +34 -0
- package/core/frontend/services/theme-engine/middleware/index.js +6 -0
- package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +116 -0
- package/core/frontend/services/theme-engine/middleware/update-local-template-data.js +9 -0
- package/core/frontend/services/theme-engine/middleware/update-local-template-options.js +57 -0
- package/core/frontend/src/cards/css/bookmark.css +72 -47
- package/core/frontend/src/cards/css/button.css +4 -0
- package/core/frontend/src/cards/css/callout.css +40 -3
- package/core/frontend/src/cards/css/gallery.css +15 -10
- package/core/frontend/src/cards/css/nft.css +20 -11
- package/core/frontend/src/cards/css/toggle.css +58 -0
- package/core/frontend/src/cards/js/toggle.js +16 -0
- package/core/frontend/web/middleware/error-handler.js +93 -0
- package/core/frontend/web/middleware/handle-image-sizes.js +3 -6
- package/core/frontend/web/middleware/index.js +1 -0
- package/core/frontend/web/middleware/serve-public-file.js +39 -16
- package/core/frontend/web/site.js +11 -14
- package/core/server/adapters/scheduling/SchedulingDefault.js +2 -2
- package/core/server/adapters/storage/LocalStorageBase.js +2 -2
- package/core/server/api/canary/authentication.js +1 -1
- package/core/server/api/canary/db.js +2 -2
- package/core/server/api/canary/media.js +3 -2
- package/core/server/api/canary/oembed.js +16 -1
- package/core/server/api/canary/session.js +1 -1
- package/core/server/api/canary/slugs.js +1 -1
- package/core/server/api/canary/utils/permissions.js +2 -2
- package/core/server/api/canary/utils/serializers/output/config.js +2 -6
- package/core/server/api/v2/authentication.js +1 -1
- package/core/server/api/v2/db.js +2 -2
- package/core/server/api/v2/session.js +1 -1
- package/core/server/api/v2/slugs.js +1 -1
- package/core/server/api/v2/utils/permissions.js +2 -2
- package/core/server/api/v3/authentication.js +1 -1
- package/core/server/api/v3/db.js +2 -2
- package/core/server/api/v3/session.js +1 -1
- package/core/server/api/v3/slugs.js +1 -1
- package/core/server/api/v3/utils/permissions.js +2 -2
- package/core/server/data/db/connection.js +7 -0
- package/core/server/data/db/state-manager.js +4 -4
- package/core/server/data/exporter/export-filename.js +1 -1
- package/core/server/data/importer/handlers/json.js +1 -1
- package/core/server/data/importer/import-manager.js +1 -1
- package/core/server/data/importer/importers/data/base.js +1 -1
- package/core/server/data/importer/importers/data/data-importer.js +3 -3
- package/core/server/data/migrations/init/2-create-fixtures.js +3 -20
- package/core/server/data/migrations/utils.js +2 -2
- package/core/server/data/migrations/versions/1.21/1-add-contributor-role.js +5 -5
- package/core/server/data/migrations/versions/1.25/1-update-koenig-beta-html.js +1 -0
- package/core/server/data/migrations/versions/2.15/2-insert-zapier-integration.js +3 -3
- package/core/server/data/migrations/versions/2.2/3-insert-admin-integration-role.js +5 -5
- package/core/server/data/migrations/versions/2.27/1-insert-ghost-db-backup-role.js +5 -6
- package/core/server/data/migrations/versions/2.27/2-insert-db-backup-integration.js +3 -4
- package/core/server/data/migrations/versions/2.28/3-insert-ghost-scheduler-role.js +7 -7
- package/core/server/data/migrations/versions/2.28/4-insert-scheduler-integration.js +3 -3
- package/core/server/data/migrations/versions/3.1/08-add-uuid-values-to-members.js +1 -0
- package/core/server/data/migrations/versions/3.22/02-settings-key-renames.js +2 -0
- package/core/server/data/migrations/versions/3.22/05-migrate-members-subscription-settings.js +3 -0
- package/core/server/data/migrations/versions/3.22/06-migrate-stripe-connect-settings.js +2 -0
- package/core/server/data/migrations/versions/3.23/01-migrate-bulk-email-settings.js +1 -0
- package/core/server/data/migrations/versions/3.29/01-remove-duplicate-subscriptions.js +2 -0
- package/core/server/data/migrations/versions/3.29/02-remove-duplicate-customers.js +2 -0
- package/core/server/data/migrations/versions/3.38/04-populate-recipient-filter-column.js +2 -0
- package/core/server/data/migrations/versions/4.0/01-update-mobiledoc.js +2 -0
- package/core/server/data/migrations/versions/4.0/03-populate-status-column-for-members.js +4 -0
- package/core/server/data/migrations/versions/4.0/06-populate-members-subscribe-events-table.js +1 -0
- package/core/server/data/migrations/versions/4.0/17-populate-members-status-events-table.js +1 -0
- package/core/server/data/migrations/versions/4.0/18-transform-urls-absolute-to-transform-ready.js +5 -0
- package/core/server/data/migrations/versions/4.0/22-solve-orphaned-webhooks.js +1 -0
- package/core/server/data/migrations/versions/4.0/23-regenerate-posts-html.js +1 -0
- package/core/server/data/migrations/versions/4.0/25-populate-members-paid-subscription-events-table.js +2 -1
- package/core/server/data/migrations/versions/4.12/02-fix-member-statuses.js +1 -0
- package/core/server/data/migrations/versions/4.14/01-fix-comped-member-statuses.js +3 -0
- package/core/server/data/migrations/versions/4.14/02-fix-free-members-status-events.js +1 -0
- package/core/server/data/migrations/versions/4.20/05-remove-not-null-constraint-from-portal-title.js +2 -0
- package/core/server/data/migrations/versions/4.23/01-truncate-offer-names.js +59 -0
- package/core/server/data/migrations/versions/4.3/04-attach-members-to-product.js +1 -0
- package/core/server/data/migrations/versions/4.4/01-restore-free-members-signup-setting-from-backup.js +1 -0
- package/core/server/data/migrations/versions/4.6/01-remove-comped-status.js +1 -0
- package/core/server/data/migrations/versions/4.8/04-migrate-show-newsletter-header-setting.js +1 -0
- package/core/server/data/migrations/versions/4.9/05-fix-missed-mobiledoc-url-transforms.js +1 -0
- package/core/server/data/migrations/versions/4.9/06-add-comped-status.js +1 -0
- package/core/server/data/migrations/versions/4.9/07-update-comped-members-status-events.js +1 -0
- package/core/server/data/schema/commands.js +2 -2
- package/core/server/data/schema/fixtures/fixture-manager.js +340 -0
- package/core/server/data/schema/fixtures/index.js +8 -2
- package/core/server/ghost-server.js +2 -2
- package/core/server/lib/image/image-size.js +2 -2
- package/core/server/models/base/listeners.js +2 -2
- package/core/server/models/member-email-change-event.js +2 -2
- package/core/server/models/member-login-event.js +2 -2
- package/core/server/models/member-paid-subscription-event.js +3 -3
- package/core/server/models/member-payment-event.js +3 -3
- package/core/server/models/member-product-event.js +6 -6
- package/core/server/models/member-status-event.js +5 -3
- package/core/server/models/member-subscribe-event.js +9 -3
- package/core/server/models/relations/authors.js +1 -1
- package/core/server/models/settings.js +1 -1
- package/core/server/services/auth/passwordreset.js +1 -1
- package/core/server/services/auth/setup.js +1 -1
- package/core/server/services/email-analytics/jobs/index.js +1 -1
- package/core/server/services/mega/mega.js +6 -4
- package/core/server/services/mega/post-email-serializer.js +5 -1
- package/core/server/services/mega/segment-parser.js +1 -2
- package/core/server/services/mega/template.js +52 -37
- package/core/server/services/members/api.js +22 -0
- package/core/server/services/members/config.js +1 -1
- package/core/server/services/members/emails/signup-paid.js +168 -0
- package/core/server/services/members/service.js +6 -2
- package/core/server/services/members/stripe-connect.js +4 -2
- package/core/server/services/nft-oembed.js +13 -22
- package/core/server/services/oembed.js +28 -24
- package/core/server/services/permissions/can-this.js +1 -1
- package/core/server/services/public-config/config.js +1 -1
- package/core/server/services/redirects/api.js +20 -25
- package/core/server/services/redirects/index.js +18 -10
- package/core/server/services/redirects/utils.js +14 -0
- package/core/server/services/redirects/validation.js +10 -0
- package/core/server/services/route-settings/default-settings-manager.js +1 -1
- package/core/server/services/route-settings/index.js +40 -17
- package/core/server/services/route-settings/route-settings.js +120 -115
- package/core/server/services/route-settings/settings-loader.js +18 -36
- package/core/server/services/route-settings/yaml-parser.js +1 -1
- package/core/server/services/slack.js +1 -1
- package/core/server/services/themes/activation-bridge.js +3 -3
- package/core/server/services/themes/storage.js +2 -2
- package/core/server/services/twitter-embed.js +80 -0
- package/core/server/services/url/LocalFileCache.js +75 -0
- package/core/server/services/url/Resources.js +8 -2
- package/core/server/services/url/UrlGenerator.js +23 -20
- package/core/server/services/url/UrlService.js +75 -63
- package/core/server/services/url/index.js +17 -3
- package/core/server/services/xmlrpc.js +2 -2
- package/core/server/web/admin/app.js +7 -10
- package/core/server/web/admin/controller.js +35 -12
- package/core/server/web/admin/middleware/redirect-admin-urls.js +15 -0
- package/core/server/web/admin/views/default-prod.html +4 -4
- package/core/server/web/admin/views/default.html +4 -4
- package/core/server/web/api/app.js +1 -1
- package/core/server/web/api/canary/admin/app.js +3 -6
- package/core/server/web/api/canary/admin/middleware.js +7 -7
- package/core/server/web/api/canary/admin/routes.js +5 -5
- package/core/server/web/api/canary/content/app.js +3 -6
- package/core/server/web/api/canary/content/middleware.js +3 -3
- package/core/server/web/api/v2/admin/app.js +3 -6
- package/core/server/web/api/v2/admin/middleware.js +7 -7
- package/core/server/web/api/v2/admin/routes.js +5 -5
- package/core/server/web/api/v2/content/app.js +3 -6
- package/core/server/web/api/v2/content/middleware.js +3 -3
- package/core/server/web/api/v3/admin/app.js +3 -6
- package/core/server/web/api/v3/admin/middleware.js +7 -7
- package/core/server/web/api/v3/admin/routes.js +5 -5
- package/core/server/web/api/v3/content/app.js +3 -6
- package/core/server/web/api/v3/content/middleware.js +3 -3
- package/core/server/web/members/app.js +6 -9
- package/core/server/web/oauth/app.js +0 -4
- package/core/server/web/parent/app.js +17 -9
- package/core/server/web/parent/frontend.js +1 -1
- package/core/server/web/shared/index.js +2 -2
- package/core/server/web/shared/{middlewares → middleware}/api/index.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/api/spam-prevention.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/brute.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/cache-control.js +0 -0
- package/core/server/web/shared/middleware/error-handler.js +224 -0
- package/core/server/web/shared/{middlewares → middleware}/index.js +0 -4
- package/core/server/web/shared/{middlewares → middleware}/pretty-urls.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/uncapitalise.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/url-redirects.js +0 -0
- package/core/shared/config/defaults.json +13 -1
- package/core/shared/config/helpers.js +42 -0
- package/core/shared/config/loader.js +1 -1
- package/core/shared/labs.js +9 -5
- package/core/shared/sentry.js +1 -1
- package/loggingrc.js +19 -20
- package/package.json +38 -37
- package/yarn.lock +1064 -892
- package/content/themes/casper/assets/js/gallery-card.js +0 -24
- package/core/built/assets/ghost-dark-39fb496d051565531062d7e047d1c0b1.css +0 -1
- package/core/built/assets/ghost.min-4207edfc1ae0a3f9f6505ca00d20b0c0.css +0 -1
- package/core/frontend/services/theme-engine/middleware.js +0 -209
- package/core/server/data/schema/fixtures/utils.js +0 -321
- package/core/server/web/parent/vhost-utils.js +0 -39
- package/core/server/web/shared/middlewares/error-handler.js +0 -329
- package/core/server/web/shared/middlewares/maintenance.js +0 -25
|
@@ -4,9 +4,14 @@ const express = require('../../../shared/express');
|
|
|
4
4
|
const compress = require('compression');
|
|
5
5
|
const mw = require('./middleware');
|
|
6
6
|
const vhost = require('@tryghost/vhost-middleware');
|
|
7
|
-
const vhostUtils = require('./vhost-utils');
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* @param {Object} options
|
|
10
|
+
* @param {Boolean} [options.start]
|
|
11
|
+
* @param {Boolean} [options.backend]
|
|
12
|
+
* @param {Boolean} [options.frontend]
|
|
13
|
+
*/
|
|
14
|
+
module.exports = function setupParentApp({start, frontend = true, backend = true}) {
|
|
10
15
|
debug('ParentApp setup start');
|
|
11
16
|
const parentApp = express('parent');
|
|
12
17
|
|
|
@@ -27,14 +32,17 @@ module.exports = function setupParentApp(options = {}) {
|
|
|
27
32
|
|
|
28
33
|
// Mount the express apps on the parentApp
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const frontendApp = require('./frontend')(options);
|
|
36
|
-
parentApp.use(vhost(vhostUtils.getFrontendHostArg(), frontendApp));
|
|
35
|
+
if (backend) {
|
|
36
|
+
debug('Mounting bakcend: ADMIN + API');
|
|
37
|
+
const backendApp = require('./backend')();
|
|
38
|
+
parentApp.use(vhost(config.getBackendMountPath(), backendApp));
|
|
39
|
+
}
|
|
37
40
|
|
|
41
|
+
if (frontend) {
|
|
42
|
+
debug('Mounting frontend: SITE + MEMBERS');
|
|
43
|
+
const frontendApp = require('./frontend')({start});
|
|
44
|
+
parentApp.use(vhost(config.getFrontendMountPath(), frontendApp));
|
|
45
|
+
}
|
|
38
46
|
debug('ParentApp setup end');
|
|
39
47
|
|
|
40
48
|
return parentApp;
|
|
@@ -16,7 +16,7 @@ module.exports = (options) => {
|
|
|
16
16
|
|
|
17
17
|
// Force SSL if blog url is set to https. The redirects handling must happen before asset and page routing,
|
|
18
18
|
// otherwise we serve assets/pages with http. This can cause mixed content warnings in the admin client.
|
|
19
|
-
frontendApp.use(shared.
|
|
19
|
+
frontendApp.use(shared.middleware.urlRedirects.frontendSSLRedirect);
|
|
20
20
|
|
|
21
21
|
frontendApp.lazyUse('/members', require('../members'));
|
|
22
22
|
frontendApp.use('/', require('../../../frontend/web')(options));
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
const _ = require('lodash');
|
|
2
|
+
const debug = require('@tryghost/debug')('error-handler');
|
|
3
|
+
const errors = require('@tryghost/errors');
|
|
4
|
+
const tpl = require('@tryghost/tpl');
|
|
5
|
+
const sentry = require('../../../../shared/sentry');
|
|
6
|
+
|
|
7
|
+
const messages = {
|
|
8
|
+
pageNotFound: 'Page not found',
|
|
9
|
+
resourceNotFound: 'Resource not found',
|
|
10
|
+
actions: {
|
|
11
|
+
images: {
|
|
12
|
+
upload: 'upload image'
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
userMessages: {
|
|
16
|
+
BookshelfRelationsError: 'Database error, cannot {action}.',
|
|
17
|
+
InternalServerError: 'Internal server error, cannot {action}.',
|
|
18
|
+
IncorrectUsageError: 'Incorrect usage error, cannot {action}.',
|
|
19
|
+
NotFoundError: 'Resource not found error, cannot {action}.',
|
|
20
|
+
BadRequestError: 'Request not understood error, cannot {action}.',
|
|
21
|
+
UnauthorizedError: 'Authorisation error, cannot {action}.',
|
|
22
|
+
NoPermissionError: 'Permission error, cannot {action}.',
|
|
23
|
+
ValidationError: 'Validation error, cannot {action}.',
|
|
24
|
+
UnsupportedMediaTypeError: 'Unsupported media error, cannot {action}.',
|
|
25
|
+
TooManyRequestsError: 'Too many requests error, cannot {action}.',
|
|
26
|
+
MaintenanceError: 'Server down for maintenance, cannot {action}.',
|
|
27
|
+
MethodNotAllowedError: 'Method not allowed, cannot {action}.',
|
|
28
|
+
RequestEntityTooLargeError: 'Request too large, cannot {action}.',
|
|
29
|
+
TokenRevocationError: 'Token is not available, cannot {action}.',
|
|
30
|
+
VersionMismatchError: 'Version mismatch error, cannot {action}.',
|
|
31
|
+
DataExportError: 'Error exporting content.',
|
|
32
|
+
DataImportError: 'Duplicated entry, cannot save {action}.',
|
|
33
|
+
DatabaseVersionError: 'Database version compatibility error, cannot {action}.',
|
|
34
|
+
EmailError: 'Error sending email!',
|
|
35
|
+
ThemeValidationError: 'Theme validation error, cannot {action}.',
|
|
36
|
+
HostLimitError: 'Host Limit error, cannot {action}.',
|
|
37
|
+
DisabledFeatureError: 'Theme validation error, the {{{helperName}}} helper is not available. Cannot {action}.',
|
|
38
|
+
UpdateCollisionError: 'Saving failed! Someone else is editing this post.'
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const updateStack = (err) => {
|
|
43
|
+
let stackbits = err.stack.split(/\n/g);
|
|
44
|
+
|
|
45
|
+
// We build this up backwards, so we always insert at position 1
|
|
46
|
+
|
|
47
|
+
if (process.env.NODE_ENV === 'production' || err.statusCode === 404) {
|
|
48
|
+
// In production mode, remove the stack trace
|
|
49
|
+
stackbits.splice(1, stackbits.length - 1);
|
|
50
|
+
} else {
|
|
51
|
+
// In dev mode, clearly mark the strack trace
|
|
52
|
+
stackbits.splice(1, 0, `Stack Trace:`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Add in our custom cotext and help methods
|
|
56
|
+
|
|
57
|
+
if (err.help) {
|
|
58
|
+
stackbits.splice(1, 0, `${err.help}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (err.context) {
|
|
62
|
+
stackbits.splice(1, 0, `${err.context}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return stackbits.join('\n');
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get an error ready to be shown the the user
|
|
70
|
+
*/
|
|
71
|
+
module.exports.prepareError = (err, req, res, next) => {
|
|
72
|
+
debug(err);
|
|
73
|
+
|
|
74
|
+
if (Array.isArray(err)) {
|
|
75
|
+
err = err[0];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!errors.utils.isGhostError(err)) {
|
|
79
|
+
// We need a special case for 404 errors
|
|
80
|
+
if (err.statusCode && err.statusCode === 404) {
|
|
81
|
+
err = new errors.NotFoundError({
|
|
82
|
+
err: err
|
|
83
|
+
});
|
|
84
|
+
} else if (err.stack.match(/node_modules\/handlebars\//)) {
|
|
85
|
+
// Temporary handling of theme errors from handlebars
|
|
86
|
+
// @TODO remove this when #10496 is solved properly
|
|
87
|
+
err = new errors.IncorrectUsageError({
|
|
88
|
+
err: err,
|
|
89
|
+
message: err.message,
|
|
90
|
+
statusCode: err.statusCode
|
|
91
|
+
});
|
|
92
|
+
} else {
|
|
93
|
+
err = new errors.InternalServerError({
|
|
94
|
+
err: err,
|
|
95
|
+
message: err.message,
|
|
96
|
+
statusCode: err.statusCode
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// used for express logging middleware see core/server/app.js
|
|
102
|
+
req.err = err;
|
|
103
|
+
|
|
104
|
+
// alternative for res.status();
|
|
105
|
+
res.statusCode = err.statusCode;
|
|
106
|
+
|
|
107
|
+
err.stack = updateStack(err);
|
|
108
|
+
|
|
109
|
+
// never cache errors
|
|
110
|
+
res.set({
|
|
111
|
+
'Cache-Control': 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
next(err);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const jsonErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
|
|
118
|
+
res.json({
|
|
119
|
+
errors: [{
|
|
120
|
+
message: err.message,
|
|
121
|
+
context: err.context,
|
|
122
|
+
help: err.help,
|
|
123
|
+
errorType: err.errorType,
|
|
124
|
+
errorDetails: err.errorDetails,
|
|
125
|
+
ghostErrorCode: err.ghostErrorCode
|
|
126
|
+
}]
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const jsonErrorRendererV2 = (err, req, res, next) => { // eslint-disable-line no-unused-vars
|
|
131
|
+
const userError = prepareUserMessage(err, req);
|
|
132
|
+
|
|
133
|
+
res.json({
|
|
134
|
+
errors: [{
|
|
135
|
+
message: userError.message || null,
|
|
136
|
+
context: userError.context || null,
|
|
137
|
+
type: err.errorType || null,
|
|
138
|
+
details: err.errorDetails || null,
|
|
139
|
+
property: err.property || null,
|
|
140
|
+
help: err.help || null,
|
|
141
|
+
code: err.code || null,
|
|
142
|
+
id: err.id || null
|
|
143
|
+
}]
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const prepareUserMessage = (err, res) => {
|
|
148
|
+
const userError = {
|
|
149
|
+
message: err.message,
|
|
150
|
+
context: err.context
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const docName = _.get(res, 'frameOptions.docName');
|
|
154
|
+
const method = _.get(res, 'frameOptions.method');
|
|
155
|
+
|
|
156
|
+
if (docName && method) {
|
|
157
|
+
let action;
|
|
158
|
+
|
|
159
|
+
const actionMap = {
|
|
160
|
+
browse: 'list',
|
|
161
|
+
read: 'read',
|
|
162
|
+
add: 'save',
|
|
163
|
+
edit: 'edit',
|
|
164
|
+
destroy: 'delete'
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
if (_.get(messages.actions, [docName, method])) {
|
|
168
|
+
action = tpl(messages.actions[docName][method]);
|
|
169
|
+
} else if (Object.keys(actionMap).includes(method)) {
|
|
170
|
+
let resource = docName;
|
|
171
|
+
|
|
172
|
+
if (method !== 'browse') {
|
|
173
|
+
resource = resource.replace(/s$/, '');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
action = `${actionMap[method]} ${resource}`;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (action) {
|
|
180
|
+
if (err.context) {
|
|
181
|
+
userError.context = `${err.message} ${err.context}`;
|
|
182
|
+
} else {
|
|
183
|
+
userError.context = err.message;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
userError.message = tpl(messages.userMessages[err.name], {action: action});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return userError;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
module.exports.resourceNotFound = (req, res, next) => {
|
|
194
|
+
next(new errors.NotFoundError({message: tpl(messages.resourceNotFound)}));
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
module.exports.pageNotFound = (req, res, next) => {
|
|
198
|
+
next(new errors.NotFoundError({message: tpl(messages.pageNotFound)}));
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
module.exports.handleJSONResponse = [
|
|
202
|
+
// Make sure the error can be served
|
|
203
|
+
module.exports.prepareError,
|
|
204
|
+
// Handle the error in Sentry
|
|
205
|
+
sentry.errorHandler,
|
|
206
|
+
// Render the error using JSON format
|
|
207
|
+
jsonErrorRenderer
|
|
208
|
+
];
|
|
209
|
+
|
|
210
|
+
module.exports.handleJSONResponseV2 = [
|
|
211
|
+
// Make sure the error can be served
|
|
212
|
+
module.exports.prepareError,
|
|
213
|
+
// Handle the error in Sentry
|
|
214
|
+
sentry.errorHandler,
|
|
215
|
+
// Render the error using JSON format
|
|
216
|
+
jsonErrorRendererV2
|
|
217
|
+
];
|
|
218
|
+
|
|
219
|
+
module.exports.handleHTMLResponse = [
|
|
220
|
+
// Make sure the error can be served
|
|
221
|
+
module.exports.prepareError,
|
|
222
|
+
// Handle the error in Sentry
|
|
223
|
+
sentry.errorHandler
|
|
224
|
+
];
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
"privacy": false,
|
|
16
16
|
"useMinFiles": true,
|
|
17
17
|
"paths": {
|
|
18
|
-
"contentPath": "content/"
|
|
18
|
+
"contentPath": "content/",
|
|
19
|
+
"fixtures": "core/server/data/schema/fixtures/fixtures",
|
|
20
|
+
"assetSrc": "core/frontend/src"
|
|
19
21
|
},
|
|
20
22
|
"adapters": {
|
|
21
23
|
"sso": {
|
|
@@ -127,5 +129,15 @@
|
|
|
127
129
|
"portal": {
|
|
128
130
|
"url": "https://unpkg.com/@tryghost/portal@~1.12.0/umd/portal.min.js",
|
|
129
131
|
"version": "1.12"
|
|
132
|
+
},
|
|
133
|
+
"tenor": {
|
|
134
|
+
"publicReadOnlyApiKey": null,
|
|
135
|
+
"contentFilter": "off"
|
|
136
|
+
},
|
|
137
|
+
"opensea": {
|
|
138
|
+
"privateReadOnlyApiKey": null
|
|
139
|
+
},
|
|
140
|
+
"twitter": {
|
|
141
|
+
"privateReadOnlyToken": null
|
|
130
142
|
}
|
|
131
143
|
}
|
|
@@ -1,4 +1,42 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
+
const escapeRegExp = require('lodash/escapeRegExp');
|
|
3
|
+
const {URL} = require('url');
|
|
4
|
+
|
|
5
|
+
const DEFAULT_HOST_ARG = /.*/;
|
|
6
|
+
|
|
7
|
+
const getHostInfo = (config) => {
|
|
8
|
+
const frontendHost = new URL(config.getSiteUrl()).hostname;
|
|
9
|
+
|
|
10
|
+
const backendHost = config.getAdminUrl() ? (new URL(config.getAdminUrl()).hostname) : '';
|
|
11
|
+
const hasSeparateBackendHost = backendHost && backendHost !== frontendHost;
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
backendHost,
|
|
15
|
+
hasSeparateBackendHost
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @returns {string|RegExp}
|
|
22
|
+
*/
|
|
23
|
+
const getBackendMountPath = function getFrontendMountPath() {
|
|
24
|
+
const {backendHost, hasSeparateBackendHost} = getHostInfo(this);
|
|
25
|
+
|
|
26
|
+
// with a separate admin url only serve on that host, otherwise serve on all hosts
|
|
27
|
+
return (hasSeparateBackendHost) && backendHost ? backendHost : DEFAULT_HOST_ARG;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @returns {string|RegExp}
|
|
33
|
+
*/
|
|
34
|
+
const getFrontendMountPath = function getFrontendMountPath() {
|
|
35
|
+
const {backendHost, hasSeparateBackendHost} = getHostInfo(this);
|
|
36
|
+
|
|
37
|
+
// with a separate admin url we adjust the frontend vhost to exclude requests to that host, otherwise serve on all hosts
|
|
38
|
+
return (hasSeparateBackendHost && backendHost) ? new RegExp(`^(?!${escapeRegExp(backendHost)}).*`) : DEFAULT_HOST_ARG;
|
|
39
|
+
};
|
|
2
40
|
|
|
3
41
|
/**
|
|
4
42
|
* @callback isPrivacyDisabledFn
|
|
@@ -46,6 +84,8 @@ const getContentPath = function getContentPath(type) {
|
|
|
46
84
|
return path.join(this.get('paths:contentPath'), 'data/');
|
|
47
85
|
case 'settings':
|
|
48
86
|
return path.join(this.get('paths:contentPath'), 'settings/');
|
|
87
|
+
case 'public':
|
|
88
|
+
return path.join(this.get('paths:contentPath'), 'public/');
|
|
49
89
|
default:
|
|
50
90
|
// new Error is allowed here, as we do not want config to depend on @tryghost/error
|
|
51
91
|
// @TODO: revisit this decision when @tryghost/error is no longer dependent on all of ghost-ignition
|
|
@@ -62,4 +102,6 @@ const getContentPath = function getContentPath(type) {
|
|
|
62
102
|
module.exports.bindAll = (nconf) => {
|
|
63
103
|
nconf.isPrivacyDisabled = isPrivacyDisabled.bind(nconf);
|
|
64
104
|
nconf.getContentPath = getContentPath.bind(nconf);
|
|
105
|
+
nconf.getBackendMountPath = getBackendMountPath.bind(nconf);
|
|
106
|
+
nconf.getFrontendMountPath = getFrontendMountPath.bind(nconf);
|
|
65
107
|
};
|
package/core/shared/labs.js
CHANGED
|
@@ -15,7 +15,8 @@ const messages = {
|
|
|
15
15
|
|
|
16
16
|
// flags in this list always return `true`, allows quick global enable prior to full flag removal
|
|
17
17
|
const GA_FEATURES = [
|
|
18
|
-
'customThemeSettings'
|
|
18
|
+
'customThemeSettings',
|
|
19
|
+
'nftCard'
|
|
19
20
|
];
|
|
20
21
|
|
|
21
22
|
// NOTE: this allowlist is meant to be used to filter out any unexpected
|
|
@@ -33,11 +34,13 @@ const ALPHA_FEATURES = [
|
|
|
33
34
|
'mediaAPI',
|
|
34
35
|
'filesAPI',
|
|
35
36
|
'membersAutoLogin',
|
|
36
|
-
'buttonCard',
|
|
37
37
|
'calloutCard',
|
|
38
|
-
'nftCard',
|
|
39
38
|
'accordionCard',
|
|
40
|
-
'
|
|
39
|
+
'fileCard',
|
|
40
|
+
'audioCard',
|
|
41
|
+
'videoCard',
|
|
42
|
+
'productCard',
|
|
43
|
+
'quoteStyles'
|
|
41
44
|
];
|
|
42
45
|
|
|
43
46
|
module.exports.GA_KEYS = [...GA_FEATURES];
|
|
@@ -47,7 +50,7 @@ module.exports.getAll = () => {
|
|
|
47
50
|
const labs = _.cloneDeep(settingsCache.get('labs')) || {};
|
|
48
51
|
|
|
49
52
|
ALPHA_FEATURES.forEach((alphaKey) => {
|
|
50
|
-
if (labs[alphaKey] && !(config.get('enableDeveloperExperiments') || process.env.NODE_ENV.
|
|
53
|
+
if (labs[alphaKey] && !(config.get('enableDeveloperExperiments') || process.env.NODE_ENV.startsWith('test'))) {
|
|
51
54
|
delete labs[alphaKey];
|
|
52
55
|
}
|
|
53
56
|
});
|
|
@@ -102,6 +105,7 @@ module.exports.enabledHelper = function enabledHelper(options, callback) {
|
|
|
102
105
|
});
|
|
103
106
|
errDetails.help = tpl(options.errorHelp || messages.errorHelp, {url: options.helpUrl});
|
|
104
107
|
|
|
108
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
105
109
|
logging.error(new errors.DisabledFeatureError(errDetails));
|
|
106
110
|
|
|
107
111
|
const {SafeString} = require('express-hbs');
|
package/core/shared/sentry.js
CHANGED
|
@@ -18,7 +18,7 @@ if (sentryConfig && !sentryConfig.disabled) {
|
|
|
18
18
|
shouldHandleError(error) {
|
|
19
19
|
// Sometimes non-Ghost issues will come into here but they won't
|
|
20
20
|
// have a statusCode so we should always handle them
|
|
21
|
-
if (!errors.utils.
|
|
21
|
+
if (!errors.utils.isGhostError(error)) {
|
|
22
22
|
return true;
|
|
23
23
|
}
|
|
24
24
|
|
package/loggingrc.js
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
const config = require('./core/shared/config');
|
|
2
2
|
const ghostVersion = require('@tryghost/version');
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
// Config for logging
|
|
5
|
+
const loggingConfig = config.get('logging') || {};
|
|
6
|
+
|
|
7
|
+
if (!loggingConfig.path) {
|
|
8
|
+
loggingConfig.path = config.getContentPath('logs');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Additional values used by logging
|
|
12
|
+
loggingConfig.env = config.get('env');
|
|
13
|
+
loggingConfig.domain = config.get('url');
|
|
14
|
+
|
|
15
|
+
// Config for metrics
|
|
16
|
+
loggingConfig.metrics = config.get('logging:metrics') || {};
|
|
17
|
+
loggingConfig.metrics.metadata = {
|
|
18
|
+
// Undefined if unavailable
|
|
19
|
+
siteId: config.get('hostSettings:siteId'),
|
|
8
20
|
domain: config.get('url'),
|
|
9
|
-
|
|
10
|
-
level: config.get('logging:level'),
|
|
11
|
-
transports: config.get('logging:transports'),
|
|
12
|
-
metrics: {
|
|
13
|
-
transports: config.get('logging:metrics:transports'),
|
|
14
|
-
metadata: {
|
|
15
|
-
// Undefined if unavailable
|
|
16
|
-
siteId: config.get('hostSettings:siteId'),
|
|
17
|
-
domain: config.get('url'),
|
|
18
|
-
version: ghostVersion.safe
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
gelf: config.get('logging:gelf'),
|
|
22
|
-
loggly: config.get('logging:loggly'),
|
|
23
|
-
elasticsearch: config.get('logging:elasticsearch'),
|
|
24
|
-
rotation: config.get('logging:rotation')
|
|
21
|
+
version: ghostVersion.safe
|
|
25
22
|
};
|
|
23
|
+
|
|
24
|
+
module.exports = loggingConfig;
|