ghost 4.24.0 → 4.26.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 (147) 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 +50 -215
  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 +8 -4
  15. package/core/boot.js +52 -25
  16. package/core/built/assets/ghost-dark-ef86e3bc7f0fb83d39d3d6a49bff8dd5.css +1 -0
  17. package/core/built/assets/ghost.min-57c1e677f42d596942d317ce93e8a62c.css +1 -0
  18. package/core/built/assets/{ghost.min-d5595f9c71ebc534ccf9ac78483d357c.js → ghost.min-f3c6886e191d34450e9ffca0c8fa056e.js} +504 -579
  19. package/core/built/assets/icons/audio-upload.svg +8 -0
  20. package/core/built/assets/{vendor.min-1a84ac3ef74edf31c6e86810b45221cc.js → vendor.min-b6b8d2a31d61830c2d8f65c5ba54236a.js} +2614 -2149
  21. package/core/frontend/apps/amp/lib/helpers/amp_content.js +2 -2
  22. package/core/frontend/apps/amp/lib/views/amp.hbs +75 -0
  23. package/core/frontend/apps/private-blogging/index.js +1 -1
  24. package/core/frontend/helpers/url.js +18 -1
  25. package/core/frontend/services/apps/index.js +1 -1
  26. package/core/frontend/services/apps/loader.js +3 -3
  27. package/core/frontend/services/helpers/handlebars.js +1 -1
  28. package/core/frontend/services/theme-engine/middleware/ensure-active-theme.js +34 -0
  29. package/core/frontend/services/theme-engine/middleware/index.js +6 -0
  30. package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +116 -0
  31. package/core/frontend/services/theme-engine/middleware/update-local-template-data.js +9 -0
  32. package/core/frontend/services/theme-engine/middleware/update-local-template-options.js +57 -0
  33. package/core/frontend/src/cards/css/audio.css +186 -0
  34. package/core/frontend/src/cards/css/blockquote.css +27 -0
  35. package/core/frontend/src/cards/css/button.css +4 -0
  36. package/core/frontend/src/cards/css/callout.css +23 -14
  37. package/core/frontend/src/cards/css/toggle.css +42 -20
  38. package/core/frontend/src/cards/js/audio.js +137 -0
  39. package/core/frontend/web/middleware/error-handler.js +93 -0
  40. package/core/frontend/web/middleware/handle-image-sizes.js +3 -6
  41. package/core/frontend/web/middleware/index.js +1 -0
  42. package/core/frontend/web/site.js +2 -2
  43. package/core/server/adapters/scheduling/SchedulingDefault.js +2 -2
  44. package/core/server/adapters/storage/LocalStorageBase.js +2 -2
  45. package/core/server/api/canary/db.js +2 -2
  46. package/core/server/api/canary/media.js +3 -2
  47. package/core/server/api/canary/oembed.js +16 -1
  48. package/core/server/api/canary/session.js +1 -1
  49. package/core/server/api/canary/slugs.js +1 -1
  50. package/core/server/api/canary/utils/permissions.js +2 -2
  51. package/core/server/api/canary/utils/serializers/output/config.js +2 -6
  52. package/core/server/api/v2/db.js +2 -2
  53. package/core/server/api/v2/session.js +1 -1
  54. package/core/server/api/v2/slugs.js +1 -1
  55. package/core/server/api/v2/utils/permissions.js +2 -2
  56. package/core/server/api/v3/db.js +2 -2
  57. package/core/server/api/v3/session.js +1 -1
  58. package/core/server/api/v3/slugs.js +1 -1
  59. package/core/server/api/v3/utils/permissions.js +2 -2
  60. package/core/server/data/db/state-manager.js +4 -4
  61. package/core/server/data/exporter/export-filename.js +1 -1
  62. package/core/server/data/importer/handlers/json.js +1 -1
  63. package/core/server/data/importer/import-manager.js +1 -1
  64. package/core/server/data/importer/importers/data/base.js +1 -1
  65. package/core/server/data/migrations/utils.js +2 -2
  66. package/core/server/data/migrations/versions/1.25/1-update-koenig-beta-html.js +1 -0
  67. package/core/server/data/migrations/versions/3.1/08-add-uuid-values-to-members.js +1 -0
  68. package/core/server/data/migrations/versions/3.22/02-settings-key-renames.js +2 -0
  69. package/core/server/data/migrations/versions/3.22/05-migrate-members-subscription-settings.js +3 -0
  70. package/core/server/data/migrations/versions/3.22/06-migrate-stripe-connect-settings.js +2 -0
  71. package/core/server/data/migrations/versions/3.23/01-migrate-bulk-email-settings.js +1 -0
  72. package/core/server/data/migrations/versions/3.29/01-remove-duplicate-subscriptions.js +2 -0
  73. package/core/server/data/migrations/versions/3.29/02-remove-duplicate-customers.js +2 -0
  74. package/core/server/data/migrations/versions/3.38/04-populate-recipient-filter-column.js +2 -0
  75. package/core/server/data/migrations/versions/4.0/01-update-mobiledoc.js +2 -0
  76. package/core/server/data/migrations/versions/4.0/03-populate-status-column-for-members.js +4 -0
  77. package/core/server/data/migrations/versions/4.0/06-populate-members-subscribe-events-table.js +1 -0
  78. package/core/server/data/migrations/versions/4.0/17-populate-members-status-events-table.js +1 -0
  79. package/core/server/data/migrations/versions/4.0/18-transform-urls-absolute-to-transform-ready.js +5 -0
  80. package/core/server/data/migrations/versions/4.0/22-solve-orphaned-webhooks.js +1 -0
  81. package/core/server/data/migrations/versions/4.0/23-regenerate-posts-html.js +1 -0
  82. package/core/server/data/migrations/versions/4.0/25-populate-members-paid-subscription-events-table.js +2 -1
  83. package/core/server/data/migrations/versions/4.12/02-fix-member-statuses.js +1 -0
  84. package/core/server/data/migrations/versions/4.14/01-fix-comped-member-statuses.js +3 -0
  85. package/core/server/data/migrations/versions/4.14/02-fix-free-members-status-events.js +1 -0
  86. package/core/server/data/migrations/versions/4.20/05-remove-not-null-constraint-from-portal-title.js +2 -0
  87. package/core/server/data/migrations/versions/4.23/01-truncate-offer-names.js +1 -0
  88. package/core/server/data/migrations/versions/4.3/04-attach-members-to-product.js +1 -0
  89. package/core/server/data/migrations/versions/4.4/01-restore-free-members-signup-setting-from-backup.js +1 -0
  90. package/core/server/data/migrations/versions/4.6/01-remove-comped-status.js +1 -0
  91. package/core/server/data/migrations/versions/4.8/04-migrate-show-newsletter-header-setting.js +1 -0
  92. package/core/server/data/migrations/versions/4.9/05-fix-missed-mobiledoc-url-transforms.js +1 -0
  93. package/core/server/data/migrations/versions/4.9/06-add-comped-status.js +1 -0
  94. package/core/server/data/migrations/versions/4.9/07-update-comped-members-status-events.js +1 -0
  95. package/core/server/data/schema/commands.js +2 -2
  96. package/core/server/ghost-server.js +2 -2
  97. package/core/server/lib/image/image-size.js +2 -2
  98. package/core/server/models/base/listeners.js +2 -2
  99. package/core/server/models/member-email-change-event.js +2 -2
  100. package/core/server/models/member-login-event.js +2 -2
  101. package/core/server/models/member-paid-subscription-event.js +3 -3
  102. package/core/server/models/member-payment-event.js +3 -3
  103. package/core/server/models/member-product-event.js +6 -6
  104. package/core/server/models/member-status-event.js +5 -3
  105. package/core/server/models/member-subscribe-event.js +9 -3
  106. package/core/server/models/relations/authors.js +1 -1
  107. package/core/server/models/settings.js +1 -1
  108. package/core/server/notify.js +1 -2
  109. package/core/server/services/auth/passwordreset.js +1 -1
  110. package/core/server/services/auth/setup.js +1 -1
  111. package/core/server/services/mega/mega.js +6 -4
  112. package/core/server/services/mega/template.js +43 -17
  113. package/core/server/services/members/api.js +22 -0
  114. package/core/server/services/members/config.js +1 -1
  115. package/core/server/services/members/emails/signup-paid.js +168 -0
  116. package/core/server/services/members/service.js +6 -2
  117. package/core/server/services/members/stripe-connect.js +4 -2
  118. package/core/server/services/nft-oembed.js +7 -2
  119. package/core/server/services/oembed.js +15 -3
  120. package/core/server/services/permissions/can-this.js +1 -1
  121. package/core/server/services/redirects/api.js +2 -2
  122. package/core/server/services/route-settings/default-settings-manager.js +1 -1
  123. package/core/server/services/route-settings/route-settings.js +4 -12
  124. package/core/server/services/route-settings/settings-loader.js +4 -4
  125. package/core/server/services/route-settings/yaml-parser.js +1 -1
  126. package/core/server/services/slack.js +1 -1
  127. package/core/server/services/themes/storage.js +2 -2
  128. package/core/server/services/twitter-embed.js +81 -0
  129. package/core/server/services/xmlrpc.js +2 -2
  130. package/core/server/web/admin/views/default-prod.html +4 -4
  131. package/core/server/web/admin/views/default.html +4 -4
  132. package/core/server/web/api/canary/admin/middleware.js +1 -1
  133. package/core/server/web/api/v2/admin/middleware.js +1 -1
  134. package/core/server/web/api/v3/admin/middleware.js +1 -1
  135. package/core/server/web/parent/app.js +2 -22
  136. package/core/server/web/parent/backend.js +2 -0
  137. package/core/server/web/shared/middleware/error-handler.js +28 -150
  138. package/core/shared/config/defaults.json +7 -1
  139. package/core/shared/express.js +1 -1
  140. package/core/shared/labs.js +7 -7
  141. package/core/shared/sentry.js +1 -1
  142. package/package.json +38 -38
  143. package/yarn.lock +632 -941
  144. package/content/themes/casper/assets/js/gallery-card.js +0 -24
  145. package/core/built/assets/ghost-dark-e7b57ab951512c5719aee89b16b9a448.css +0 -1
  146. package/core/built/assets/ghost.min-7f3603dbeb5ebf0ec09e207ae82fb4e3.css +0 -1
  147. package/core/frontend/services/theme-engine/middleware.js +0 -209
@@ -1,6 +1,7 @@
1
1
  const errors = require('@tryghost/errors');
2
2
  const tpl = require('@tryghost/tpl');
3
3
  const logging = require('@tryghost/logging');
4
+ const sentry = require('../../shared/sentry');
4
5
  const {extract, hasProvider} = require('oembed-parser');
5
6
  const cheerio = require('cheerio');
6
7
  const _ = require('lodash');
@@ -128,7 +129,14 @@ class OEmbed {
128
129
  const response = await this.externalRequest(url, {cookieJar});
129
130
 
130
131
  const html = response.body;
131
- scraperResponse = await metascraper({html, url});
132
+ try {
133
+ scraperResponse = await metascraper({html, url});
134
+ } catch (err) {
135
+ // Log to avoid being blind to errors happenning in metascraper
136
+ sentry.captureException(err);
137
+ logging.error(err);
138
+ return this.unknownProvider(url);
139
+ }
132
140
 
133
141
  const metadata = Object.assign({}, scraperResponse, {
134
142
  thumbnail: scraperResponse.image,
@@ -284,6 +292,10 @@ class OEmbed {
284
292
  try {
285
293
  const urlObject = new URL(url);
286
294
 
295
+ // Trimming solves the difference of url validation between `new URL(url)`
296
+ // and metascraper.
297
+ url = url.trim();
298
+
287
299
  for (const provider of this.customProviders) {
288
300
  if (await provider.canSupportRequest(urlObject)) {
289
301
  const result = await provider.getOEmbedData(urlObject, this.externalRequest);
@@ -314,12 +326,12 @@ class OEmbed {
314
326
  return data;
315
327
  } catch (err) {
316
328
  // allow specific validation errors through for better error messages
317
- if (errors.utils.isIgnitionError(err) && err.errorType === 'ValidationError') {
329
+ if (errors.utils.isGhostError(err) && err.errorType === 'ValidationError') {
318
330
  throw err;
319
331
  }
320
332
 
321
333
  // log the real error because we're going to throw a generic "Unknown provider" error
322
- logging.error(new errors.GhostError({
334
+ logging.error(new errors.InternalServerError({
323
335
  message: 'Encountered error when fetching oembed',
324
336
  err
325
337
  }));
@@ -128,7 +128,7 @@ CanThisResult.prototype.beginCheck = function (context) {
128
128
  context = parseContext(context);
129
129
 
130
130
  if (actionsMap.empty()) {
131
- throw new errors.GhostError({message: tpl(messages.noActionsMapFoundError)});
131
+ throw new errors.InternalServerError({message: tpl(messages.noActionsMapFoundError)});
132
132
  }
133
133
 
134
134
  // Kick off loading of user permissions if necessary
@@ -34,7 +34,7 @@ const readRedirectsFile = async (redirectsPath) => {
34
34
  return '';
35
35
  }
36
36
 
37
- if (errors.utils.isIgnitionError(err)) {
37
+ if (errors.utils.isGhostError(err)) {
38
38
  throw err;
39
39
  }
40
40
 
@@ -162,7 +162,7 @@ class CustomRedirectsAPI {
162
162
  }
163
163
  }
164
164
  } catch (err) {
165
- if (errors.utils.isIgnitionError(err)) {
165
+ if (errors.utils.isGhostError(err)) {
166
166
  logging.error(err);
167
167
  } else {
168
168
  logging.error(new errors.IncorrectUsageError({
@@ -48,7 +48,7 @@ class DefaultSettingsManager {
48
48
  });
49
49
  }).catch((error) => {
50
50
  // CASE: we might have a permission error, as we can't access the directory
51
- throw new errors.GhostError({
51
+ throw new errors.InternalServerError({
52
52
  message: tpl(messages.ensureSettings, {
53
53
  path: this.destinationFolderPath
54
54
  }),
@@ -9,7 +9,7 @@ const tpl = require('@tryghost/tpl');
9
9
  const bridge = require('../../../bridge');
10
10
 
11
11
  const messages = {
12
- loadError: 'Could not load {filename} file.'
12
+ loadError: 'Could not load routes.yaml file.'
13
13
  };
14
14
 
15
15
  /**
@@ -38,14 +38,6 @@ class RouteSettings {
38
38
  * @private
39
39
  */
40
40
  this.defaultRoutesSettingHash = '3d180d52c663d173a6be791ef411ed01';
41
- /**
42
- * @private
43
- */
44
- this.filename = 'routes';
45
- /**
46
- * @private
47
- */
48
- this.ext = 'yaml';
49
41
 
50
42
  this.settingsLoader = settingsLoader;
51
43
  this.settingsPath = settingsPath;
@@ -90,7 +82,7 @@ class RouteSettings {
90
82
  return Promise.resolve([]);
91
83
  }
92
84
 
93
- if (errors.utils.isIgnitionError(err)) {
85
+ if (errors.utils.isGhostError(err)) {
94
86
  throw err;
95
87
  }
96
88
 
@@ -115,7 +107,7 @@ class RouteSettings {
115
107
  };
116
108
 
117
109
  try {
118
- bridge.reloadFrontend();
110
+ await bridge.reloadFrontend();
119
111
  } catch (err) {
120
112
  return bringBackValidRoutes()
121
113
  .finally(() => {
@@ -134,7 +126,7 @@ class RouteSettings {
134
126
  if (!urlService.hasFinished()) {
135
127
  if (tries > 5) {
136
128
  throw new errors.InternalServerError({
137
- message: tpl(messages.loadError, {filename: `${this.filename}.${this.ext}`})
129
+ message: tpl(messages.loadError)
138
130
  });
139
131
  }
140
132
 
@@ -36,11 +36,11 @@ class SettingsLoader {
36
36
 
37
37
  return validate(object);
38
38
  } catch (err) {
39
- if (errors.utils.isIgnitionError(err)) {
39
+ if (errors.utils.isGhostError(err)) {
40
40
  throw err;
41
41
  }
42
42
 
43
- throw new errors.GhostError({
43
+ throw new errors.InternalServerError({
44
44
  message: tpl(messages.settingsLoaderError, {
45
45
  setting: 'routes',
46
46
  path: this.settingFilePath
@@ -66,11 +66,11 @@ class SettingsLoader {
66
66
 
67
67
  return validate(object);
68
68
  } catch (err) {
69
- if (errors.utils.isIgnitionError(err)) {
69
+ if (errors.utils.isGhostError(err)) {
70
70
  throw err;
71
71
  }
72
72
 
73
- throw new errors.GhostError({
73
+ throw new errors.InternalServerError({
74
74
  message: tpl(messages.settingsLoaderError, {
75
75
  setting: 'routes',
76
76
  path: this.settingFilePath
@@ -35,7 +35,7 @@ module.exports = function parseYaml(file) {
35
35
 
36
36
  return parsed;
37
37
  } catch (error) {
38
- if (errors.utils.isIgnitionError(error)) {
38
+ if (errors.utils.isGhostError(error)) {
39
39
  throw error;
40
40
  }
41
41
 
@@ -136,7 +136,7 @@ function ping(post) {
136
136
  'Content-type': 'application/json'
137
137
  }
138
138
  }).catch(function (err) {
139
- logging.error(new errors.GhostError({
139
+ logging.error(new errors.InternalServerError({
140
140
  err: err,
141
141
  context: tpl(messages.requestFailedError, {service: 'slack'}),
142
142
  help: tpl(messages.requestFailedHelp, {url: 'https://ghost.org/docs/'})
@@ -112,7 +112,7 @@ module.exports = {
112
112
  if (checkedTheme) {
113
113
  fs.remove(checkedTheme.path)
114
114
  .catch((err) => {
115
- logging.error(new errors.GhostError({err: err}));
115
+ logging.error(new errors.InternalServerError({err: err}));
116
116
  });
117
117
  }
118
118
 
@@ -120,7 +120,7 @@ module.exports = {
120
120
  getStorage()
121
121
  .delete(backupName)
122
122
  .catch((err) => {
123
- logging.error(new errors.GhostError({err: err}));
123
+ logging.error(new errors.InternalServerError({err: err}));
124
124
  });
125
125
  }
126
126
  },
@@ -0,0 +1,81 @@
1
+ const {extract} = require('oembed-parser');
2
+
3
+ /**
4
+ * @typedef {import('./oembed').ICustomProvider} ICustomProvider
5
+ * @typedef {import('./oembed').IExternalRequest} IExternalRequest
6
+ */
7
+
8
+ const TWITTER_PATH_REGEX = /\/status\/(\d+)/;
9
+
10
+ /**
11
+ * @implements ICustomProvider
12
+ */
13
+ class TwitterOEmbedProvider {
14
+ /**
15
+ * @param {object} dependencies
16
+ */
17
+ constructor(dependencies) {
18
+ this.dependencies = dependencies;
19
+ }
20
+
21
+ /**
22
+ * @param {URL} url
23
+ * @returns {Promise<boolean>}
24
+ */
25
+ async canSupportRequest(url) {
26
+ return url.host === 'twitter.com' && TWITTER_PATH_REGEX.test(url.pathname);
27
+ }
28
+
29
+ /**
30
+ * @param {URL} url
31
+ * @param {IExternalRequest} externalRequest
32
+ *
33
+ * @returns {Promise<object>}
34
+ */
35
+ async getOEmbedData(url, externalRequest) {
36
+ const [match, tweetId] = url.pathname.match(TWITTER_PATH_REGEX);
37
+ if (!match) {
38
+ return null;
39
+ }
40
+
41
+ /** @type {object} */
42
+ const oembedData = await extract(url.href);
43
+
44
+ if (this.dependencies.config.bearerToken) {
45
+ const query = {
46
+ expansions: ['attachments.poll_ids', 'attachments.media_keys', 'author_id', 'entities.mentions.username', 'geo.place_id', 'in_reply_to_user_id', 'referenced_tweets.id', 'referenced_tweets.id.author_id'],
47
+ 'media.fields': ['duration_ms', 'height', 'media_key', 'preview_image_url', 'type', 'url', 'width', 'public_metrics', 'alt_text'],
48
+ 'place.fields': ['contained_within', 'country', 'country_code', 'full_name', 'geo', 'id', 'name', 'place_type'],
49
+ 'poll.fields': ['duration_minutes', 'end_datetime', 'id', 'options', 'voting_status'],
50
+ 'tweet.fields': ['attachments', 'author_id', 'context_annotations', 'conversation_id', 'created_at', 'entities', 'geo', 'id', 'in_reply_to_user_id', 'lang', 'public_metrics', 'possibly_sensitive', 'referenced_tweets', 'reply_settings', 'source', 'text', 'withheld'],
51
+ 'user.fields': ['created_at', 'description', 'entities', 'id', 'location', 'name', 'pinned_tweet_id', 'profile_image_url', 'protected', 'public_metrics', 'url', 'username', 'verified', 'withheld']
52
+ };
53
+
54
+ const queryString = Object.keys(query).map((key) => {
55
+ return `${key}=${query[key].join(',')}`;
56
+ }).join('&');
57
+
58
+ try {
59
+ const result = await externalRequest(`https://api.twitter.com/2/tweets/${tweetId}?${queryString}`, {
60
+ responseType: 'json',
61
+ headers: {
62
+ Authorization: `Bearer ${this.dependencies.config.bearerToken}`
63
+ }
64
+ });
65
+
66
+ const body = JSON.parse(result.body);
67
+
68
+ oembedData.tweet_data = body.data;
69
+ oembedData.tweet_data.includes = body.includes;
70
+ } catch (err) {
71
+ this.dependencies.logging.error(err);
72
+ }
73
+ }
74
+
75
+ oembedData.type = 'twitter';
76
+
77
+ return oembedData;
78
+ }
79
+ }
80
+
81
+ module.exports = TwitterOEmbedProvider;
@@ -87,7 +87,7 @@ function ping(post) {
87
87
  if (!goodResponse.test(res.body)) {
88
88
  const matches = res.body.match(errorMessage);
89
89
  const message = matches ? matches[1] : res.body;
90
- throw new errors.GhostError({message});
90
+ throw new errors.InternalServerError({message});
91
91
  }
92
92
  })
93
93
  .catch(function (err) {
@@ -100,7 +100,7 @@ function ping(post) {
100
100
  help: tpl(messages.requestFailedHelp, {url: 'https://ghost.org/docs/'})
101
101
  });
102
102
  } else {
103
- error = new errors.GhostError({
103
+ error = new errors.InternalServerError({
104
104
  err: err,
105
105
  message: err.message,
106
106
  context: tpl(messages.requestFailedError, {service: 'xmlrpc'}),
@@ -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.24%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.26%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-7f3603dbeb5ebf0ec09e207ae82fb4e3.css" title="light">
44
+ <link rel="stylesheet" href="assets/ghost.min-57c1e677f42d596942d317ce93e8a62c.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-1a84ac3ef74edf31c6e86810b45221cc.js"></script>
63
- <script src="assets/ghost.min-d5595f9c71ebc534ccf9ac78483d357c.js"></script>
62
+ <script src="assets/vendor.min-b6b8d2a31d61830c2d8f65c5ba54236a.js"></script>
63
+ <script src="assets/ghost.min-f3c6886e191d34450e9ffca0c8fa056e.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.24%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.26%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-7f3603dbeb5ebf0ec09e207ae82fb4e3.css" title="light">
44
+ <link rel="stylesheet" href="assets/ghost.min-57c1e677f42d596942d317ce93e8a62c.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-1a84ac3ef74edf31c6e86810b45221cc.js"></script>
63
- <script src="assets/ghost.min-d5595f9c71ebc534ccf9ac78483d357c.js"></script>
62
+ <script src="assets/vendor.min-b6b8d2a31d61830c2d8f65c5ba54236a.js"></script>
63
+ <script src="assets/ghost.min-f3c6886e191d34450e9ffca0c8fa056e.js"></script>
64
64
 
65
65
  </body>
66
66
  </html>
@@ -44,7 +44,7 @@ const notImplemented = function (req, res, next) {
44
44
  }
45
45
  }
46
46
 
47
- next(new errors.GhostError({
47
+ next(new errors.InternalServerError({
48
48
  errorType: 'NotImplementedError',
49
49
  message: tpl(messages.notImplemented),
50
50
  statusCode: '501'
@@ -40,7 +40,7 @@ const notImplemented = function (req, res, next) {
40
40
  }
41
41
  }
42
42
 
43
- next(new errors.GhostError({
43
+ next(new errors.InternalServerError({
44
44
  errorType: 'NotImplementedError',
45
45
  message: tpl(messages.notImplemented),
46
46
  statusCode: '501'
@@ -44,7 +44,7 @@ const notImplemented = function (req, res, next) {
44
44
  }
45
45
  }
46
46
 
47
- next(new errors.GhostError({
47
+ next(new errors.InternalServerError({
48
48
  errorType: 'NotImplementedError',
49
49
  message: tpl(messages.notImplemented),
50
50
  statusCode: '501'
@@ -3,22 +3,15 @@ const config = require('../../../shared/config');
3
3
  const express = require('../../../shared/express');
4
4
  const compress = require('compression');
5
5
  const mw = require('./middleware');
6
- const vhost = require('@tryghost/vhost-middleware');
7
6
 
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}) {
7
+ module.exports = function setupParentApp() {
15
8
  debug('ParentApp setup start');
16
9
  const parentApp = express('parent');
17
10
 
18
11
  parentApp.use(mw.requestId);
19
12
  parentApp.use(mw.logRequest);
20
13
 
21
- // Register event emmiter on req/res to trigger cache invalidation webhook event
14
+ // Register event emitter on req/res to trigger cache invalidation webhook event
22
15
  parentApp.use(mw.emitEvents);
23
16
 
24
17
  // enabled gzip compression by default
@@ -30,19 +23,6 @@ module.exports = function setupParentApp({start, frontend = true, backend = true
30
23
  // @TODO: figure out if this is really needed everywhere? Is it not frontend only...
31
24
  parentApp.use(mw.ghostLocals);
32
25
 
33
- // Mount the express apps on the parentApp
34
-
35
- if (backend) {
36
- debug('Mounting bakcend: ADMIN + API');
37
- const backendApp = require('./backend')();
38
- parentApp.use(vhost(config.getBackendMountPath(), backendApp));
39
- }
40
-
41
- if (frontend) {
42
- debug('Mounting frontend: SITE + MEMBERS');
43
- const frontendApp = require('./frontend')({start});
44
- parentApp.use(vhost(config.getFrontendMountPath(), frontendApp));
45
- }
46
26
  debug('ParentApp setup end');
47
27
 
48
28
  return parentApp;
@@ -10,9 +10,11 @@ module.exports = () => {
10
10
  // BACKEND
11
11
  // Wrap the admin and API apps into a single express app for use with vhost
12
12
  const backendApp = express('backend');
13
+
13
14
  backendApp.lazyUse('/ghost/api', require('../api'));
14
15
  backendApp.lazyUse('/ghost/oauth', require('../oauth'));
15
16
  backendApp.lazyUse('/ghost/.well-known', require('../well-known'));
17
+
16
18
  backendApp.use('/ghost', require('../../services/auth/session').createSessionFromToken, require('../admin')());
17
19
 
18
20
  return backendApp;