ghost 4.22.4 → 4.25.1

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.
Files changed (170) hide show
  1. package/.eslintrc.js +39 -0
  2. package/content/themes/casper/assets/built/casper.js +1 -1
  3. package/content/themes/casper/assets/built/casper.js.map +1 -1
  4. package/content/themes/casper/assets/built/global.css +1 -1
  5. package/content/themes/casper/assets/built/global.css.map +1 -1
  6. package/content/themes/casper/assets/built/screen.css +1 -1
  7. package/content/themes/casper/assets/built/screen.css.map +1 -1
  8. package/content/themes/casper/assets/css/global.css +6 -1
  9. package/content/themes/casper/assets/css/screen.css +32 -216
  10. package/content/themes/casper/default.hbs +2 -2
  11. package/content/themes/casper/package.json +3 -2
  12. package/content/themes/casper/post.hbs +1 -1
  13. package/content/themes/casper/yarn.lock +173 -123
  14. package/core/app.js +12 -1
  15. package/core/boot.js +33 -19
  16. package/core/bridge.js +10 -10
  17. package/core/built/assets/ghost-dark-f67240a9636407594be38571c615629c.css +1 -0
  18. package/core/built/assets/{ghost.min-2e3e64eb258cf424c59c3e308b4bc6e6.js → ghost.min-3441c3282e390002626a2dc1d7586185.js} +544 -619
  19. package/core/built/assets/ghost.min-ee5bd95a831378b4c8ccefb37d26eac0.css +1 -0
  20. package/core/built/assets/icons/audio-upload.svg +8 -0
  21. package/core/built/assets/{vendor.min-c9002845b6c30ac978abdadde9f33d7c.js → vendor.min-6fc912d1248c906f95efad2cb3eebb7d.js} +2656 -2118
  22. package/core/frontend/apps/amp/lib/helpers/amp_content.js +2 -2
  23. package/core/frontend/apps/amp/lib/views/amp.hbs +70 -0
  24. package/core/frontend/apps/private-blogging/index.js +1 -1
  25. package/core/frontend/helpers/url.js +18 -1
  26. package/core/frontend/services/apps/index.js +1 -1
  27. package/core/frontend/services/apps/loader.js +3 -3
  28. package/core/frontend/services/card-assets/index.js +0 -12
  29. package/core/frontend/services/card-assets/service.js +22 -21
  30. package/core/frontend/services/helpers/handlebars.js +1 -1
  31. package/core/frontend/services/theme-engine/middleware/ensure-active-theme.js +34 -0
  32. package/core/frontend/services/theme-engine/middleware/index.js +6 -0
  33. package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +116 -0
  34. package/core/frontend/services/theme-engine/middleware/update-local-template-data.js +9 -0
  35. package/core/frontend/services/theme-engine/middleware/update-local-template-options.js +57 -0
  36. package/core/frontend/src/cards/css/blockquote.css +29 -0
  37. package/core/frontend/src/cards/css/bookmark.css +7 -0
  38. package/core/frontend/src/cards/css/button.css +4 -0
  39. package/core/frontend/src/cards/css/callout.css +23 -15
  40. package/core/frontend/src/cards/css/gallery.css +13 -3
  41. package/core/frontend/src/cards/css/toggle.css +36 -16
  42. package/core/frontend/web/middleware/error-handler.js +93 -0
  43. package/core/frontend/web/middleware/handle-image-sizes.js +3 -6
  44. package/core/frontend/web/middleware/index.js +1 -0
  45. package/core/frontend/web/middleware/serve-public-file.js +25 -8
  46. package/core/frontend/web/site.js +2 -5
  47. package/core/server/adapters/scheduling/SchedulingDefault.js +2 -2
  48. package/core/server/adapters/storage/LocalStorageBase.js +2 -2
  49. package/core/server/api/canary/db.js +2 -2
  50. package/core/server/api/canary/media.js +3 -2
  51. package/core/server/api/canary/oembed.js +16 -1
  52. package/core/server/api/canary/session.js +1 -1
  53. package/core/server/api/canary/slugs.js +1 -1
  54. package/core/server/api/canary/utils/permissions.js +2 -2
  55. package/core/server/api/canary/utils/serializers/output/config.js +2 -6
  56. package/core/server/api/v2/db.js +2 -2
  57. package/core/server/api/v2/session.js +1 -1
  58. package/core/server/api/v2/slugs.js +1 -1
  59. package/core/server/api/v2/utils/permissions.js +2 -2
  60. package/core/server/api/v3/db.js +2 -2
  61. package/core/server/api/v3/session.js +1 -1
  62. package/core/server/api/v3/slugs.js +1 -1
  63. package/core/server/api/v3/utils/permissions.js +2 -2
  64. package/core/server/data/db/state-manager.js +4 -4
  65. package/core/server/data/exporter/export-filename.js +1 -1
  66. package/core/server/data/importer/handlers/json.js +1 -1
  67. package/core/server/data/importer/import-manager.js +1 -1
  68. package/core/server/data/importer/importers/data/base.js +1 -1
  69. package/core/server/data/migrations/utils.js +2 -2
  70. package/core/server/data/migrations/versions/1.25/1-update-koenig-beta-html.js +1 -0
  71. package/core/server/data/migrations/versions/3.1/08-add-uuid-values-to-members.js +1 -0
  72. package/core/server/data/migrations/versions/3.22/02-settings-key-renames.js +2 -0
  73. package/core/server/data/migrations/versions/3.22/05-migrate-members-subscription-settings.js +3 -0
  74. package/core/server/data/migrations/versions/3.22/06-migrate-stripe-connect-settings.js +2 -0
  75. package/core/server/data/migrations/versions/3.23/01-migrate-bulk-email-settings.js +1 -0
  76. package/core/server/data/migrations/versions/3.29/01-remove-duplicate-subscriptions.js +2 -0
  77. package/core/server/data/migrations/versions/3.29/02-remove-duplicate-customers.js +2 -0
  78. package/core/server/data/migrations/versions/3.38/04-populate-recipient-filter-column.js +2 -0
  79. package/core/server/data/migrations/versions/4.0/01-update-mobiledoc.js +2 -0
  80. package/core/server/data/migrations/versions/4.0/03-populate-status-column-for-members.js +4 -0
  81. package/core/server/data/migrations/versions/4.0/06-populate-members-subscribe-events-table.js +1 -0
  82. package/core/server/data/migrations/versions/4.0/17-populate-members-status-events-table.js +1 -0
  83. package/core/server/data/migrations/versions/4.0/18-transform-urls-absolute-to-transform-ready.js +5 -0
  84. package/core/server/data/migrations/versions/4.0/22-solve-orphaned-webhooks.js +1 -0
  85. package/core/server/data/migrations/versions/4.0/23-regenerate-posts-html.js +1 -0
  86. package/core/server/data/migrations/versions/4.0/25-populate-members-paid-subscription-events-table.js +2 -1
  87. package/core/server/data/migrations/versions/4.12/02-fix-member-statuses.js +1 -0
  88. package/core/server/data/migrations/versions/4.14/01-fix-comped-member-statuses.js +3 -0
  89. package/core/server/data/migrations/versions/4.14/02-fix-free-members-status-events.js +1 -0
  90. package/core/server/data/migrations/versions/4.20/05-remove-not-null-constraint-from-portal-title.js +2 -0
  91. package/core/server/data/migrations/versions/4.23/01-truncate-offer-names.js +59 -0
  92. package/core/server/data/migrations/versions/4.3/04-attach-members-to-product.js +1 -0
  93. package/core/server/data/migrations/versions/4.4/01-restore-free-members-signup-setting-from-backup.js +1 -0
  94. package/core/server/data/migrations/versions/4.6/01-remove-comped-status.js +1 -0
  95. package/core/server/data/migrations/versions/4.8/04-migrate-show-newsletter-header-setting.js +1 -0
  96. package/core/server/data/migrations/versions/4.9/05-fix-missed-mobiledoc-url-transforms.js +1 -0
  97. package/core/server/data/migrations/versions/4.9/06-add-comped-status.js +1 -0
  98. package/core/server/data/migrations/versions/4.9/07-update-comped-members-status-events.js +1 -0
  99. package/core/server/data/schema/commands.js +2 -2
  100. package/core/server/ghost-server.js +2 -2
  101. package/core/server/lib/image/image-size.js +2 -2
  102. package/core/server/models/base/listeners.js +2 -2
  103. package/core/server/models/member-email-change-event.js +2 -2
  104. package/core/server/models/member-login-event.js +2 -2
  105. package/core/server/models/member-paid-subscription-event.js +3 -3
  106. package/core/server/models/member-payment-event.js +3 -3
  107. package/core/server/models/member-product-event.js +6 -6
  108. package/core/server/models/member-status-event.js +5 -3
  109. package/core/server/models/member-subscribe-event.js +9 -3
  110. package/core/server/models/relations/authors.js +1 -1
  111. package/core/server/models/settings.js +1 -1
  112. package/core/server/services/auth/passwordreset.js +1 -1
  113. package/core/server/services/auth/setup.js +1 -1
  114. package/core/server/services/email-analytics/jobs/index.js +1 -1
  115. package/core/server/services/mega/mega.js +6 -4
  116. package/core/server/services/mega/template.js +31 -12
  117. package/core/server/services/members/api.js +22 -0
  118. package/core/server/services/members/config.js +1 -1
  119. package/core/server/services/members/emails/signup-paid.js +168 -0
  120. package/core/server/services/members/service.js +6 -2
  121. package/core/server/services/members/stripe-connect.js +4 -2
  122. package/core/server/services/nft-oembed.js +6 -1
  123. package/core/server/services/oembed.js +36 -28
  124. package/core/server/services/permissions/can-this.js +1 -1
  125. package/core/server/services/redirects/api.js +20 -25
  126. package/core/server/services/redirects/index.js +18 -10
  127. package/core/server/services/redirects/utils.js +14 -0
  128. package/core/server/services/redirects/validation.js +10 -0
  129. package/core/server/services/route-settings/default-settings-manager.js +1 -1
  130. package/core/server/services/route-settings/index.js +40 -17
  131. package/core/server/services/route-settings/route-settings.js +120 -115
  132. package/core/server/services/route-settings/settings-loader.js +18 -36
  133. package/core/server/services/route-settings/yaml-parser.js +1 -1
  134. package/core/server/services/slack.js +1 -1
  135. package/core/server/services/themes/activation-bridge.js +3 -3
  136. package/core/server/services/themes/storage.js +2 -2
  137. package/core/server/services/twitter-embed.js +80 -0
  138. package/core/server/services/url/LocalFileCache.js +75 -0
  139. package/core/server/services/url/UrlService.js +15 -47
  140. package/core/server/services/url/index.js +17 -4
  141. package/core/server/services/xmlrpc.js +2 -2
  142. package/core/server/web/admin/app.js +2 -5
  143. package/core/server/web/admin/controller.js +35 -12
  144. package/core/server/web/admin/middleware/redirect-admin-urls.js +15 -0
  145. package/core/server/web/admin/views/default-prod.html +4 -4
  146. package/core/server/web/admin/views/default.html +4 -4
  147. package/core/server/web/api/canary/admin/app.js +0 -3
  148. package/core/server/web/api/canary/admin/middleware.js +1 -1
  149. package/core/server/web/api/canary/content/app.js +0 -3
  150. package/core/server/web/api/v2/admin/app.js +0 -3
  151. package/core/server/web/api/v2/admin/middleware.js +1 -1
  152. package/core/server/web/api/v2/content/app.js +0 -3
  153. package/core/server/web/api/v3/admin/app.js +0 -3
  154. package/core/server/web/api/v3/admin/middleware.js +1 -1
  155. package/core/server/web/api/v3/content/app.js +0 -3
  156. package/core/server/web/members/app.js +0 -3
  157. package/core/server/web/oauth/app.js +0 -4
  158. package/core/server/web/parent/app.js +17 -8
  159. package/core/server/web/shared/middleware/error-handler.js +57 -162
  160. package/core/server/web/shared/middleware/index.js +0 -4
  161. package/core/shared/config/defaults.json +7 -1
  162. package/core/shared/labs.js +10 -5
  163. package/core/shared/sentry.js +1 -1
  164. package/package.json +43 -42
  165. package/yarn.lock +802 -923
  166. package/content/themes/casper/assets/js/gallery-card.js +0 -24
  167. package/core/built/assets/ghost-dark-42cf6e0c730578940ec069bda45aea41.css +0 -1
  168. package/core/built/assets/ghost.min-fcf6a0738421f86c47c55f20d00c5ba9.css +0 -1
  169. package/core/frontend/services/theme-engine/middleware.js +0 -209
  170. package/core/server/web/shared/middleware/maintenance.js +0 -25
@@ -2,7 +2,6 @@ const debug = require('@tryghost/debug')('web:oauth:app');
2
2
  const {URL} = require('url');
3
3
  const express = require('../../../shared/express');
4
4
  const urlUtils = require('../../../shared/url-utils');
5
- const shared = require('../shared');
6
5
  const settingsCache = require('../../../shared/settings-cache');
7
6
  const models = require('../../models');
8
7
  const auth = require('../../services/auth');
@@ -24,9 +23,6 @@ module.exports = function setupOAuthApp() {
24
23
  }
25
24
  oauthApp.use(labsMiddleware);
26
25
 
27
- // send 503 json response in case of maintenance
28
- oauthApp.use(shared.middleware.maintenance);
29
-
30
26
  /**
31
27
  * Configure the passport.authenticate middleware
32
28
  * We need to configure it on each request because clientId and secret
@@ -5,7 +5,13 @@ const compress = require('compression');
5
5
  const mw = require('./middleware');
6
6
  const vhost = require('@tryghost/vhost-middleware');
7
7
 
8
- module.exports = function setupParentApp(options = {}) {
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}) {
9
15
  debug('ParentApp setup start');
10
16
  const parentApp = express('parent');
11
17
 
@@ -26,14 +32,17 @@ module.exports = function setupParentApp(options = {}) {
26
32
 
27
33
  // Mount the express apps on the parentApp
28
34
 
29
- // ADMIN + API
30
- const backendApp = require('./backend')();
31
- parentApp.use(vhost(config.getBackendMountPath(), backendApp));
32
-
33
- // SITE + MEMBERS
34
- const frontendApp = require('./frontend')(options);
35
- parentApp.use(vhost(config.getFrontendMountPath(), frontendApp));
35
+ if (backend) {
36
+ debug('Mounting bakcend: ADMIN + API');
37
+ const backendApp = require('./backend')();
38
+ parentApp.use(vhost(config.getBackendMountPath(), backendApp));
39
+ }
36
40
 
41
+ if (frontend) {
42
+ debug('Mounting frontend: SITE + MEMBERS');
43
+ const frontendApp = require('./frontend')({start});
44
+ parentApp.use(vhost(config.getFrontendMountPath(), frontendApp));
45
+ }
37
46
  debug('ParentApp setup end');
38
47
 
39
48
  return parentApp;
@@ -1,16 +1,10 @@
1
- const hbs = require('express-hbs');
2
1
  const _ = require('lodash');
3
2
  const debug = require('@tryghost/debug')('error-handler');
4
3
  const errors = require('@tryghost/errors');
5
4
  const tpl = require('@tryghost/tpl');
6
- const config = require('../../../../shared/config');
7
- const helpers = require('../../../../frontend/services/routing/helpers');
8
5
  const sentry = require('../../../../shared/sentry');
9
6
 
10
7
  const messages = {
11
- oopsErrorTemplateHasError: 'Oops, seems there is an error in the error template.',
12
- encounteredError: 'Encountered the error: ',
13
- whilstTryingToRender: 'whilst trying to render an error page for the error: ',
14
8
  pageNotFound: 'Page not found',
15
9
  resourceNotFound: 'Resource not found',
16
10
  actions: {
@@ -45,36 +39,44 @@ const messages = {
45
39
  }
46
40
  };
47
41
 
48
- const escapeExpression = hbs.Utils.escapeExpression;
49
- const _private = {};
50
- const errorHandler = {};
42
+ const updateStack = (err) => {
43
+ let stackbits = err.stack.split(/\n/g);
51
44
 
52
- /**
53
- * This is a bare minimum setup, which allows us to render the error page
54
- * It uses the {{asset}} helper, and nothing more
55
- */
56
- _private.createHbsEngine = () => {
57
- const engine = hbs.create();
58
- engine.registerHelper('asset', require('../../../../frontend/helpers/asset'));
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
59
56
 
60
- return engine.express4();
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');
61
66
  };
62
67
 
63
68
  /**
64
69
  * Get an error ready to be shown the the user
65
- *
66
- * @TODO: support multiple errors within one single error, see https://github.com/TryGhost/Ghost/issues/7116#issuecomment-252231809
67
70
  */
68
- _private.prepareError = (err, req, res, next) => {
71
+ module.exports.prepareError = (err, req, res, next) => {
69
72
  debug(err);
70
73
 
71
74
  if (Array.isArray(err)) {
72
75
  err = err[0];
73
76
  }
74
77
 
75
- if (!errors.utils.isIgnitionError(err)) {
78
+ if (!errors.utils.isGhostError(err)) {
76
79
  // We need a special case for 404 errors
77
- // @TODO look at adding this to the GhostError class
78
80
  if (err.statusCode && err.statusCode === 404) {
79
81
  err = new errors.NotFoundError({
80
82
  err: err
@@ -88,7 +90,7 @@ _private.prepareError = (err, req, res, next) => {
88
90
  statusCode: err.statusCode
89
91
  });
90
92
  } else {
91
- err = new errors.GhostError({
93
+ err = new errors.InternalServerError({
92
94
  err: err,
93
95
  message: err.message,
94
96
  statusCode: err.statusCode
@@ -102,6 +104,8 @@ _private.prepareError = (err, req, res, next) => {
102
104
  // alternative for res.status();
103
105
  res.statusCode = err.statusCode;
104
106
 
107
+ err.stack = updateStack(err);
108
+
105
109
  // never cache errors
106
110
  res.set({
107
111
  'Cache-Control': 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'
@@ -110,7 +114,7 @@ _private.prepareError = (err, req, res, next) => {
110
114
  next(err);
111
115
  };
112
116
 
113
- _private.JSONErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
117
+ const jsonErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
114
118
  res.json({
115
119
  errors: [{
116
120
  message: err.message,
@@ -123,7 +127,24 @@ _private.JSONErrorRenderer = (err, req, res, next) => { // eslint-disable-line n
123
127
  });
124
128
  };
125
129
 
126
- _private.prepareUserMessage = (err, res) => {
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) => {
127
148
  const userError = {
128
149
  message: err.message,
129
150
  context: err.context
@@ -169,161 +190,35 @@ _private.prepareUserMessage = (err, res) => {
169
190
  return userError;
170
191
  };
171
192
 
172
- _private.JSONErrorRendererV2 = (err, req, res, next) => { // eslint-disable-line no-unused-vars
173
- const userError = _private.prepareUserMessage(err, req);
174
-
175
- res.json({
176
- errors: [{
177
- message: userError.message || null,
178
- context: userError.context || null,
179
- type: err.errorType || null,
180
- details: err.errorDetails || null,
181
- property: err.property || null,
182
- help: err.help || null,
183
- code: err.code || null,
184
- id: err.id || null
185
- }]
186
- });
187
- };
188
-
189
- _private.ErrorFallbackMessage = err => `<h1>${tpl(messages.oopsErrorTemplateHasError)}</h1>
190
- <p>${tpl(messages.encounteredError)}</p>
191
- <pre>${escapeExpression(err.message || err)}</pre>
192
- <br ><p>${tpl(messages.whilstTryingToRender)}</p>
193
- ${err.statusCode} <pre>${escapeExpression(err.message || err)}</pre>`;
194
-
195
- _private.ThemeErrorRenderer = (err, req, res, next) => {
196
- // If the error code is explicitly set to STATIC_FILE_NOT_FOUND,
197
- // Skip trying to render an HTML error, and move on to the basic error renderer
198
- // We do this because customised 404 templates could reference the image that's missing
199
- // A better long term solution might be to do this based on extension
200
- if (err.code === 'STATIC_FILE_NOT_FOUND') {
201
- return next(err);
202
- }
203
-
204
- // Renderer begin
205
- // Format Data
206
- const data = {
207
- message: err.message,
208
- // @deprecated Remove in Ghost 5.0
209
- code: err.statusCode,
210
- statusCode: err.statusCode,
211
- errorDetails: err.errorDetails || []
212
- };
213
-
214
- // Template
215
- // @TODO: very dirty !!!!!!
216
- helpers.templates.setTemplate(req, res);
217
-
218
- // It can be that something went wrong with the theme or otherwise loading handlebars
219
- // This ensures that no matter what res.render will work here
220
- // @TODO: split the error handler for assets, admin & theme to refactor this away
221
- if (_.isEmpty(req.app.engines)) {
222
- res._template = 'error';
223
- req.app.engine('hbs', _private.createHbsEngine());
224
- req.app.set('view engine', 'hbs');
225
- req.app.set('views', config.get('paths').defaultViews);
226
- }
227
-
228
- // @TODO use renderer here?!
229
- // Render Call - featuring an error handler for what happens if rendering fails
230
- res.render(res._template, data, (_err, html) => {
231
- if (!_err) {
232
- return res.send(html);
233
- }
234
-
235
- // re-attach new error e.g. error template has syntax error or misusage
236
- req.err = _err;
237
-
238
- // And then try to explain things to the user...
239
- // Cheat and output the error using handlebars escapeExpression
240
- return res.status(500).send(_private.ErrorFallbackMessage(_err));
241
- });
242
- };
243
-
244
- _private.HTMLErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
245
- const data = {
246
- message: err.message,
247
- statusCode: err.statusCode,
248
- errorDetails: err.errorDetails || []
249
- };
250
-
251
- // e.g. if you serve the admin /ghost and Ghost returns a 503 because it generates the urls at the moment.
252
- // This ensures that no matter what res.render will work here
253
- // @TODO: put to prepare error function?
254
- if (_.isEmpty(req.app.engines)) {
255
- res._template = 'error';
256
- req.app.engine('hbs', _private.createHbsEngine());
257
- req.app.set('view engine', 'hbs');
258
- req.app.set('views', config.get('paths').defaultViews);
259
- }
260
-
261
- res.render('error', data, (_err, html) => {
262
- if (!_err) {
263
- return res.send(html);
264
- }
265
-
266
- // re-attach new error e.g. error template has syntax error or misusage
267
- req.err = _err;
268
-
269
- // And then try to explain things to the user...
270
- // Cheat and output the error using handlebars escapeExpression
271
- return res.status(500).send(_private.ErrorFallbackMessage(_err));
272
- });
273
- };
274
-
275
- _private.BasicErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
276
- return res.send(res.statusCode + ' ' + err.message);
277
- };
278
-
279
- errorHandler.resourceNotFound = (req, res, next) => {
280
- // TODO, handle unknown resources & methods differently, so that we can also produce
281
- // 405 Method Not Allowed
193
+ module.exports.resourceNotFound = (req, res, next) => {
282
194
  next(new errors.NotFoundError({message: tpl(messages.resourceNotFound)}));
283
195
  };
284
196
 
285
- errorHandler.pageNotFound = (req, res, next) => {
197
+ module.exports.pageNotFound = (req, res, next) => {
286
198
  next(new errors.NotFoundError({message: tpl(messages.pageNotFound)}));
287
199
  };
288
200
 
289
- errorHandler.handleJSONResponse = [
201
+ module.exports.handleJSONResponse = [
290
202
  // Make sure the error can be served
291
- _private.prepareError,
203
+ module.exports.prepareError,
292
204
  // Handle the error in Sentry
293
205
  sentry.errorHandler,
294
206
  // Render the error using JSON format
295
- _private.JSONErrorRenderer
207
+ jsonErrorRenderer
296
208
  ];
297
209
 
298
- errorHandler.handleJSONResponseV2 = [
210
+ module.exports.handleJSONResponseV2 = [
299
211
  // Make sure the error can be served
300
- _private.prepareError,
212
+ module.exports.prepareError,
301
213
  // Handle the error in Sentry
302
214
  sentry.errorHandler,
303
215
  // Render the error using JSON format
304
- _private.JSONErrorRendererV2
216
+ jsonErrorRendererV2
305
217
  ];
306
218
 
307
- errorHandler.handleHTMLResponse = [
219
+ module.exports.handleHTMLResponse = [
308
220
  // Make sure the error can be served
309
- _private.prepareError,
221
+ module.exports.prepareError,
310
222
  // Handle the error in Sentry
311
- sentry.errorHandler,
312
- // Render the error using HTML format
313
- _private.HTMLErrorRenderer,
314
- // Fall back to basic if HTML is not explicitly accepted
315
- _private.BasicErrorRenderer
223
+ sentry.errorHandler
316
224
  ];
317
-
318
- errorHandler.handleThemeResponse = [
319
- // Make sure the error can be served
320
- _private.prepareError,
321
- // Handle the error in Sentry
322
- sentry.errorHandler,
323
- // Render the error using theme template
324
- _private.ThemeErrorRenderer,
325
- // Fall back to basic if HTML is not explicitly accepted
326
- _private.BasicErrorRenderer
327
- ];
328
-
329
- module.exports = errorHandler;
@@ -15,10 +15,6 @@ module.exports = {
15
15
  return require('./error-handler');
16
16
  },
17
17
 
18
- get maintenance() {
19
- return require('./maintenance');
20
- },
21
-
22
18
  get prettyUrls() {
23
19
  return require('./pretty-urls');
24
20
  },
@@ -131,7 +131,13 @@
131
131
  "version": "1.12"
132
132
  },
133
133
  "tenor": {
134
- "apiKey": null,
134
+ "publicReadOnlyApiKey": null,
135
135
  "contentFilter": "off"
136
+ },
137
+ "opensea": {
138
+ "privateReadOnlyApiKey": null
139
+ },
140
+ "twitter": {
141
+ "privateReadOnlyToken": null
136
142
  }
137
143
  }
@@ -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,14 @@ const ALPHA_FEATURES = [
33
34
  'mediaAPI',
34
35
  'filesAPI',
35
36
  'membersAutoLogin',
36
- 'buttonCard',
37
37
  'calloutCard',
38
- 'nftCard',
39
38
  'accordionCard',
40
- 'gifsCard'
39
+ 'fileCard',
40
+ 'audioCard',
41
+ 'videoCard',
42
+ 'productCard',
43
+ 'quoteStyles',
44
+ 'beforeAfterCard'
41
45
  ];
42
46
 
43
47
  module.exports.GA_KEYS = [...GA_FEATURES];
@@ -47,7 +51,7 @@ module.exports.getAll = () => {
47
51
  const labs = _.cloneDeep(settingsCache.get('labs')) || {};
48
52
 
49
53
  ALPHA_FEATURES.forEach((alphaKey) => {
50
- if (labs[alphaKey] && !(config.get('enableDeveloperExperiments') || process.env.NODE_ENV.match(/^testing/))) {
54
+ if (labs[alphaKey] && !(config.get('enableDeveloperExperiments') || process.env.NODE_ENV.startsWith('test'))) {
51
55
  delete labs[alphaKey];
52
56
  }
53
57
  });
@@ -102,6 +106,7 @@ module.exports.enabledHelper = function enabledHelper(options, callback) {
102
106
  });
103
107
  errDetails.help = tpl(options.errorHelp || messages.errorHelp, {url: options.helpUrl});
104
108
 
109
+ // eslint-disable-next-line no-restricted-syntax
105
110
  logging.error(new errors.DisabledFeatureError(errDetails));
106
111
 
107
112
  const {SafeString} = require('express-hbs');
@@ -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.isIgnitionError(error)) {
21
+ if (!errors.utils.isGhostError(error)) {
22
22
  return true;
23
23
  }
24
24
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ghost",
3
- "version": "4.22.4",
3
+ "version": "4.25.1",
4
4
  "description": "The professional publishing platform",
5
5
  "author": "Ghost Foundation",
6
6
  "homepage": "https://ghost.org",
@@ -55,56 +55,57 @@
55
55
  "dependencies": {
56
56
  "@nexes/nql": "0.6.0",
57
57
  "@sentry/node": "6.15.0",
58
- "@tryghost/adapter-manager": "0.2.18",
58
+ "@tryghost/adapter-manager": "0.2.24",
59
59
  "@tryghost/admin-api-schema": "2.6.1",
60
- "@tryghost/bookshelf-plugins": "0.3.4",
61
- "@tryghost/bootstrap-socket": "0.2.13",
60
+ "@tryghost/bookshelf-plugins": "0.3.5",
61
+ "@tryghost/bootstrap-socket": "0.2.14",
62
62
  "@tryghost/color-utils": "0.1.5",
63
63
  "@tryghost/config-url-helpers": "0.1.3",
64
64
  "@tryghost/constants": "1.0.0",
65
65
  "@tryghost/custom-theme-settings-service": "0.3.1",
66
66
  "@tryghost/debug": "0.1.9",
67
- "@tryghost/email-analytics-provider-mailgun": "1.0.5",
68
- "@tryghost/email-analytics-service": "1.0.4",
69
- "@tryghost/errors": "0.2.17",
70
- "@tryghost/express-dynamic-redirects": "0.2.1",
67
+ "@tryghost/email-analytics-provider-mailgun": "1.0.6",
68
+ "@tryghost/email-analytics-service": "1.0.5",
69
+ "@tryghost/errors": "1.0.4",
70
+ "@tryghost/express-dynamic-redirects": "0.2.2",
71
71
  "@tryghost/helpers": "1.1.54",
72
- "@tryghost/image-transform": "1.0.18",
73
- "@tryghost/job-manager": "0.8.12",
72
+ "@tryghost/image-transform": "1.0.24",
73
+ "@tryghost/job-manager": "0.8.16",
74
74
  "@tryghost/kg-card-factory": "3.1.0",
75
75
  "@tryghost/kg-default-atoms": "3.1.0",
76
- "@tryghost/kg-default-cards": "5.8.3",
76
+ "@tryghost/kg-default-cards": "5.9.2",
77
77
  "@tryghost/kg-markdown-html-renderer": "5.1.0",
78
- "@tryghost/kg-mobiledoc-html-renderer": "5.2.0",
79
- "@tryghost/limit-service": "1.0.0",
80
- "@tryghost/logging": "1.0.1",
78
+ "@tryghost/kg-mobiledoc-html-renderer": "5.3.0",
79
+ "@tryghost/limit-service": "1.0.6",
80
+ "@tryghost/logging": "1.0.2",
81
81
  "@tryghost/magic-link": "1.0.14",
82
- "@tryghost/members-api": "2.7.4",
83
- "@tryghost/members-csv": "1.1.8",
84
- "@tryghost/members-importer": "0.3.4",
85
- "@tryghost/members-offers": "0.10.2",
86
- "@tryghost/members-ssr": "1.0.15",
82
+ "@tryghost/members-api": "2.8.4",
83
+ "@tryghost/members-csv": "1.2.0",
84
+ "@tryghost/members-importer": "0.3.5",
85
+ "@tryghost/members-offers": "0.10.3",
86
+ "@tryghost/members-ssr": "1.0.16",
87
87
  "@tryghost/metrics": "1.0.1",
88
- "@tryghost/minifier": "0.1.1",
88
+ "@tryghost/minifier": "0.1.7",
89
89
  "@tryghost/mw-session-from-token": "0.1.26",
90
- "@tryghost/nodemailer": "0.3.7",
91
- "@tryghost/package-json": "1.0.6",
90
+ "@tryghost/nodemailer": "0.3.8",
91
+ "@tryghost/package-json": "1.0.12",
92
92
  "@tryghost/promise": "0.1.13",
93
- "@tryghost/request": "0.1.9",
93
+ "@tryghost/request": "0.1.10",
94
94
  "@tryghost/root-utils": "0.3.7",
95
95
  "@tryghost/security": "0.2.13",
96
- "@tryghost/session-service": "0.1.28",
96
+ "@tryghost/session-service": "0.1.34",
97
+ "@tryghost/settings-path-manager": "0.1.2",
97
98
  "@tryghost/social-urls": "0.1.27",
98
99
  "@tryghost/string": "0.1.21",
99
100
  "@tryghost/tpl": "0.1.8",
100
101
  "@tryghost/update-check-service": "0.2.5",
101
102
  "@tryghost/url-utils": "2.0.4",
102
- "@tryghost/validator": "0.1.8",
103
+ "@tryghost/validator": "0.1.9",
103
104
  "@tryghost/version": "0.1.7",
104
105
  "@tryghost/vhost-middleware": "1.0.19",
105
106
  "@tryghost/zip": "1.1.18",
106
107
  "amperize": "0.6.1",
107
- "analytics-node": "5.1.2",
108
+ "analytics-node": "6.0.0",
108
109
  "bluebird": "3.7.2",
109
110
  "body-parser": "1.19.0",
110
111
  "bookshelf": "1.2.0",
@@ -129,7 +130,7 @@
129
130
  "ghost-storage-base": "1.0.0",
130
131
  "glob": "7.2.0",
131
132
  "got": "9.6.0",
132
- "gscan": "4.11.0",
133
+ "gscan": "4.15.2",
133
134
  "html-to-text": "5.1.1",
134
135
  "image-size": "1.0.0",
135
136
  "intl": "1.2.5",
@@ -144,28 +145,28 @@
144
145
  "lodash": "4.17.21",
145
146
  "luxon": "2.1.1",
146
147
  "mailgun-js": "0.22.0",
147
- "metascraper": "5.25.1",
148
- "metascraper-author": "5.25.1",
149
- "metascraper-description": "5.25.1",
150
- "metascraper-image": "5.25.1",
151
- "metascraper-logo": "5.25.1",
152
- "metascraper-logo-favicon": "5.25.1",
153
- "metascraper-publisher": "5.25.1",
154
- "metascraper-title": "5.25.1",
155
- "metascraper-url": "5.25.1",
148
+ "metascraper": "5.25.4",
149
+ "metascraper-author": "5.25.4",
150
+ "metascraper-description": "5.25.4",
151
+ "metascraper-image": "5.25.4",
152
+ "metascraper-logo": "5.25.4",
153
+ "metascraper-logo-favicon": "5.25.4",
154
+ "metascraper-publisher": "5.25.4",
155
+ "metascraper-title": "5.25.4",
156
+ "metascraper-url": "5.25.4",
156
157
  "moment": "2.24.0",
157
158
  "moment-timezone": "0.5.23",
158
159
  "multer": "1.4.3",
159
160
  "mysql": "2.18.1",
160
161
  "nconf": "0.11.3",
161
162
  "node-jose": "2.0.0",
162
- "oembed-parser": "1.5.2",
163
+ "oembed-parser": "1.4.9",
163
164
  "passport": "0.5.0",
164
165
  "passport-google-oauth": "2.0.0",
165
166
  "path-match": "1.2.4",
166
167
  "probe-image-size": "5.0.0",
167
168
  "rss": "1.2.2",
168
- "sanitize-html": "2.5.3",
169
+ "sanitize-html": "2.6.0",
169
170
  "semver": "7.3.5",
170
171
  "stoppable": "1.1.0",
171
172
  "tough-cookie": "4.0.0",
@@ -173,16 +174,16 @@
173
174
  "xml": "1.0.1"
174
175
  },
175
176
  "optionalDependencies": {
176
- "@tryghost/html-to-mobiledoc": "1.3.2",
177
+ "@tryghost/html-to-mobiledoc": "1.4.1",
177
178
  "sqlite3": "5.0.2"
178
179
  },
179
180
  "devDependencies": {
180
181
  "@lodder/grunt-postcss": "3.1.1",
181
182
  "c8": "7.10.0",
182
183
  "coffeescript": "2.6.1",
183
- "cssnano": "5.0.11",
184
+ "cssnano": "5.0.12",
184
185
  "eslint": "7.32.0",
185
- "eslint-plugin-ghost": "2.7.0",
186
+ "eslint-plugin-ghost": "2.11.0",
186
187
  "grunt": "1.4.1",
187
188
  "grunt-bg-shell": "2.3.3",
188
189
  "grunt-contrib-clean": "2.0.0",
@@ -200,7 +201,7 @@
200
201
  "mock-knex": "0.4.10",
201
202
  "nock": "13.2.1",
202
203
  "papaparse": "5.3.1",
203
- "postcss": "8.3.11",
204
+ "postcss": "8.4.4",
204
205
  "rewire": "5.0.0",
205
206
  "should": "13.2.3",
206
207
  "sinon": "11.1.2",