ghost 4.29.0 → 4.32.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.
Files changed (79) hide show
  1. package/content/themes/casper/assets/built/screen.css +1 -1
  2. package/content/themes/casper/assets/built/screen.css.map +1 -1
  3. package/content/themes/casper/assets/css/screen.css +110 -43
  4. package/content/themes/casper/package.json +1 -1
  5. package/core/boot.js +3 -5
  6. package/core/built/assets/{chunk.3.e54be01b5124e4e27958.js → chunk.3.8f95b516d88ff4eec64c.js} +7 -7
  7. package/core/built/assets/ghost-dark-43f5faa616791819b3ae91e128ec41f0.css +1 -0
  8. package/core/built/assets/{ghost.min-ba8ef5d16b8a6f9072564a368154df72.js → ghost.min-2b20489c79323b165909749382adc158.js} +4 -4
  9. package/core/built/assets/ghost.min-c3f7cbabcc1a69476534453c6c747ee3.css +1 -0
  10. package/core/built/assets/icons/file-upload.svg +1 -1
  11. package/core/built/assets/{vendor.min-c450359ad46217cd48c00b277ae54a09.js → vendor.min-992a9b07f7d0a67b5a4afd91319edf8b.js} +615 -579
  12. package/core/frontend/apps/amp/lib/views/amp.hbs +134 -0
  13. package/core/frontend/helpers/get.js +4 -0
  14. package/core/frontend/services/theme-engine/i18n/i18n.js +11 -12
  15. package/core/frontend/services/theme-engine/i18n/index.js +1 -2
  16. package/core/frontend/services/theme-engine/i18n/theme-i18n.js +5 -4
  17. package/core/frontend/src/cards/css/audio.css +4 -2
  18. package/core/frontend/src/cards/css/before-after.css +45 -11
  19. package/core/frontend/src/cards/css/bookmark.css +3 -2
  20. package/core/frontend/src/cards/css/button.css +4 -3
  21. package/core/frontend/src/cards/css/callout.css +10 -5
  22. package/core/frontend/src/cards/css/file.css +107 -48
  23. package/core/frontend/src/cards/css/gallery.css +5 -3
  24. package/core/frontend/src/cards/css/header.css +228 -0
  25. package/core/frontend/src/cards/css/nft.css +1 -7
  26. package/core/frontend/src/cards/css/product.css +24 -26
  27. package/core/frontend/src/cards/css/toggle.css +32 -22
  28. package/core/frontend/src/cards/css/video.css +103 -44
  29. package/core/frontend/src/cards/js/before-after.js +10 -15
  30. package/core/frontend/src/cards/js/video.js +81 -13
  31. package/core/frontend/web/middleware/error-handler.js +2 -2
  32. package/core/frontend/web/site.js +2 -1
  33. package/core/server/api/canary/oembed.js +1 -2
  34. package/core/server/data/db/state-manager.js +5 -8
  35. package/core/server/lib/image/cached-image-size-from-url.js +3 -4
  36. package/core/server/lib/image/image-utils.js +2 -2
  37. package/core/server/lib/image/index.js +1 -2
  38. package/core/server/run-update-check.js +1 -13
  39. package/core/server/services/email-analytics/index.js +2 -4
  40. package/core/server/services/email-analytics/jobs/fetch-latest.js +2 -21
  41. package/core/server/services/integrations/integrations-service.js +2 -2
  42. package/core/server/services/invites/index.js +0 -2
  43. package/core/server/services/invites/invites.js +3 -3
  44. package/core/server/services/jobs/job-service.js +1 -1
  45. package/core/server/services/mail/templates/invite-user.html +1 -1
  46. package/core/server/services/mail/templates/reset-password.html +1 -1
  47. package/core/server/services/mail/templates/welcome.html +1 -1
  48. package/core/server/services/mega/template.js +109 -1
  49. package/core/server/services/members/api.js +0 -1
  50. package/core/server/services/members/config.js +4 -7
  51. package/core/server/services/members/emails/signin.js +1 -1
  52. package/core/server/services/members/emails/signup-paid.js +1 -1
  53. package/core/server/services/members/emails/signup.js +1 -1
  54. package/core/server/services/members/emails/subscribe.js +1 -1
  55. package/core/server/services/members/emails/updateEmail.js +1 -1
  56. package/core/server/services/members/service.js +1 -4
  57. package/core/server/services/notifications/index.js +0 -2
  58. package/core/server/services/notifications/notifications.js +4 -5
  59. package/core/server/services/stripe/index.js +0 -2
  60. package/core/server/services/twitter-embed.js +2 -1
  61. package/core/server/web/admin/app.js +4 -2
  62. package/core/server/web/admin/views/default-prod.html +4 -4
  63. package/core/server/web/admin/views/default.html +4 -4
  64. package/core/server/web/api/app.js +3 -2
  65. package/core/server/web/api/canary/admin/app.js +4 -2
  66. package/core/server/web/api/canary/content/app.js +4 -2
  67. package/core/server/web/api/v2/admin/app.js +4 -2
  68. package/core/server/web/api/v2/content/app.js +4 -2
  69. package/core/server/web/api/v3/admin/app.js +4 -2
  70. package/core/server/web/api/v3/content/app.js +4 -2
  71. package/core/server/web/members/app.js +6 -4
  72. package/core/server/web/shared/middleware/index.js +0 -4
  73. package/core/shared/config/overrides.json +11 -1
  74. package/core/shared/labs.js +6 -6
  75. package/package.json +22 -21
  76. package/yarn.lock +212 -111
  77. package/core/built/assets/ghost-dark-b93e2e2dcc4c0e1efa981314f45f8cda.css +0 -1
  78. package/core/built/assets/ghost.min-578a1b7e68d1f7ae0003ebe421b7c182.css +0 -1
  79. package/core/server/web/shared/middleware/error-handler.js +0 -224
@@ -207,7 +207,6 @@ function createApiInstance(config) {
207
207
  Settings: models.Settings
208
208
  },
209
209
  stripeAPIService: stripeService.api,
210
- logger: logging,
211
210
  offersAPI: offersService.api,
212
211
  labsService: labsService
213
212
  });
@@ -1,4 +1,5 @@
1
1
  const errors = require('@tryghost/errors');
2
+ const logging = require('@tryghost/logging');
2
3
  const tpl = require('@tryghost/tpl');
3
4
  const {URL} = require('url');
4
5
  const crypto = require('crypto');
@@ -15,15 +16,11 @@ class MembersConfigProvider {
15
16
  * @param {{get: (key: string) => any}} options.settingsCache
16
17
  * @param {{get: (key: string) => any}} options.config
17
18
  * @param {any} options.urlUtils
18
- * @param {any} options.logging
19
- * @param {{original: string}} options.ghostVersion
20
19
  */
21
20
  constructor(options) {
22
21
  this._settingsCache = options.settingsCache;
23
22
  this._config = options.config;
24
23
  this._urlUtils = options.urlUtils;
25
- this._logging = options.logging;
26
- this._ghostVersion = options.ghostVersion;
27
24
  }
28
25
 
29
26
  /**
@@ -193,12 +190,12 @@ class MembersConfigProvider {
193
190
  getAuthSecret() {
194
191
  const hexSecret = this._settingsCache.get('members_email_auth_secret');
195
192
  if (!hexSecret) {
196
- this._logging.warn('Could not find members_email_auth_secret, using dynamically generated secret');
193
+ logging.warn('Could not find members_email_auth_secret, using dynamically generated secret');
197
194
  return crypto.randomBytes(64);
198
195
  }
199
196
  const secret = Buffer.from(hexSecret, 'hex');
200
197
  if (secret.length < 64) {
201
- this._logging.warn('members_email_auth_secret not large enough (64 bytes), using dynamically generated secret');
198
+ logging.warn('members_email_auth_secret not large enough (64 bytes), using dynamically generated secret');
202
199
  return crypto.randomBytes(64);
203
200
  }
204
201
  return secret;
@@ -236,7 +233,7 @@ class MembersConfigProvider {
236
233
  let publicKey = this._settingsCache.get('members_public_key');
237
234
 
238
235
  if (!privateKey || !publicKey) {
239
- this._logging.warn('Could not find members_private_key, using dynamically generated keypair');
236
+ logging.warn('Could not find members_private_key, using dynamically generated keypair');
240
237
  const keypair = createKeypair({bits: 1024});
241
238
  privateKey = keypair.private;
242
239
  publicKey = keypair.public;
@@ -99,7 +99,7 @@ module.exports = ({siteTitle, email, url, accentColor = '#15212A', siteDomain, s
99
99
  }
100
100
  </style>
101
101
  </head>
102
- <body class="" style="background-color: #ffffff; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.5em; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
102
+ <body style="background-color: #ffffff; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.5em; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
103
103
  <table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
104
104
  <tr>
105
105
  <td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;">&nbsp;</td>
@@ -99,7 +99,7 @@ module.exports = ({siteTitle, email, url, accentColor = '#15212A', siteDomain, s
99
99
  }
100
100
  </style>
101
101
  </head>
102
- <body class="" style="background-color: #FFFFFF; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.5em; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
102
+ <body style="background-color: #FFFFFF; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.5em; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
103
103
  <table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #FFFFFF;">
104
104
  <tr>
105
105
  <td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;">&nbsp;</td>
@@ -99,7 +99,7 @@ module.exports = ({siteTitle, email, url, accentColor = '#15212A', siteDomain, s
99
99
  }
100
100
  </style>
101
101
  </head>
102
- <body class="" style="background-color: #FFFFFF; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.5em; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
102
+ <body style="background-color: #FFFFFF; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.5em; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
103
103
  <table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #FFFFFF;">
104
104
  <tr>
105
105
  <td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;">&nbsp;</td>
@@ -99,7 +99,7 @@ module.exports = ({siteTitle, email, url, accentColor = '#15212A', siteDomain, s
99
99
  }
100
100
  </style>
101
101
  </head>
102
- <body class="" style="background-color: #FFFFFF; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
102
+ <body style="background-color: #FFFFFF; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
103
103
  <table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #FFFFFF;">
104
104
  <tr>
105
105
  <td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;">&nbsp;</td>
@@ -92,7 +92,7 @@ module.exports = ({email, url}) => `
92
92
  }
93
93
  </style>
94
94
  </head>
95
- <body class="" style="background-color: #F4F8FB; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
95
+ <body style="background-color: #F4F8FB; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
96
96
  <table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #F4F8FB;">
97
97
  <tr>
98
98
  <td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;">&nbsp;</td>
@@ -13,7 +13,6 @@ const labsService = require('../../../shared/labs');
13
13
  const settingsCache = require('../../../shared/settings-cache');
14
14
  const config = require('../../../shared/config');
15
15
  const models = require('../../models');
16
- const ghostVersion = require('@tryghost/version');
17
16
  const _ = require('lodash');
18
17
  const {GhostMailer} = require('../mail');
19
18
  const jobsService = require('../jobs');
@@ -35,9 +34,7 @@ const ghostMailer = new GhostMailer();
35
34
  const membersConfig = new MembersConfigProvider({
36
35
  config,
37
36
  settingsCache,
38
- urlUtils,
39
- logging,
40
- ghostVersion
37
+ urlUtils
41
38
  });
42
39
 
43
40
  let membersApi;
@@ -1,10 +1,8 @@
1
1
  const settingsCache = require('../../../shared/settings-cache');
2
- const ghostVersion = require('@tryghost/version');
3
2
  const Notifications = require('./notifications');
4
3
  const models = require('../../models');
5
4
 
6
5
  module.exports.notifications = new Notifications({
7
6
  settingsCache,
8
- ghostVersion: ghostVersion.full,
9
7
  SettingsModel: models.Settings
10
8
  });
@@ -3,6 +3,7 @@ const semver = require('semver');
3
3
  const Promise = require('bluebird');
4
4
  const _ = require('lodash');
5
5
  const errors = require('@tryghost/errors');
6
+ const ghostVersion = require('@tryghost/version');
6
7
  const tpl = require('@tryghost/tpl');
7
8
  const ObjectId = require('bson-objectid');
8
9
 
@@ -16,12 +17,10 @@ class Notifications {
16
17
  *
17
18
  * @param {Object} options
18
19
  * @param {Object} options.settingsCache - settings cache instance
19
- * @param {String} options.ghostVersion - Ghost instance version in "full" format - major.minor.patch
20
20
  * @param {Object} options.SettingsModel - Ghost's Setting model instance
21
21
  */
22
- constructor({settingsCache, ghostVersion, SettingsModel}) {
22
+ constructor({settingsCache, SettingsModel}) {
23
23
  this.settingsCache = settingsCache;
24
- this.ghostVersion = ghostVersion;
25
24
  this.SettingsModel = SettingsModel;
26
25
  }
27
26
 
@@ -74,7 +73,7 @@ class Notifications {
74
73
  browse({user}) {
75
74
  let allNotifications = this.fetchAllNotifications();
76
75
  allNotifications = _.orderBy(allNotifications, 'addedAt', 'desc');
77
- const blogVersion = this.ghostVersion.match(/^(\d+\.)(\d+\.)(\d+)/);
76
+ const blogVersion = ghostVersion.full.match(/^(\d+\.)(\d+\.)(\d+)/);
78
77
 
79
78
  allNotifications = allNotifications.filter((notification) => {
80
79
  if (notification.createdAtVersion && !this.wasSeen(notification, user)) {
@@ -128,7 +127,7 @@ class Notifications {
128
127
  location: 'bottom',
129
128
  status: 'alert',
130
129
  id: ObjectId().toHexString(),
131
- createdAtVersion: this.ghostVersion
130
+ createdAtVersion: ghostVersion.full
132
131
  };
133
132
 
134
133
  const overrides = {
@@ -1,5 +1,4 @@
1
1
  const _ = require('lodash');
2
- const logging = require('@tryghost/logging');
3
2
  const StripeAPIService = require('@tryghost/members-stripe-service');
4
3
 
5
4
  const config = require('../../../shared/config');
@@ -9,7 +8,6 @@ const events = require('../../lib/common/events');
9
8
  const {getConfig} = require('./config');
10
9
 
11
10
  const api = new StripeAPIService({
12
- logger: logging,
13
11
  config: {}
14
12
  });
15
13
 
@@ -1,4 +1,5 @@
1
1
  const {extract} = require('oembed-parser');
2
+ const logging = require('@tryghost/logging');
2
3
  const labs = require('../../shared/labs');
3
4
 
4
5
  /**
@@ -69,7 +70,7 @@ class TwitterOEmbedProvider {
69
70
  oembedData.tweet_data = body.data;
70
71
  oembedData.tweet_data.includes = body.includes;
71
72
  } catch (err) {
72
- this.dependencies.logging.error(err);
73
+ logging.error(err);
73
74
  }
74
75
  }
75
76
 
@@ -5,6 +5,8 @@ const config = require('../../../shared/config');
5
5
  const constants = require('@tryghost/constants');
6
6
  const urlUtils = require('../../../shared/url-utils');
7
7
  const shared = require('../shared');
8
+ const errorHandler = require('@tryghost/mw-error-handler');
9
+ const sentry = require('../../../shared/sentry');
8
10
  const redirectAdminUrls = require('./middleware/redirect-admin-urls');
9
11
 
10
12
  module.exports = function setupAdminApp() {
@@ -44,8 +46,8 @@ module.exports = function setupAdminApp() {
44
46
  // Finally, routing
45
47
  adminApp.get('*', require('./controller'));
46
48
 
47
- adminApp.use(shared.middleware.errorHandler.pageNotFound);
48
- adminApp.use(shared.middleware.errorHandler.handleHTMLResponse);
49
+ adminApp.use(errorHandler.pageNotFound);
50
+ adminApp.use(errorHandler.handleHTMLResponse(sentry));
49
51
 
50
52
  debug('Admin setup end');
51
53
 
@@ -8,7 +8,7 @@
8
8
  <title>Ghost Admin</title>
9
9
 
10
10
 
11
- <meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%2F%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%224.29%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22moment%22%3A%7B%22includeTimezone%22%3A%22all%22%7D%2C%22emberKeyboard%22%3A%7B%22disableInputsInitializer%22%3Atrue%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%7D" />
11
+ <meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%2F%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%224.32%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22moment%22%3A%7B%22includeTimezone%22%3A%22all%22%7D%2C%22emberKeyboard%22%3A%7B%22disableInputsInitializer%22%3Atrue%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%7D" />
12
12
 
13
13
  <meta name="HandheldFriendly" content="True" />
14
14
  <meta name="MobileOptimized" content="320" />
@@ -41,7 +41,7 @@
41
41
 
42
42
 
43
43
  <link rel="stylesheet" href="assets/vendor.min-987af30228885bce50f05c4723fe6f53.css">
44
- <link rel="stylesheet" href="assets/ghost.min-578a1b7e68d1f7ae0003ebe421b7c182.css" title="light">
44
+ <link rel="stylesheet" href="assets/ghost.min-c3f7cbabcc1a69476534453c6c747ee3.css" title="light">
45
45
 
46
46
 
47
47
 
@@ -59,8 +59,8 @@
59
59
  <div id="ember-basic-dropdown-wormhole"></div>
60
60
 
61
61
 
62
- <script src="assets/vendor.min-c450359ad46217cd48c00b277ae54a09.js"></script>
63
- <script src="assets/ghost.min-ba8ef5d16b8a6f9072564a368154df72.js"></script>
62
+ <script src="assets/vendor.min-992a9b07f7d0a67b5a4afd91319edf8b.js"></script>
63
+ <script src="assets/ghost.min-2b20489c79323b165909749382adc158.js"></script>
64
64
 
65
65
  </body>
66
66
  </html>
@@ -8,7 +8,7 @@
8
8
  <title>Ghost Admin</title>
9
9
 
10
10
 
11
- <meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%2F%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%224.29%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22moment%22%3A%7B%22includeTimezone%22%3A%22all%22%7D%2C%22emberKeyboard%22%3A%7B%22disableInputsInitializer%22%3Atrue%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%7D" />
11
+ <meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%2F%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%224.32%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22moment%22%3A%7B%22includeTimezone%22%3A%22all%22%7D%2C%22emberKeyboard%22%3A%7B%22disableInputsInitializer%22%3Atrue%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%7D" />
12
12
 
13
13
  <meta name="HandheldFriendly" content="True" />
14
14
  <meta name="MobileOptimized" content="320" />
@@ -41,7 +41,7 @@
41
41
 
42
42
 
43
43
  <link rel="stylesheet" href="assets/vendor.min-987af30228885bce50f05c4723fe6f53.css">
44
- <link rel="stylesheet" href="assets/ghost.min-578a1b7e68d1f7ae0003ebe421b7c182.css" title="light">
44
+ <link rel="stylesheet" href="assets/ghost.min-c3f7cbabcc1a69476534453c6c747ee3.css" title="light">
45
45
 
46
46
 
47
47
 
@@ -59,8 +59,8 @@
59
59
  <div id="ember-basic-dropdown-wormhole"></div>
60
60
 
61
61
 
62
- <script src="assets/vendor.min-c450359ad46217cd48c00b277ae54a09.js"></script>
63
- <script src="assets/ghost.min-ba8ef5d16b8a6f9072564a368154df72.js"></script>
62
+ <script src="assets/vendor.min-992a9b07f7d0a67b5a4afd91319edf8b.js"></script>
63
+ <script src="assets/ghost.min-2b20489c79323b165909749382adc158.js"></script>
64
64
 
65
65
  </body>
66
66
  </html>
@@ -2,7 +2,8 @@ const debug = require('@tryghost/debug')('web:api:default:app');
2
2
  const config = require('../../../shared/config');
3
3
  const express = require('../../../shared/express');
4
4
  const urlUtils = require('../../../shared/url-utils');
5
- const errorHandler = require('../shared/middleware/error-handler');
5
+ const sentry = require('../../../shared/sentry');
6
+ const errorHandler = require('@tryghost/mw-error-handler');
6
7
 
7
8
  module.exports = function setupApiApp() {
8
9
  debug('Parent API setup start');
@@ -26,7 +27,7 @@ module.exports = function setupApiApp() {
26
27
 
27
28
  // Error handling for requests to non-existent API versions
28
29
  apiApp.use(errorHandler.resourceNotFound);
29
- apiApp.use(errorHandler.handleJSONResponse);
30
+ apiApp.use(errorHandler.handleJSONResponse(sentry));
30
31
 
31
32
  debug('Parent API setup end');
32
33
  return apiApp;
@@ -4,6 +4,8 @@ const express = require('../../../../../shared/express');
4
4
  const bodyParser = require('body-parser');
5
5
  const shared = require('../../../shared');
6
6
  const apiMw = require('../../middleware');
7
+ const errorHandler = require('@tryghost/mw-error-handler');
8
+ const sentry = require('../../../../../shared/sentry');
7
9
  const routes = require('./routes');
8
10
 
9
11
  module.exports = function setupApiApp() {
@@ -30,8 +32,8 @@ module.exports = function setupApiApp() {
30
32
  apiApp.use(routes());
31
33
 
32
34
  // API error handling
33
- apiApp.use(shared.middleware.errorHandler.resourceNotFound);
34
- apiApp.use(shared.middleware.errorHandler.handleJSONResponseV2);
35
+ apiApp.use(errorHandler.resourceNotFound);
36
+ apiApp.use(errorHandler.handleJSONResponseV2(sentry));
35
37
 
36
38
  debug('Admin API canary setup end');
37
39
 
@@ -2,8 +2,10 @@ const debug = require('@tryghost/debug')('web:api:canary:content:app');
2
2
  const boolParser = require('express-query-boolean');
3
3
  const bodyParser = require('body-parser');
4
4
  const express = require('../../../../../shared/express');
5
+ const sentry = require('../../../../../shared/sentry');
5
6
  const shared = require('../../../shared');
6
7
  const routes = require('./routes');
8
+ const errorHandler = require('@tryghost/mw-error-handler');
7
9
 
8
10
  module.exports = function setupApiApp() {
9
11
  debug('Content API canary setup start');
@@ -24,8 +26,8 @@ module.exports = function setupApiApp() {
24
26
  apiApp.use(routes());
25
27
 
26
28
  // API error handling
27
- apiApp.use(shared.middleware.errorHandler.resourceNotFound);
28
- apiApp.use(shared.middleware.errorHandler.handleJSONResponse);
29
+ apiApp.use(errorHandler.resourceNotFound);
30
+ apiApp.use(errorHandler.handleJSONResponse(sentry));
29
31
 
30
32
  debug('Content API canary setup end');
31
33
 
@@ -1,10 +1,12 @@
1
1
  const debug = require('@tryghost/debug')('web:v2:admin:app');
2
2
  const boolParser = require('express-query-boolean');
3
3
  const express = require('../../../../../shared/express');
4
+ const sentry = require('../../../../../shared/sentry');
4
5
  const bodyParser = require('body-parser');
5
6
  const shared = require('../../../shared');
6
7
  const apiMw = require('../../middleware');
7
8
  const routes = require('./routes');
9
+ const errorHandler = require('@tryghost/mw-error-handler');
8
10
 
9
11
  module.exports = function setupApiApp() {
10
12
  debug('Admin API v2 setup start');
@@ -30,8 +32,8 @@ module.exports = function setupApiApp() {
30
32
  apiApp.use(routes());
31
33
 
32
34
  // API error handling
33
- apiApp.use(shared.middleware.errorHandler.resourceNotFound);
34
- apiApp.use(shared.middleware.errorHandler.handleJSONResponseV2);
35
+ apiApp.use(errorHandler.resourceNotFound);
36
+ apiApp.use(errorHandler.handleJSONResponseV2(sentry));
35
37
 
36
38
  debug('Admin API v2 setup end');
37
39
 
@@ -2,8 +2,10 @@ const debug = require('@tryghost/debug')('web:api:v2:content:app');
2
2
  const boolParser = require('express-query-boolean');
3
3
  const bodyParser = require('body-parser');
4
4
  const express = require('../../../../../shared/express');
5
+ const sentry = require('../../../../../shared/sentry');
5
6
  const shared = require('../../../shared');
6
7
  const routes = require('./routes');
8
+ const errorHandler = require('@tryghost/mw-error-handler');
7
9
 
8
10
  module.exports = function setupApiApp() {
9
11
  debug('Content API v2 setup start');
@@ -24,8 +26,8 @@ module.exports = function setupApiApp() {
24
26
  apiApp.use(routes());
25
27
 
26
28
  // API error handling
27
- apiApp.use(shared.middleware.errorHandler.resourceNotFound);
28
- apiApp.use(shared.middleware.errorHandler.handleJSONResponse);
29
+ apiApp.use(errorHandler.resourceNotFound);
30
+ apiApp.use(errorHandler.handleJSONResponse(sentry));
29
31
 
30
32
  debug('Content API v2 setup end');
31
33
 
@@ -1,10 +1,12 @@
1
1
  const debug = require('@tryghost/debug')('web:v3:admin:app');
2
2
  const boolParser = require('express-query-boolean');
3
3
  const express = require('../../../../../shared/express');
4
+ const sentry = require('../../../../../shared/sentry');
4
5
  const bodyParser = require('body-parser');
5
6
  const shared = require('../../../shared');
6
7
  const apiMw = require('../../middleware');
7
8
  const routes = require('./routes');
9
+ const errorHandler = require('@tryghost/mw-error-handler');
8
10
 
9
11
  module.exports = function setupApiApp() {
10
12
  debug('Admin API v3 setup start');
@@ -30,8 +32,8 @@ module.exports = function setupApiApp() {
30
32
  apiApp.use(routes());
31
33
 
32
34
  // API error handling
33
- apiApp.use(shared.middleware.errorHandler.resourceNotFound);
34
- apiApp.use(shared.middleware.errorHandler.handleJSONResponseV2);
35
+ apiApp.use(errorHandler.resourceNotFound);
36
+ apiApp.use(errorHandler.handleJSONResponseV2(sentry));
35
37
 
36
38
  debug('Admin API v3 setup end');
37
39
 
@@ -2,8 +2,10 @@ const debug = require('@tryghost/debug')('web:api:v3:content:app');
2
2
  const boolParser = require('express-query-boolean');
3
3
  const bodyParser = require('body-parser');
4
4
  const express = require('../../../../../shared/express');
5
+ const sentry = require('../../../../../shared/sentry');
5
6
  const shared = require('../../../shared');
6
7
  const routes = require('./routes');
8
+ const errorHandler = require('@tryghost/mw-error-handler');
7
9
 
8
10
  module.exports = function setupApiApp() {
9
11
  debug('Content API v3 setup start');
@@ -24,8 +26,8 @@ module.exports = function setupApiApp() {
24
26
  apiApp.use(routes());
25
27
 
26
28
  // API error handling
27
- apiApp.use(shared.middleware.errorHandler.resourceNotFound);
28
- apiApp.use(shared.middleware.errorHandler.handleJSONResponse);
29
+ apiApp.use(errorHandler.resourceNotFound);
30
+ apiApp.use(errorHandler.handleJSONResponse(sentry));
29
31
 
30
32
  debug('Content API v3 setup end');
31
33
 
@@ -4,10 +4,12 @@ const cors = require('cors');
4
4
  const bodyParser = require('body-parser');
5
5
  const express = require('../../../shared/express');
6
6
  const urlUtils = require('../../../shared/url-utils');
7
+ const sentry = require('../../../shared/sentry');
7
8
  const membersService = require('../../services/members');
8
9
  const middleware = membersService.middleware;
9
10
  const shared = require('../shared');
10
11
  const labs = require('../../../shared/labs');
12
+ const errorHandler = require('@tryghost/mw-error-handler');
11
13
 
12
14
  module.exports = function setupMembersApp() {
13
15
  debug('Members App setup start');
@@ -46,12 +48,12 @@ module.exports = function setupMembersApp() {
46
48
  membersApp.post('/api/events', labs.enabledMiddleware('membersActivity'), middleware.loadMemberSession, (req, res, next) => membersService.api.middleware.createEvents(req, res, next));
47
49
 
48
50
  // API error handling
49
- membersApp.use('/api', shared.middleware.errorHandler.resourceNotFound);
50
- membersApp.use('/api', shared.middleware.errorHandler.handleJSONResponseV2);
51
+ membersApp.use('/api', errorHandler.resourceNotFound);
52
+ membersApp.use('/api', errorHandler.handleJSONResponseV2(sentry));
51
53
 
52
54
  // Webhook error handling
53
- membersApp.use('/webhooks', shared.middleware.errorHandler.resourceNotFound);
54
- membersApp.use('/webhooks', shared.middleware.errorHandler.handleJSONResponseV2);
55
+ membersApp.use('/webhooks', errorHandler.resourceNotFound);
56
+ membersApp.use('/webhooks', errorHandler.handleJSONResponseV2(sentry));
55
57
 
56
58
  debug('Members App setup end');
57
59
 
@@ -11,10 +11,6 @@ module.exports = {
11
11
  return require('./cache-control');
12
12
  },
13
13
 
14
- get errorHandler() {
15
- return require('./error-handler');
16
- },
17
-
18
14
  get prettyUrls() {
19
15
  return require('./pretty-urls');
20
16
  },
@@ -32,7 +32,17 @@
32
32
  },
33
33
  "media": {
34
34
  "extensions": [".mp4",".webm", ".ogv", ".mp3", ".wav", ".ogg"],
35
- "contentTypes": ["video/mp4", "video/webm", "video/ogg", "audio/mpeg", "audio/vnd.wav", "audio/ogg"]
35
+ "contentTypes": [
36
+ "video/mp4",
37
+ "video/webm",
38
+ "video/ogg",
39
+ "audio/mpeg",
40
+ "audio/vnd.wav",
41
+ "audio/wave",
42
+ "audio/wav",
43
+ "audio/x-wav",
44
+ "audio/ogg"
45
+ ]
36
46
  },
37
47
  "thumbnails": {
38
48
  "extensions": [".jpg", ".jpeg", ".gif", ".png", ".svg", ".svgz", ".ico", ".webp"],
@@ -18,12 +18,16 @@ const GA_FEATURES = [
18
18
  'customThemeSettings',
19
19
  'nftCard',
20
20
  'calloutCard',
21
+ 'videoCard',
21
22
  'accordionCard',
22
23
  'productCard',
23
24
  'richTwitterNewsletters',
24
25
  'audioCard',
25
26
  'mediaAPI',
26
- 'filesAPI'
27
+ 'membersAutoLogin',
28
+ 'filesAPI',
29
+ 'fileCard',
30
+ 'headerCard'
27
31
  ];
28
32
 
29
33
  // NOTE: this allowlist is meant to be used to filter out any unexpected
@@ -38,12 +42,8 @@ const ALPHA_FEATURES = [
38
42
  'membersActivity',
39
43
  'cardSettingsPanel',
40
44
  'urlCache',
41
- 'membersAutoLogin',
42
- 'fileCard',
43
- 'videoCard',
44
45
  'beforeAfterCard',
45
- 'tweetGridCard',
46
- 'headerCard'
46
+ 'tweetGridCard'
47
47
  ];
48
48
 
49
49
  module.exports.GA_KEYS = [...GA_FEATURES];