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.
Files changed (230) hide show
  1. package/.c8rc.json +24 -0
  2. package/.eslintrc.js +39 -0
  3. package/Gruntfile.js +0 -1
  4. package/content/public/README.md +3 -0
  5. package/content/themes/casper/assets/built/casper.js +1 -1
  6. package/content/themes/casper/assets/built/casper.js.map +1 -1
  7. package/content/themes/casper/assets/built/global.css +1 -1
  8. package/content/themes/casper/assets/built/global.css.map +1 -1
  9. package/content/themes/casper/assets/built/screen.css +1 -1
  10. package/content/themes/casper/assets/built/screen.css.map +1 -1
  11. package/content/themes/casper/assets/css/global.css +6 -1
  12. package/content/themes/casper/assets/css/screen.css +32 -216
  13. package/content/themes/casper/default.hbs +2 -2
  14. package/content/themes/casper/package.json +3 -2
  15. package/content/themes/casper/post.hbs +1 -1
  16. package/content/themes/casper/yarn.lock +173 -123
  17. package/core/app.js +12 -1
  18. package/core/boot.js +47 -28
  19. package/core/bridge.js +10 -10
  20. package/core/built/assets/{chunk.3.324fd0cc598c73650219.js → chunk.3.8f95b516d88ff4eec64c.js} +18 -18
  21. package/core/built/assets/ghost-dark-d690e732e17ffc794e2e59c1467ca282.css +1 -0
  22. package/core/built/assets/ghost.min-043bb7480a0810109b130f13b2a4235e.css +1 -0
  23. package/core/built/assets/{ghost.min-7da921f6c6cac3fe10da1ba104575440.js → ghost.min-bc72f685c1c9adc9885925c1412435a5.js} +563 -605
  24. package/core/built/assets/icons/audio-upload.svg +8 -0
  25. package/core/built/assets/icons/powered-by-tenor.svg +35 -0
  26. package/core/built/assets/icons/tenor.svg +7 -0
  27. package/core/built/assets/{vendor.min-413f887176a041e6dbf88214ca9a7481.js → vendor.min-d1234c632a54502777c34e50752fa3fc.js} +4622 -3631
  28. package/core/frontend/apps/amp/lib/helpers/amp_content.js +2 -2
  29. package/core/frontend/apps/amp/lib/views/amp.hbs +112 -0
  30. package/core/frontend/apps/private-blogging/index.js +1 -1
  31. package/core/frontend/apps/private-blogging/lib/router.js +1 -1
  32. package/core/frontend/services/apps/index.js +1 -1
  33. package/core/frontend/services/apps/loader.js +3 -3
  34. package/core/frontend/services/card-assets/index.js +0 -12
  35. package/core/frontend/services/card-assets/service.js +29 -28
  36. package/core/frontend/services/helpers/handlebars.js +1 -1
  37. package/core/frontend/services/routing/CollectionRouter.js +4 -5
  38. package/core/frontend/services/routing/EmailRouter.js +1 -1
  39. package/core/frontend/services/routing/ParentRouter.js +0 -8
  40. package/core/frontend/services/routing/PreviewRouter.js +1 -1
  41. package/core/frontend/services/routing/StaticPagesRouter.js +1 -1
  42. package/core/frontend/services/routing/StaticRoutesRouter.js +4 -4
  43. package/core/frontend/services/routing/TaxonomyRouter.js +3 -3
  44. package/core/frontend/services/routing/{middlewares → middleware}/index.js +0 -0
  45. package/core/frontend/services/routing/{middlewares → middleware}/page-param.js +0 -0
  46. package/core/frontend/services/routing/router-manager.js +7 -2
  47. package/core/frontend/services/rss/generate-feed.js +2 -1
  48. package/core/frontend/services/theme-engine/middleware/ensure-active-theme.js +34 -0
  49. package/core/frontend/services/theme-engine/middleware/index.js +6 -0
  50. package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +116 -0
  51. package/core/frontend/services/theme-engine/middleware/update-local-template-data.js +9 -0
  52. package/core/frontend/services/theme-engine/middleware/update-local-template-options.js +57 -0
  53. package/core/frontend/src/cards/css/bookmark.css +72 -47
  54. package/core/frontend/src/cards/css/button.css +4 -0
  55. package/core/frontend/src/cards/css/callout.css +40 -3
  56. package/core/frontend/src/cards/css/gallery.css +15 -10
  57. package/core/frontend/src/cards/css/nft.css +20 -11
  58. package/core/frontend/src/cards/css/toggle.css +58 -0
  59. package/core/frontend/src/cards/js/toggle.js +16 -0
  60. package/core/frontend/web/middleware/error-handler.js +93 -0
  61. package/core/frontend/web/middleware/handle-image-sizes.js +3 -6
  62. package/core/frontend/web/middleware/index.js +1 -0
  63. package/core/frontend/web/middleware/serve-public-file.js +39 -16
  64. package/core/frontend/web/site.js +11 -14
  65. package/core/server/adapters/scheduling/SchedulingDefault.js +2 -2
  66. package/core/server/adapters/storage/LocalStorageBase.js +2 -2
  67. package/core/server/api/canary/authentication.js +1 -1
  68. package/core/server/api/canary/db.js +2 -2
  69. package/core/server/api/canary/media.js +3 -2
  70. package/core/server/api/canary/oembed.js +16 -1
  71. package/core/server/api/canary/session.js +1 -1
  72. package/core/server/api/canary/slugs.js +1 -1
  73. package/core/server/api/canary/utils/permissions.js +2 -2
  74. package/core/server/api/canary/utils/serializers/output/config.js +2 -6
  75. package/core/server/api/v2/authentication.js +1 -1
  76. package/core/server/api/v2/db.js +2 -2
  77. package/core/server/api/v2/session.js +1 -1
  78. package/core/server/api/v2/slugs.js +1 -1
  79. package/core/server/api/v2/utils/permissions.js +2 -2
  80. package/core/server/api/v3/authentication.js +1 -1
  81. package/core/server/api/v3/db.js +2 -2
  82. package/core/server/api/v3/session.js +1 -1
  83. package/core/server/api/v3/slugs.js +1 -1
  84. package/core/server/api/v3/utils/permissions.js +2 -2
  85. package/core/server/data/db/connection.js +7 -0
  86. package/core/server/data/db/state-manager.js +4 -4
  87. package/core/server/data/exporter/export-filename.js +1 -1
  88. package/core/server/data/importer/handlers/json.js +1 -1
  89. package/core/server/data/importer/import-manager.js +1 -1
  90. package/core/server/data/importer/importers/data/base.js +1 -1
  91. package/core/server/data/importer/importers/data/data-importer.js +3 -3
  92. package/core/server/data/migrations/init/2-create-fixtures.js +3 -20
  93. package/core/server/data/migrations/utils.js +2 -2
  94. package/core/server/data/migrations/versions/1.21/1-add-contributor-role.js +5 -5
  95. package/core/server/data/migrations/versions/1.25/1-update-koenig-beta-html.js +1 -0
  96. package/core/server/data/migrations/versions/2.15/2-insert-zapier-integration.js +3 -3
  97. package/core/server/data/migrations/versions/2.2/3-insert-admin-integration-role.js +5 -5
  98. package/core/server/data/migrations/versions/2.27/1-insert-ghost-db-backup-role.js +5 -6
  99. package/core/server/data/migrations/versions/2.27/2-insert-db-backup-integration.js +3 -4
  100. package/core/server/data/migrations/versions/2.28/3-insert-ghost-scheduler-role.js +7 -7
  101. package/core/server/data/migrations/versions/2.28/4-insert-scheduler-integration.js +3 -3
  102. package/core/server/data/migrations/versions/3.1/08-add-uuid-values-to-members.js +1 -0
  103. package/core/server/data/migrations/versions/3.22/02-settings-key-renames.js +2 -0
  104. package/core/server/data/migrations/versions/3.22/05-migrate-members-subscription-settings.js +3 -0
  105. package/core/server/data/migrations/versions/3.22/06-migrate-stripe-connect-settings.js +2 -0
  106. package/core/server/data/migrations/versions/3.23/01-migrate-bulk-email-settings.js +1 -0
  107. package/core/server/data/migrations/versions/3.29/01-remove-duplicate-subscriptions.js +2 -0
  108. package/core/server/data/migrations/versions/3.29/02-remove-duplicate-customers.js +2 -0
  109. package/core/server/data/migrations/versions/3.38/04-populate-recipient-filter-column.js +2 -0
  110. package/core/server/data/migrations/versions/4.0/01-update-mobiledoc.js +2 -0
  111. package/core/server/data/migrations/versions/4.0/03-populate-status-column-for-members.js +4 -0
  112. package/core/server/data/migrations/versions/4.0/06-populate-members-subscribe-events-table.js +1 -0
  113. package/core/server/data/migrations/versions/4.0/17-populate-members-status-events-table.js +1 -0
  114. package/core/server/data/migrations/versions/4.0/18-transform-urls-absolute-to-transform-ready.js +5 -0
  115. package/core/server/data/migrations/versions/4.0/22-solve-orphaned-webhooks.js +1 -0
  116. package/core/server/data/migrations/versions/4.0/23-regenerate-posts-html.js +1 -0
  117. package/core/server/data/migrations/versions/4.0/25-populate-members-paid-subscription-events-table.js +2 -1
  118. package/core/server/data/migrations/versions/4.12/02-fix-member-statuses.js +1 -0
  119. package/core/server/data/migrations/versions/4.14/01-fix-comped-member-statuses.js +3 -0
  120. package/core/server/data/migrations/versions/4.14/02-fix-free-members-status-events.js +1 -0
  121. package/core/server/data/migrations/versions/4.20/05-remove-not-null-constraint-from-portal-title.js +2 -0
  122. package/core/server/data/migrations/versions/4.23/01-truncate-offer-names.js +59 -0
  123. package/core/server/data/migrations/versions/4.3/04-attach-members-to-product.js +1 -0
  124. package/core/server/data/migrations/versions/4.4/01-restore-free-members-signup-setting-from-backup.js +1 -0
  125. package/core/server/data/migrations/versions/4.6/01-remove-comped-status.js +1 -0
  126. package/core/server/data/migrations/versions/4.8/04-migrate-show-newsletter-header-setting.js +1 -0
  127. package/core/server/data/migrations/versions/4.9/05-fix-missed-mobiledoc-url-transforms.js +1 -0
  128. package/core/server/data/migrations/versions/4.9/06-add-comped-status.js +1 -0
  129. package/core/server/data/migrations/versions/4.9/07-update-comped-members-status-events.js +1 -0
  130. package/core/server/data/schema/commands.js +2 -2
  131. package/core/server/data/schema/fixtures/fixture-manager.js +340 -0
  132. package/core/server/data/schema/fixtures/index.js +8 -2
  133. package/core/server/ghost-server.js +2 -2
  134. package/core/server/lib/image/image-size.js +2 -2
  135. package/core/server/models/base/listeners.js +2 -2
  136. package/core/server/models/member-email-change-event.js +2 -2
  137. package/core/server/models/member-login-event.js +2 -2
  138. package/core/server/models/member-paid-subscription-event.js +3 -3
  139. package/core/server/models/member-payment-event.js +3 -3
  140. package/core/server/models/member-product-event.js +6 -6
  141. package/core/server/models/member-status-event.js +5 -3
  142. package/core/server/models/member-subscribe-event.js +9 -3
  143. package/core/server/models/relations/authors.js +1 -1
  144. package/core/server/models/settings.js +1 -1
  145. package/core/server/services/auth/passwordreset.js +1 -1
  146. package/core/server/services/auth/setup.js +1 -1
  147. package/core/server/services/email-analytics/jobs/index.js +1 -1
  148. package/core/server/services/mega/mega.js +6 -4
  149. package/core/server/services/mega/post-email-serializer.js +5 -1
  150. package/core/server/services/mega/segment-parser.js +1 -2
  151. package/core/server/services/mega/template.js +52 -37
  152. package/core/server/services/members/api.js +22 -0
  153. package/core/server/services/members/config.js +1 -1
  154. package/core/server/services/members/emails/signup-paid.js +168 -0
  155. package/core/server/services/members/service.js +6 -2
  156. package/core/server/services/members/stripe-connect.js +4 -2
  157. package/core/server/services/nft-oembed.js +13 -22
  158. package/core/server/services/oembed.js +28 -24
  159. package/core/server/services/permissions/can-this.js +1 -1
  160. package/core/server/services/public-config/config.js +1 -1
  161. package/core/server/services/redirects/api.js +20 -25
  162. package/core/server/services/redirects/index.js +18 -10
  163. package/core/server/services/redirects/utils.js +14 -0
  164. package/core/server/services/redirects/validation.js +10 -0
  165. package/core/server/services/route-settings/default-settings-manager.js +1 -1
  166. package/core/server/services/route-settings/index.js +40 -17
  167. package/core/server/services/route-settings/route-settings.js +120 -115
  168. package/core/server/services/route-settings/settings-loader.js +18 -36
  169. package/core/server/services/route-settings/yaml-parser.js +1 -1
  170. package/core/server/services/slack.js +1 -1
  171. package/core/server/services/themes/activation-bridge.js +3 -3
  172. package/core/server/services/themes/storage.js +2 -2
  173. package/core/server/services/twitter-embed.js +80 -0
  174. package/core/server/services/url/LocalFileCache.js +75 -0
  175. package/core/server/services/url/Resources.js +8 -2
  176. package/core/server/services/url/UrlGenerator.js +23 -20
  177. package/core/server/services/url/UrlService.js +75 -63
  178. package/core/server/services/url/index.js +17 -3
  179. package/core/server/services/xmlrpc.js +2 -2
  180. package/core/server/web/admin/app.js +7 -10
  181. package/core/server/web/admin/controller.js +35 -12
  182. package/core/server/web/admin/middleware/redirect-admin-urls.js +15 -0
  183. package/core/server/web/admin/views/default-prod.html +4 -4
  184. package/core/server/web/admin/views/default.html +4 -4
  185. package/core/server/web/api/app.js +1 -1
  186. package/core/server/web/api/canary/admin/app.js +3 -6
  187. package/core/server/web/api/canary/admin/middleware.js +7 -7
  188. package/core/server/web/api/canary/admin/routes.js +5 -5
  189. package/core/server/web/api/canary/content/app.js +3 -6
  190. package/core/server/web/api/canary/content/middleware.js +3 -3
  191. package/core/server/web/api/v2/admin/app.js +3 -6
  192. package/core/server/web/api/v2/admin/middleware.js +7 -7
  193. package/core/server/web/api/v2/admin/routes.js +5 -5
  194. package/core/server/web/api/v2/content/app.js +3 -6
  195. package/core/server/web/api/v2/content/middleware.js +3 -3
  196. package/core/server/web/api/v3/admin/app.js +3 -6
  197. package/core/server/web/api/v3/admin/middleware.js +7 -7
  198. package/core/server/web/api/v3/admin/routes.js +5 -5
  199. package/core/server/web/api/v3/content/app.js +3 -6
  200. package/core/server/web/api/v3/content/middleware.js +3 -3
  201. package/core/server/web/members/app.js +6 -9
  202. package/core/server/web/oauth/app.js +0 -4
  203. package/core/server/web/parent/app.js +17 -9
  204. package/core/server/web/parent/frontend.js +1 -1
  205. package/core/server/web/shared/index.js +2 -2
  206. package/core/server/web/shared/{middlewares → middleware}/api/index.js +0 -0
  207. package/core/server/web/shared/{middlewares → middleware}/api/spam-prevention.js +0 -0
  208. package/core/server/web/shared/{middlewares → middleware}/brute.js +0 -0
  209. package/core/server/web/shared/{middlewares → middleware}/cache-control.js +0 -0
  210. package/core/server/web/shared/middleware/error-handler.js +224 -0
  211. package/core/server/web/shared/{middlewares → middleware}/index.js +0 -4
  212. package/core/server/web/shared/{middlewares → middleware}/pretty-urls.js +0 -0
  213. package/core/server/web/shared/{middlewares → middleware}/uncapitalise.js +0 -0
  214. package/core/server/web/shared/{middlewares → middleware}/url-redirects.js +0 -0
  215. package/core/shared/config/defaults.json +13 -1
  216. package/core/shared/config/helpers.js +42 -0
  217. package/core/shared/config/loader.js +1 -1
  218. package/core/shared/labs.js +9 -5
  219. package/core/shared/sentry.js +1 -1
  220. package/loggingrc.js +19 -20
  221. package/package.json +38 -37
  222. package/yarn.lock +1064 -892
  223. package/content/themes/casper/assets/js/gallery-card.js +0 -24
  224. package/core/built/assets/ghost-dark-39fb496d051565531062d7e047d1c0b1.css +0 -1
  225. package/core/built/assets/ghost.min-4207edfc1ae0a3f9f6505ca00d20b0c0.css +0 -1
  226. package/core/frontend/services/theme-engine/middleware.js +0 -209
  227. package/core/server/data/schema/fixtures/utils.js +0 -321
  228. package/core/server/web/parent/vhost-utils.js +0 -39
  229. package/core/server/web/shared/middlewares/error-handler.js +0 -329
  230. 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
- 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}) {
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
- // ADMIN + API
31
- const backendApp = require('./backend')();
32
- parentApp.use(vhost(vhostUtils.getBackendHostArg(), backendApp));
33
-
34
- // SITE + MEMBERS
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.middlewares.urlRedirects.frontendSSLRedirect);
19
+ frontendApp.use(shared.middleware.urlRedirects.frontendSSLRedirect);
20
20
 
21
21
  frontendApp.lazyUse('/members', require('../members'));
22
22
  frontendApp.use('/', require('../../../frontend/web')(options));
@@ -1,5 +1,5 @@
1
1
  module.exports = {
2
- get middlewares() {
3
- return require('./middlewares');
2
+ get middleware() {
3
+ return require('./middleware');
4
4
  }
5
5
  };
@@ -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
+ ];
@@ -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
  },
@@ -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
  };
@@ -41,8 +41,8 @@ function loadNconf(options) {
41
41
  // ## Config Methods
42
42
 
43
43
  // Expose dynamic utility methods
44
- helpers.bindAll(nconf);
45
44
  urlHelpers.bindAll(nconf);
45
+ helpers.bindAll(nconf);
46
46
 
47
47
  // ## Sanitization
48
48
 
@@ -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
- 'gifsCard'
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.match(/^testing/))) {
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');
@@ -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/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
- module.exports = {
5
- name: config.get('logging:name'),
6
- env: config.get('env'),
7
- path: config.get('logging:path') || config.getContentPath('logs'),
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
- mode: config.get('logging:mode'),
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;