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.
- package/.eslintrc.js +39 -0
- package/content/themes/casper/assets/built/casper.js +1 -1
- package/content/themes/casper/assets/built/casper.js.map +1 -1
- package/content/themes/casper/assets/built/global.css +1 -1
- package/content/themes/casper/assets/built/global.css.map +1 -1
- package/content/themes/casper/assets/built/screen.css +1 -1
- package/content/themes/casper/assets/built/screen.css.map +1 -1
- package/content/themes/casper/assets/css/global.css +6 -1
- package/content/themes/casper/assets/css/screen.css +50 -215
- package/content/themes/casper/default.hbs +2 -2
- package/content/themes/casper/package.json +3 -2
- package/content/themes/casper/post.hbs +1 -1
- package/content/themes/casper/yarn.lock +173 -123
- package/core/app.js +8 -4
- package/core/boot.js +52 -25
- package/core/built/assets/ghost-dark-ef86e3bc7f0fb83d39d3d6a49bff8dd5.css +1 -0
- package/core/built/assets/ghost.min-57c1e677f42d596942d317ce93e8a62c.css +1 -0
- package/core/built/assets/{ghost.min-d5595f9c71ebc534ccf9ac78483d357c.js → ghost.min-f3c6886e191d34450e9ffca0c8fa056e.js} +504 -579
- package/core/built/assets/icons/audio-upload.svg +8 -0
- package/core/built/assets/{vendor.min-1a84ac3ef74edf31c6e86810b45221cc.js → vendor.min-b6b8d2a31d61830c2d8f65c5ba54236a.js} +2614 -2149
- package/core/frontend/apps/amp/lib/helpers/amp_content.js +2 -2
- package/core/frontend/apps/amp/lib/views/amp.hbs +75 -0
- package/core/frontend/apps/private-blogging/index.js +1 -1
- package/core/frontend/helpers/url.js +18 -1
- package/core/frontend/services/apps/index.js +1 -1
- package/core/frontend/services/apps/loader.js +3 -3
- package/core/frontend/services/helpers/handlebars.js +1 -1
- package/core/frontend/services/theme-engine/middleware/ensure-active-theme.js +34 -0
- package/core/frontend/services/theme-engine/middleware/index.js +6 -0
- package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +116 -0
- package/core/frontend/services/theme-engine/middleware/update-local-template-data.js +9 -0
- package/core/frontend/services/theme-engine/middleware/update-local-template-options.js +57 -0
- package/core/frontend/src/cards/css/audio.css +186 -0
- package/core/frontend/src/cards/css/blockquote.css +27 -0
- package/core/frontend/src/cards/css/button.css +4 -0
- package/core/frontend/src/cards/css/callout.css +23 -14
- package/core/frontend/src/cards/css/toggle.css +42 -20
- package/core/frontend/src/cards/js/audio.js +137 -0
- package/core/frontend/web/middleware/error-handler.js +93 -0
- package/core/frontend/web/middleware/handle-image-sizes.js +3 -6
- package/core/frontend/web/middleware/index.js +1 -0
- package/core/frontend/web/site.js +2 -2
- package/core/server/adapters/scheduling/SchedulingDefault.js +2 -2
- package/core/server/adapters/storage/LocalStorageBase.js +2 -2
- package/core/server/api/canary/db.js +2 -2
- package/core/server/api/canary/media.js +3 -2
- package/core/server/api/canary/oembed.js +16 -1
- package/core/server/api/canary/session.js +1 -1
- package/core/server/api/canary/slugs.js +1 -1
- package/core/server/api/canary/utils/permissions.js +2 -2
- package/core/server/api/canary/utils/serializers/output/config.js +2 -6
- package/core/server/api/v2/db.js +2 -2
- package/core/server/api/v2/session.js +1 -1
- package/core/server/api/v2/slugs.js +1 -1
- package/core/server/api/v2/utils/permissions.js +2 -2
- package/core/server/api/v3/db.js +2 -2
- package/core/server/api/v3/session.js +1 -1
- package/core/server/api/v3/slugs.js +1 -1
- package/core/server/api/v3/utils/permissions.js +2 -2
- package/core/server/data/db/state-manager.js +4 -4
- package/core/server/data/exporter/export-filename.js +1 -1
- package/core/server/data/importer/handlers/json.js +1 -1
- package/core/server/data/importer/import-manager.js +1 -1
- package/core/server/data/importer/importers/data/base.js +1 -1
- package/core/server/data/migrations/utils.js +2 -2
- package/core/server/data/migrations/versions/1.25/1-update-koenig-beta-html.js +1 -0
- package/core/server/data/migrations/versions/3.1/08-add-uuid-values-to-members.js +1 -0
- package/core/server/data/migrations/versions/3.22/02-settings-key-renames.js +2 -0
- package/core/server/data/migrations/versions/3.22/05-migrate-members-subscription-settings.js +3 -0
- package/core/server/data/migrations/versions/3.22/06-migrate-stripe-connect-settings.js +2 -0
- package/core/server/data/migrations/versions/3.23/01-migrate-bulk-email-settings.js +1 -0
- package/core/server/data/migrations/versions/3.29/01-remove-duplicate-subscriptions.js +2 -0
- package/core/server/data/migrations/versions/3.29/02-remove-duplicate-customers.js +2 -0
- package/core/server/data/migrations/versions/3.38/04-populate-recipient-filter-column.js +2 -0
- package/core/server/data/migrations/versions/4.0/01-update-mobiledoc.js +2 -0
- package/core/server/data/migrations/versions/4.0/03-populate-status-column-for-members.js +4 -0
- package/core/server/data/migrations/versions/4.0/06-populate-members-subscribe-events-table.js +1 -0
- package/core/server/data/migrations/versions/4.0/17-populate-members-status-events-table.js +1 -0
- package/core/server/data/migrations/versions/4.0/18-transform-urls-absolute-to-transform-ready.js +5 -0
- package/core/server/data/migrations/versions/4.0/22-solve-orphaned-webhooks.js +1 -0
- package/core/server/data/migrations/versions/4.0/23-regenerate-posts-html.js +1 -0
- package/core/server/data/migrations/versions/4.0/25-populate-members-paid-subscription-events-table.js +2 -1
- package/core/server/data/migrations/versions/4.12/02-fix-member-statuses.js +1 -0
- package/core/server/data/migrations/versions/4.14/01-fix-comped-member-statuses.js +3 -0
- package/core/server/data/migrations/versions/4.14/02-fix-free-members-status-events.js +1 -0
- package/core/server/data/migrations/versions/4.20/05-remove-not-null-constraint-from-portal-title.js +2 -0
- package/core/server/data/migrations/versions/4.23/01-truncate-offer-names.js +1 -0
- package/core/server/data/migrations/versions/4.3/04-attach-members-to-product.js +1 -0
- package/core/server/data/migrations/versions/4.4/01-restore-free-members-signup-setting-from-backup.js +1 -0
- package/core/server/data/migrations/versions/4.6/01-remove-comped-status.js +1 -0
- package/core/server/data/migrations/versions/4.8/04-migrate-show-newsletter-header-setting.js +1 -0
- package/core/server/data/migrations/versions/4.9/05-fix-missed-mobiledoc-url-transforms.js +1 -0
- package/core/server/data/migrations/versions/4.9/06-add-comped-status.js +1 -0
- package/core/server/data/migrations/versions/4.9/07-update-comped-members-status-events.js +1 -0
- package/core/server/data/schema/commands.js +2 -2
- package/core/server/ghost-server.js +2 -2
- package/core/server/lib/image/image-size.js +2 -2
- package/core/server/models/base/listeners.js +2 -2
- package/core/server/models/member-email-change-event.js +2 -2
- package/core/server/models/member-login-event.js +2 -2
- package/core/server/models/member-paid-subscription-event.js +3 -3
- package/core/server/models/member-payment-event.js +3 -3
- package/core/server/models/member-product-event.js +6 -6
- package/core/server/models/member-status-event.js +5 -3
- package/core/server/models/member-subscribe-event.js +9 -3
- package/core/server/models/relations/authors.js +1 -1
- package/core/server/models/settings.js +1 -1
- package/core/server/notify.js +1 -2
- package/core/server/services/auth/passwordreset.js +1 -1
- package/core/server/services/auth/setup.js +1 -1
- package/core/server/services/mega/mega.js +6 -4
- package/core/server/services/mega/template.js +43 -17
- package/core/server/services/members/api.js +22 -0
- package/core/server/services/members/config.js +1 -1
- package/core/server/services/members/emails/signup-paid.js +168 -0
- package/core/server/services/members/service.js +6 -2
- package/core/server/services/members/stripe-connect.js +4 -2
- package/core/server/services/nft-oembed.js +7 -2
- package/core/server/services/oembed.js +15 -3
- package/core/server/services/permissions/can-this.js +1 -1
- package/core/server/services/redirects/api.js +2 -2
- package/core/server/services/route-settings/default-settings-manager.js +1 -1
- package/core/server/services/route-settings/route-settings.js +4 -12
- package/core/server/services/route-settings/settings-loader.js +4 -4
- package/core/server/services/route-settings/yaml-parser.js +1 -1
- package/core/server/services/slack.js +1 -1
- package/core/server/services/themes/storage.js +2 -2
- package/core/server/services/twitter-embed.js +81 -0
- package/core/server/services/xmlrpc.js +2 -2
- package/core/server/web/admin/views/default-prod.html +4 -4
- package/core/server/web/admin/views/default.html +4 -4
- package/core/server/web/api/canary/admin/middleware.js +1 -1
- package/core/server/web/api/v2/admin/middleware.js +1 -1
- package/core/server/web/api/v3/admin/middleware.js +1 -1
- package/core/server/web/parent/app.js +2 -22
- package/core/server/web/parent/backend.js +2 -0
- package/core/server/web/shared/middleware/error-handler.js +28 -150
- package/core/shared/config/defaults.json +7 -1
- package/core/shared/express.js +1 -1
- package/core/shared/labs.js +7 -7
- package/core/shared/sentry.js +1 -1
- package/package.json +38 -38
- package/yarn.lock +632 -941
- package/content/themes/casper/assets/js/gallery-card.js +0 -24
- package/core/built/assets/ghost-dark-e7b57ab951512c5719aee89b16b9a448.css +0 -1
- package/core/built/assets/ghost.min-7f3603dbeb5ebf0ec09e207ae82fb4e3.css +0 -1
- 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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
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.
|
|
39
|
+
if (errors.utils.isGhostError(err)) {
|
|
40
40
|
throw err;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
throw new errors.
|
|
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.
|
|
69
|
+
if (errors.utils.isGhostError(err)) {
|
|
70
70
|
throw err;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
throw new errors.
|
|
73
|
+
throw new errors.InternalServerError({
|
|
74
74
|
message: tpl(messages.settingsLoaderError, {
|
|
75
75
|
setting: 'routes',
|
|
76
76
|
path: this.settingFilePath
|
|
@@ -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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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-
|
|
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-
|
|
63
|
-
<script src="assets/ghost.min-
|
|
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.
|
|
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-
|
|
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-
|
|
63
|
-
<script src="assets/ghost.min-
|
|
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>
|
|
@@ -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
|
|
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;
|