ghost 4.18.0 → 4.20.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 +9 -8
- package/Gruntfile.js +1 -1
- package/PRIVACY.md +3 -0
- package/content/adapters/README.md +2 -2
- package/core/boot.js +17 -12
- package/core/bridge.js +9 -1
- package/core/built/assets/{chunk.3.b80d3e1e6b8556aaff3c.js → chunk.3.777d43e2ce954ba8b2f5.js} +25 -25
- package/core/built/assets/codemirror/{codemirror-21a09582262987037db73b152fb35f7c.js → codemirror-d25c379b87ec8b33d54ac7149bc0b6ae.js} +14 -14
- package/core/built/assets/ghost-dark-20e2892d4f30d0d1183c9ac725ea37d0.css +1 -0
- package/core/built/assets/{ghost.min-88d647a008a5b1dd678a89ae1e55c038.js → ghost.min-26e427944e719b616b8dc7fbb3bbd2f9.js} +709 -422
- package/core/built/assets/ghost.min-57e46fd3b1145ecf2cbd185a13611f3b.css +1 -0
- package/core/built/assets/icons/arrow-left-small.svg +0 -4
- package/core/built/assets/icons/paintbrush.svg +10 -1
- package/core/built/assets/icons/post.svg +3 -1
- package/core/built/assets/img/footer-marketplace-bg-572b6c6486a7e26316954d599eaa9f30.png +0 -0
- package/core/built/assets/img/marketing/offers-1-f2e1b653c4d5bb90eea9d7a2862530f9.jpg +0 -0
- package/core/built/assets/img/marketing/offers-2-28a225d34cc39d133748431536961d00.jpg +0 -0
- package/core/built/assets/img/marketing/offers-3-2094c91ab21a16c37fbe6ec16c140160.jpg +0 -0
- package/core/built/assets/img/themes/Alto-f4db5af43ca9771c7ac1f754de3ddf2f.png +0 -0
- package/core/built/assets/img/themes/Bulletin-57d45b992ff0e26e0acdce7ed4cccd67.png +0 -0
- package/core/built/assets/img/themes/Casper-c7e784d7188cc5d7f097d9b6c97b0263.jpg +0 -0
- package/core/built/assets/img/themes/Dawn-be81aa8c8caae8fcfb5d5fbec823fdcc.png +0 -0
- package/core/built/assets/img/themes/Digest-d3467ac22a290e1ad3a543014758286e.png +0 -0
- package/core/built/assets/img/themes/Dope-6f8e0bbc199ce4af9a60859e9e6a74ad.png +0 -0
- package/core/built/assets/img/themes/Ease-9c279ea6cec3c0f1823f81c9dd24b116.png +0 -0
- package/core/built/assets/img/themes/Edge-0258906309e11fd075a1d9880aa09b20.png +0 -0
- package/core/built/assets/img/themes/Edition-d8f508e93bc24bdf2716ae6f8b3d44f8.png +0 -0
- package/core/built/assets/img/themes/Editorial-a25a4a34c04dedd858bd5e05ef388b1c.jpg +0 -0
- package/core/built/assets/img/themes/Journal-accf0031bbae0919900a049061e65a04.png +0 -0
- package/core/built/assets/img/themes/London-3f07efcee9e5bfb9a33827064eb77e70.jpg +0 -0
- package/core/built/assets/img/themes/Massively-06edf00108429f7fb8e65f190fba34fe.jpg +0 -0
- package/core/built/assets/img/themes/Ruby-11a53c62015612f4b3aca8f503121225.png +0 -0
- package/core/built/assets/img/themes/Wave-86e8044c2d76cb57a9030e4c24ac9520.png +0 -0
- package/core/built/assets/simplemde/{simplemde-232f69d126310434489071a1891e6d8b.js → simplemde-3ffc0ec9e9fecf29b9a499db678c9e65.js} +14 -14
- package/core/built/assets/{vendor.min-7dc7cf9c92175ebfb9cea95c120ee8a7.js → vendor.min-af502ac4142871500fc424f6a5a254ec.js} +2206 -1859
- package/core/frontend/apps/amp/lib/router.js +1 -1
- package/core/frontend/helpers/match.js +17 -23
- package/core/frontend/meta/author-url.js +1 -1
- package/core/frontend/meta/url.js +1 -1
- package/core/{server → frontend}/public/favicon.ico +0 -0
- package/core/{server → frontend}/public/ghost.css +0 -0
- package/core/{server → frontend}/public/ghost.min.css +0 -0
- package/core/{server → frontend}/public/robots.txt +0 -0
- package/core/{server → frontend}/public/sitemap.xsl +0 -0
- package/core/frontend/services/proxy.js +1 -1
- package/core/frontend/services/rendering.js +1 -1
- package/core/frontend/services/routing/CollectionRouter.js +3 -49
- package/core/frontend/services/routing/ParentRouter.js +1 -4
- package/core/frontend/services/routing/StaticPagesRouter.js +3 -5
- package/core/frontend/services/routing/StaticRoutesRouter.js +4 -6
- package/core/frontend/services/routing/TaxonomyRouter.js +4 -5
- package/core/frontend/services/routing/controllers/collection.js +2 -2
- package/core/frontend/services/routing/controllers/email-post.js +2 -2
- package/core/frontend/services/routing/controllers/entry.js +2 -2
- package/core/frontend/services/routing/controllers/preview.js +2 -2
- package/core/frontend/services/routing/index.js +6 -12
- package/core/frontend/services/routing/registry.js +13 -0
- package/core/frontend/services/routing/router-manager.js +185 -0
- package/core/frontend/services/rss/generate-feed.js +2 -2
- package/core/frontend/services/theme-engine/i18n/i18n.js +267 -28
- package/core/frontend/services/theme-engine/i18n/index.js +1 -1
- package/core/frontend/services/theme-engine/i18n/theme-i18n.js +73 -0
- package/core/frontend/web/index.js +1 -0
- package/core/{server/web/site → frontend/web}/middleware/handle-image-sizes.js +4 -4
- package/core/{server/web/site → frontend/web}/middleware/index.js +0 -0
- package/core/{server/web/site → frontend/web}/middleware/redirect-ghost-to-admin.js +3 -3
- package/core/{server/web/site → frontend/web}/middleware/serve-favicon.js +6 -6
- package/core/{server/web/site → frontend/web}/middleware/serve-public-file.js +2 -2
- package/core/{server/web/site → frontend/web}/middleware/static-theme.js +3 -3
- package/core/frontend/web/routes.js +13 -0
- package/core/{server/web/site/app.js → frontend/web/site.js} +12 -16
- package/core/server/adapters/storage/LocalFileStorage.js +35 -39
- package/core/server/adapters/storage/index.js +12 -2
- package/core/server/api/canary/custom-theme-settings.js +2 -2
- package/core/server/api/canary/images.js +1 -1
- package/core/server/api/canary/oembed.js +2 -2
- package/core/server/api/canary/offers.js +29 -1
- package/core/server/api/canary/posts-public.js +6 -2
- package/core/server/api/canary/products.js +6 -2
- package/core/server/api/canary/tags-public.js +6 -2
- package/core/server/api/canary/users.js +9 -4
- package/core/server/api/canary/utils/serializers/output/custom-theme-settings.js +2 -2
- package/core/server/api/canary/utils/serializers/output/notifications.js +1 -0
- package/core/server/api/canary/utils/serializers/output/settings.js +2 -3
- package/core/server/api/canary/utils/serializers/output/utils/url.js +1 -1
- package/core/server/api/canary/utils/validators/input/oembed.js +4 -1
- package/core/server/api/canary/utils/validators/input/passwordreset.js +8 -3
- package/core/server/api/canary/utils/validators/input/settings.js +5 -4
- package/core/server/api/canary/utils/validators/input/setup.js +6 -2
- package/core/server/api/canary/utils/validators/input/users.js +6 -2
- package/core/server/api/canary/utils/validators/input/webhooks.js +8 -3
- package/core/server/api/v2/images.js +1 -1
- package/core/server/api/v2/utils/serializers/output/authentication.js +9 -4
- package/core/server/api/v2/utils/serializers/output/notifications.js +1 -0
- package/core/server/api/v2/utils/serializers/output/users.js +5 -3
- package/core/server/api/v2/utils/serializers/output/utils/url.js +1 -1
- package/core/server/api/v2/utils/validators/input/images.js +11 -6
- package/core/server/api/v2/utils/validators/input/invitations.js +14 -6
- package/core/server/api/v2/utils/validators/input/invites.js +6 -2
- package/core/server/api/v2/utils/validators/input/oembed.js +6 -2
- package/core/server/api/v2/utils/validators/input/passwordreset.js +8 -3
- package/core/server/api/v2/utils/validators/input/settings.js +10 -4
- package/core/server/api/v2/utils/validators/input/setup.js +6 -2
- package/core/server/api/v2/utils/validators/input/users.js +5 -2
- package/core/server/api/v3/authentication.js +6 -2
- package/core/server/api/v3/authors-public.js +6 -2
- package/core/server/api/v3/email.js +9 -4
- package/core/server/api/v3/images.js +1 -1
- package/core/server/api/v3/integrations.js +7 -3
- package/core/server/api/v3/invites.js +6 -3
- package/core/server/api/v3/labels.js +10 -5
- package/core/server/api/v3/memberSigninUrls.js +5 -2
- package/core/server/api/v3/oembed.js +2 -2
- package/core/server/api/v3/pages-public.js +5 -2
- package/core/server/api/v3/pages.js +6 -3
- package/core/server/api/v3/posts-public.js +5 -3
- package/core/server/api/v3/posts.js +7 -3
- package/core/server/api/v3/preview.js +5 -3
- package/core/server/api/v3/session.js +7 -3
- package/core/server/api/v3/settings.js +8 -3
- package/core/server/api/v3/slugs.js +5 -4
- package/core/server/api/v3/utils/serializers/output/authentication.js +10 -4
- package/core/server/api/v3/utils/serializers/output/notifications.js +1 -0
- package/core/server/api/v3/utils/serializers/output/settings.js +2 -3
- package/core/server/api/v3/utils/serializers/output/users.js +6 -2
- package/core/server/api/v3/utils/serializers/output/utils/url.js +1 -1
- package/core/server/api/v3/utils/validators/input/images.js +12 -7
- package/core/server/api/v3/utils/validators/input/invitations.js +14 -6
- package/core/server/api/v3/utils/validators/input/invites.js +6 -2
- package/core/server/api/v3/utils/validators/input/oembed.js +6 -2
- package/core/server/api/v3/utils/validators/input/passwordreset.js +8 -3
- package/core/server/api/v3/utils/validators/input/settings.js +5 -4
- package/core/server/api/v3/utils/validators/input/setup.js +6 -2
- package/core/server/api/v3/utils/validators/input/users.js +6 -2
- package/core/server/api/v3/utils/validators/input/webhooks.js +8 -3
- package/core/server/data/exporter/table-lists.js +2 -1
- package/core/server/data/importer/handlers/image.js +1 -1
- package/core/server/data/importer/importers/image.js +1 -1
- package/core/server/data/migrations/init/1-create-tables.js +7 -8
- package/core/server/data/migrations/init/2-create-fixtures.js +8 -8
- package/core/server/data/migrations/versions/4.19/01-add-active-column-to-offers.js +7 -0
- package/core/server/data/migrations/versions/4.19/02-add-offer-redemptions-table.js +8 -0
- package/core/server/data/migrations/versions/4.20/01-remove-offer-redemptions-table.js +19 -0
- package/core/server/data/migrations/versions/4.20/02-remove-offers-table.js +30 -0
- package/core/server/data/migrations/versions/4.20/03-add-offers-table.js +21 -0
- package/core/server/data/migrations/versions/4.20/04-add-offer-redemptions-table.js +9 -0
- package/core/server/data/migrations/versions/4.20/05-remove-not-null-constraint-from-portal-title.js +41 -0
- package/core/server/data/schema/fixtures/utils.js +150 -143
- package/core/server/data/schema/schema.js +15 -3
- package/core/server/frontend/ghost.min.css +1 -0
- package/core/server/lib/image/blog-icon.js +10 -10
- package/core/server/lib/image/image-size.js +5 -5
- package/core/server/lib/image/image-utils.js +4 -4
- package/core/server/lib/image/index.js +1 -2
- package/core/server/lib/mobiledoc.js +3 -2
- package/core/server/models/action.js +7 -4
- package/core/server/models/base/plugins/overrides.js +19 -6
- package/core/server/models/custom-theme-setting.js +56 -1
- package/core/server/models/index.js +4 -45
- package/core/server/models/member.js +5 -0
- package/core/server/models/offer-redemption.js +10 -0
- package/core/server/models/user.js +2 -1
- package/core/server/overrides.js +6 -2
- package/core/server/run-update-check.js +0 -3
- package/core/server/services/adapter-manager/config.js +1 -0
- package/core/server/services/adapter-manager/index.js +9 -5
- package/core/server/services/adapter-manager/options-resolver.js +18 -0
- package/core/server/services/bulk-email/bulk-email-processor.js +6 -2
- package/core/server/services/bulk-email/mailgun.js +1 -1
- package/core/server/services/custom-theme-settings.js +10 -4
- package/core/server/services/invites/index.js +0 -2
- package/core/server/services/invites/invites.js +5 -5
- package/core/server/services/mail/GhostMailer.js +18 -10
- package/core/server/services/mega/mega.js +3 -3
- package/core/server/services/mega/post-email-serializer.js +2 -2
- package/core/server/services/members/api.js +3 -4
- package/core/server/services/members/emails/signin.js +1 -1
- package/core/server/services/members/emails/signup.js +1 -1
- package/core/server/services/members/emails/subscribe.js +1 -1
- package/core/server/services/members/middleware.js +10 -0
- package/core/server/services/members/service.js +2 -1
- package/core/server/services/notifications/index.js +1 -1
- package/core/server/services/notifications/notifications.js +40 -35
- package/core/server/services/oembed.js +4 -9
- package/core/server/services/offers/service.js +16 -6
- package/core/server/services/permissions/public.js +6 -2
- package/core/server/services/route-settings/route-settings.js +1 -1
- package/core/server/services/settings/index.js +3 -1
- package/core/server/services/settings/settings-bread-service.js +42 -20
- package/core/server/services/slack.js +1 -1
- package/core/server/services/themes/activate.js +2 -2
- package/core/server/services/themes/activation-bridge.js +6 -6
- package/core/server/services/themes/storage.js +1 -1
- package/core/{frontend → server}/services/url/Queue.js +0 -0
- package/core/{frontend → server}/services/url/Resource.js +0 -0
- package/core/{frontend → server}/services/url/Resources.js +2 -2
- package/core/{frontend → server}/services/url/UrlGenerator.js +14 -14
- package/core/{frontend → server}/services/url/UrlService.js +12 -15
- package/core/{frontend → server}/services/url/Urls.js +1 -1
- package/core/{frontend → server}/services/url/configs/canary.js +0 -0
- package/core/{frontend → server}/services/url/configs/v2.js +0 -0
- package/core/{frontend → server}/services/url/configs/v3.js +0 -0
- package/core/{frontend → server}/services/url/configs/v4.js +0 -0
- package/core/{frontend → server}/services/url/index.js +0 -0
- package/core/server/services/xmlrpc.js +1 -1
- package/core/server/update-check.js +3 -3
- package/core/server/web/admin/controller.js +11 -0
- 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/app.js +8 -9
- package/core/server/web/members/app.js +1 -0
- package/core/server/web/oauth/app.js +4 -2
- package/core/server/web/parent/backend.js +3 -3
- package/core/server/web/parent/frontend.js +2 -2
- package/core/server/web/shared/middlewares/api/spam-prevention.js +0 -2
- package/core/server/web/shared/middlewares/custom-redirects.js +0 -8
- package/core/server/web/shared/middlewares/maintenance.js +1 -1
- package/core/server/web/well-known.js +10 -10
- package/core/shared/config/defaults.json +2 -2
- package/core/shared/config/overrides.json +1 -1
- package/core/shared/express.js +10 -0
- package/core/shared/html-to-plaintext.js +2 -2
- package/core/shared/labs.js +14 -6
- package/loggingrc.js +10 -0
- package/package.json +60 -57
- package/yarn.lock +1317 -914
- package/core/built/assets/ghost-dark-13627f10941a7dbb2b12e1d41dc51c34.css +0 -1
- package/core/built/assets/ghost.min-d9cbfb4eb2db8915fcd2bf2416218616.css +0 -1
- package/core/built/assets/img/themes/London-68501c8ab797de7f2851cf9ea0a28e26.jpg +0 -0
- package/core/frontend/services/routing/bootstrap.js +0 -114
- package/core/server/public/404-ghost.png +0 -0
- package/core/server/public/404-ghost@2x.png +0 -0
- package/core/server/web/site/index.js +0 -1
- package/core/server/web/site/routes.js +0 -9
- package/core/shared/i18n/i18n.js +0 -312
- package/core/shared/i18n/index.js +0 -6
- package/core/shared/i18n/translations/en.json +0 -675
|
@@ -9,7 +9,7 @@ const Resources = require('./Resources');
|
|
|
9
9
|
const urlUtils = require('../../../shared/url-utils');
|
|
10
10
|
|
|
11
11
|
// This listens to services.themes.api.changed, routing events, and it's own queue events
|
|
12
|
-
const events = require('
|
|
12
|
+
const events = require('../../lib/common/events');
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* The url service class holds all instances in a centralized place.
|
|
@@ -35,9 +35,6 @@ class UrlService {
|
|
|
35
35
|
* @private
|
|
36
36
|
*/
|
|
37
37
|
_listeners() {
|
|
38
|
-
this._onRouterAddedListener = this._onRouterAddedType.bind(this);
|
|
39
|
-
events.on('router.created', this._onRouterAddedListener);
|
|
40
|
-
|
|
41
38
|
this._onThemeChangedListener = this._onThemeChangedListener.bind(this);
|
|
42
39
|
events.on('services.themes.api.changed', this._onThemeChangedListener);
|
|
43
40
|
|
|
@@ -77,22 +74,23 @@ class UrlService {
|
|
|
77
74
|
/**
|
|
78
75
|
* @description Router was created, connect it with a url generator.
|
|
79
76
|
* @param {ExpressRouter} router
|
|
80
|
-
* @private
|
|
81
77
|
*/
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
// e.g. static route router
|
|
85
|
-
// we are listening on the general `router.created` event - every router throws this event
|
|
86
|
-
if (!router || !router.getPermalinks()) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
debug('router.created');
|
|
78
|
+
onRouterAddedType(router) {
|
|
79
|
+
debug('Registering route: ', router.name);
|
|
91
80
|
|
|
92
81
|
let urlGenerator = new UrlGenerator(router, this.queue, this.resources, this.urls, this.urlGenerators.length);
|
|
93
82
|
this.urlGenerators.push(urlGenerator);
|
|
94
83
|
}
|
|
95
84
|
|
|
85
|
+
/**
|
|
86
|
+
* @description Router update handler - regenerates it's resources
|
|
87
|
+
* @param {ExpressRouter} router
|
|
88
|
+
*/
|
|
89
|
+
onRouterUpdated(router) {
|
|
90
|
+
const generator = this.urlGenerators.find(g => g.router.id === router.id);
|
|
91
|
+
generator.regenerateResources();
|
|
92
|
+
}
|
|
93
|
+
|
|
96
94
|
/**
|
|
97
95
|
* @description If the API version in the theme config changes, we have to reset urls and resources.
|
|
98
96
|
* @private
|
|
@@ -307,7 +305,6 @@ class UrlService {
|
|
|
307
305
|
if (!options.keepListeners) {
|
|
308
306
|
this._onQueueStartedListener && this.queue.removeListener('started', this._onQueueStartedListener);
|
|
309
307
|
this._onQueueEndedListener && this.queue.removeListener('ended', this._onQueueEndedListener);
|
|
310
|
-
this._onRouterAddedListener && events.removeListener('router.created', this._onRouterAddedListener);
|
|
311
308
|
this._onThemeChangedListener && events.removeListener('services.themes.api.changed', this._onThemeChangedListener);
|
|
312
309
|
}
|
|
313
310
|
}
|
|
@@ -5,7 +5,7 @@ const logging = require('@tryghost/logging');
|
|
|
5
5
|
const errors = require('@tryghost/errors');
|
|
6
6
|
|
|
7
7
|
// This emits its own url added/removed events
|
|
8
|
-
const events = require('
|
|
8
|
+
const events = require('../../lib/common/events');
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* This class keeps track of all urls in the system.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
2
|
const xml = require('xml');
|
|
3
3
|
const config = require('../../shared/config');
|
|
4
|
-
const urlService = require('
|
|
4
|
+
const urlService = require('./url');
|
|
5
5
|
const errors = require('@tryghost/errors');
|
|
6
6
|
const tpl = require('@tryghost/tpl');
|
|
7
7
|
const logging = require('@tryghost/logging');
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
2
|
|
|
3
3
|
const api = require('./api');
|
|
4
|
-
const GhostMailer = require('./services/mail').GhostMailer;
|
|
5
4
|
const config = require('../shared/config');
|
|
6
5
|
const urlUtils = require('./../shared/url-utils');
|
|
7
6
|
const jobsService = require('./services/jobs');
|
|
@@ -10,8 +9,6 @@ const request = require('@tryghost/request');
|
|
|
10
9
|
const ghostVersion = require('@tryghost/version');
|
|
11
10
|
const UpdateCheckService = require('@tryghost/update-check-service');
|
|
12
11
|
|
|
13
|
-
const ghostMailer = new GhostMailer();
|
|
14
|
-
|
|
15
12
|
/**
|
|
16
13
|
* Initializes and triggers update check
|
|
17
14
|
*
|
|
@@ -25,6 +22,9 @@ module.exports = async () => {
|
|
|
25
22
|
return;
|
|
26
23
|
}
|
|
27
24
|
|
|
25
|
+
const {GhostMailer} = require('./services/mail');
|
|
26
|
+
const ghostMailer = new GhostMailer();
|
|
27
|
+
|
|
28
28
|
const updateChecker = new UpdateCheckService({
|
|
29
29
|
api: {
|
|
30
30
|
settings: {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const debug = require('@tryghost/debug')('web:admin:controller');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const crypto = require('crypto');
|
|
3
5
|
const config = require('../../../shared/config');
|
|
4
6
|
const updateCheck = require('../../update-check');
|
|
5
7
|
|
|
@@ -21,6 +23,15 @@ module.exports = function adminController(req, res) {
|
|
|
21
23
|
const templatePath = path.resolve(config.get('paths').adminViews, defaultTemplate);
|
|
22
24
|
const headers = {};
|
|
23
25
|
|
|
26
|
+
// Generate our own ETag header
|
|
27
|
+
// `sendFile` by default uses filesize+lastmod date to generate an etag.
|
|
28
|
+
// That doesn't work for admin templates because the filesize doesn't change between versions
|
|
29
|
+
// and `npm pack` sets a fixed lastmod date for every file meaning the default etag never changes
|
|
30
|
+
const fileBuffer = fs.readFileSync(templatePath);
|
|
31
|
+
const hashSum = crypto.createHash('md5');
|
|
32
|
+
hashSum.update(fileBuffer);
|
|
33
|
+
headers.ETag = hashSum.digest('hex');
|
|
34
|
+
|
|
24
35
|
if (config.get('adminFrameProtection')) {
|
|
25
36
|
headers['X-Frame-Options'] = 'sameorigin';
|
|
26
37
|
}
|
|
@@ -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.20%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-57e46fd3b1145ecf2cbd185a13611f3b.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-af502ac4142871500fc424f6a5a254ec.js"></script>
|
|
63
|
+
<script src="assets/ghost.min-26e427944e719b616b8dc7fbb3bbd2f9.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.20%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-57e46fd3b1145ecf2cbd185a13611f3b.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-af502ac4142871500fc424f6a5a254ec.js"></script>
|
|
63
|
+
<script src="assets/ghost.min-26e427944e719b616b8dc7fbb3bbd2f9.js"></script>
|
|
64
64
|
|
|
65
65
|
</body>
|
|
66
66
|
</html>
|
|
@@ -12,18 +12,17 @@ module.exports = function setupApiApp() {
|
|
|
12
12
|
apiApp.use(require('./testmode')());
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
apiApp.
|
|
17
|
-
apiApp.use(urlUtils.getVersionPath({version: 'v2', type: 'admin'}), require('./v2/admin/app')());
|
|
15
|
+
apiApp.lazyUse(urlUtils.getVersionPath({version: 'v2', type: 'content'}), require('./v2/content/app'));
|
|
16
|
+
apiApp.lazyUse(urlUtils.getVersionPath({version: 'v2', type: 'admin'}), require('./v2/admin/app'));
|
|
18
17
|
|
|
19
|
-
apiApp.
|
|
20
|
-
apiApp.
|
|
18
|
+
apiApp.lazyUse(urlUtils.getVersionPath({version: 'v3', type: 'content'}), require('./v3/content/app'));
|
|
19
|
+
apiApp.lazyUse(urlUtils.getVersionPath({version: 'v3', type: 'admin'}), require('./v3/admin/app'));
|
|
21
20
|
|
|
22
|
-
apiApp.
|
|
23
|
-
apiApp.
|
|
21
|
+
apiApp.lazyUse(urlUtils.getVersionPath({version: 'v4', type: 'content'}), require('./canary/content/app'));
|
|
22
|
+
apiApp.lazyUse(urlUtils.getVersionPath({version: 'v4', type: 'admin'}), require('./canary/admin/app'));
|
|
24
23
|
|
|
25
|
-
apiApp.
|
|
26
|
-
apiApp.
|
|
24
|
+
apiApp.lazyUse(urlUtils.getVersionPath({version: 'canary', type: 'content'}), require('./canary/content/app'));
|
|
25
|
+
apiApp.lazyUse(urlUtils.getVersionPath({version: 'canary', type: 'admin'}), require('./canary/admin/app'));
|
|
27
26
|
|
|
28
27
|
// Error handling for requests to non-existent API versions
|
|
29
28
|
apiApp.use(errorHandler.resourceNotFound);
|
|
@@ -37,6 +37,7 @@ module.exports = function setupMembersApp() {
|
|
|
37
37
|
membersApp.put('/api/member', bodyParser.json({limit: '1mb'}), middleware.updateMemberData);
|
|
38
38
|
membersApp.post('/api/member/email', bodyParser.json({limit: '1mb'}), (req, res) => membersService.api.middleware.updateEmailAddress(req, res));
|
|
39
39
|
membersApp.get('/api/session', middleware.getIdentityToken);
|
|
40
|
+
membersApp.get('/api/offers/:id', labs.enabledMiddleware('offers'), middleware.getOfferData);
|
|
40
41
|
membersApp.delete('/api/session', middleware.deleteSession);
|
|
41
42
|
membersApp.get('/api/site', middleware.getMemberSiteData);
|
|
42
43
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
const debug = require('@tryghost/debug')('web:oauth:app');
|
|
2
2
|
const {URL} = require('url');
|
|
3
|
-
const passport = require('passport');
|
|
4
|
-
const GoogleStrategy = require('passport-google-oauth20').Strategy;
|
|
5
3
|
const express = require('../../../shared/express');
|
|
6
4
|
const urlUtils = require('../../../shared/url-utils');
|
|
7
5
|
const shared = require('../shared');
|
|
@@ -36,6 +34,10 @@ module.exports = function setupOAuthApp() {
|
|
|
36
34
|
*/
|
|
37
35
|
function googleOAuthMiddleware(clientId, secret) {
|
|
38
36
|
return (req, res, next) => {
|
|
37
|
+
// Lazy-required to save boot time
|
|
38
|
+
const passport = require('passport');
|
|
39
|
+
const GoogleStrategy = require('passport-google-oauth20').Strategy;
|
|
40
|
+
|
|
39
41
|
const adminURL = urlUtils.urlFor('admin', true);
|
|
40
42
|
|
|
41
43
|
//Create the callback url to be sent to Google
|
|
@@ -10,9 +10,9 @@ 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
|
-
backendApp.
|
|
14
|
-
backendApp.
|
|
15
|
-
backendApp.
|
|
13
|
+
backendApp.lazyUse('/ghost/api', require('../api'));
|
|
14
|
+
backendApp.lazyUse('/ghost/oauth', require('../oauth'));
|
|
15
|
+
backendApp.lazyUse('/ghost/.well-known', require('../well-known'));
|
|
16
16
|
backendApp.use('/ghost', require('../../services/auth/session').createSessionFromToken, require('../admin')());
|
|
17
17
|
|
|
18
18
|
return backendApp;
|
|
@@ -18,8 +18,8 @@ module.exports = (options) => {
|
|
|
18
18
|
// otherwise we serve assets/pages with http. This can cause mixed content warnings in the admin client.
|
|
19
19
|
frontendApp.use(shared.middlewares.urlRedirects.frontendSSLRedirect);
|
|
20
20
|
|
|
21
|
-
frontendApp.
|
|
22
|
-
frontendApp.use('/', require('
|
|
21
|
+
frontendApp.lazyUse('/members', require('../members'));
|
|
22
|
+
frontendApp.use('/', require('../../../frontend/web')(options));
|
|
23
23
|
|
|
24
24
|
return frontendApp;
|
|
25
25
|
};
|
|
@@ -107,7 +107,6 @@ const globalReset = () => {
|
|
|
107
107
|
extend({
|
|
108
108
|
attachResetToRequest: false,
|
|
109
109
|
failCallback(req, res, next, nextValidRequestDate) {
|
|
110
|
-
// TODO use i18n again
|
|
111
110
|
return next(new errors.TooManyRequestsError({
|
|
112
111
|
message: `Too many attempts try again in ${moment(nextValidRequestDate).fromNow(true)}`,
|
|
113
112
|
context: tpl(messages.forgottenPasswordIp.error,
|
|
@@ -143,7 +142,6 @@ const userLogin = () => {
|
|
|
143
142
|
failCallback(req, res, next, nextValidRequestDate) {
|
|
144
143
|
return next(new errors.TooManyRequestsError({
|
|
145
144
|
message: `Too many sign-in attempts try again in ${moment(nextValidRequestDate).fromNow(true)}`,
|
|
146
|
-
// TODO add more options to i18n
|
|
147
145
|
context: tpl(messages.tooManySigninAttempts.context),
|
|
148
146
|
help: tpl(messages.tooManySigninAttempts.context)
|
|
149
147
|
}));
|
|
@@ -7,7 +7,6 @@ const urlUtils = require('../../../../shared/url-utils');
|
|
|
7
7
|
const errors = require('@tryghost/errors');
|
|
8
8
|
const logging = require('@tryghost/logging');
|
|
9
9
|
const redirectsService = require('../../../services/redirects');
|
|
10
|
-
const labsService = require('../../../../shared/labs');
|
|
11
10
|
|
|
12
11
|
const messages = {
|
|
13
12
|
customRedirectsRegistrationFailure: 'Could not register custom redirects.'
|
|
@@ -27,13 +26,6 @@ let customRedirectsRouter;
|
|
|
27
26
|
_private.registerRoutes = (router, redirects) => {
|
|
28
27
|
debug('redirects loading');
|
|
29
28
|
|
|
30
|
-
if (labsService.isSet('offers')) {
|
|
31
|
-
redirects.unshift({
|
|
32
|
-
from: '/zimo50',
|
|
33
|
-
to: '/#/portal/offers/abcdefuckoff'
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
29
|
redirects.forEach((redirect) => {
|
|
38
30
|
/**
|
|
39
31
|
* Detect case insensitive modifier when regex is enclosed by
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const errors = require('@tryghost/errors');
|
|
2
2
|
const config = require('../../../../shared/config');
|
|
3
3
|
const tpl = require('@tryghost/tpl');
|
|
4
|
-
const urlService = require('
|
|
4
|
+
const urlService = require('../../../services/url');
|
|
5
5
|
|
|
6
6
|
const messages = {
|
|
7
7
|
maintenance: 'Site is currently undergoing maintenance, please wait a moment then retry.',
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
const express = require('../../shared/express');
|
|
2
2
|
const settings = require('../../shared/settings-cache');
|
|
3
|
-
const jose = require('node-jose');
|
|
4
|
-
|
|
5
|
-
const dangerousPrivateKey = settings.get('ghost_private_key');
|
|
6
|
-
const keyStore = jose.JWK.createKeyStore();
|
|
7
|
-
const keyStoreReady = keyStore.add(dangerousPrivateKey, 'pem');
|
|
8
|
-
|
|
9
|
-
const getSafePublicJWKS = async () => {
|
|
10
|
-
await keyStoreReady;
|
|
11
|
-
return keyStore.toJSON();
|
|
12
|
-
};
|
|
13
3
|
|
|
14
4
|
module.exports = function setupWellKnownApp() {
|
|
15
5
|
const wellKnownApp = express('well-known');
|
|
16
6
|
|
|
7
|
+
const jose = require('node-jose');
|
|
8
|
+
const dangerousPrivateKey = settings.get('ghost_private_key');
|
|
9
|
+
const keyStore = jose.JWK.createKeyStore();
|
|
10
|
+
const keyStoreReady = keyStore.add(dangerousPrivateKey, 'pem');
|
|
11
|
+
|
|
12
|
+
const getSafePublicJWKS = async () => {
|
|
13
|
+
await keyStoreReady;
|
|
14
|
+
return keyStore.toJSON();
|
|
15
|
+
};
|
|
16
|
+
|
|
17
17
|
wellKnownApp.get('/jwks.json', async (req, res) => {
|
|
18
18
|
const jwks = await getSafePublicJWKS();
|
|
19
19
|
res.json(jwks);
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
"emailAnalytics": true
|
|
122
122
|
},
|
|
123
123
|
"portal": {
|
|
124
|
-
"url": "https://unpkg.com/@tryghost/portal@~1.
|
|
125
|
-
"version": "1.
|
|
124
|
+
"url": "https://unpkg.com/@tryghost/portal@~1.12.0/umd/portal.min.js",
|
|
125
|
+
"version": "1.12"
|
|
126
126
|
}
|
|
127
127
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"internalAppPath": "core/frontend/apps/",
|
|
11
11
|
"internalAdaptersPath": "core/server/adapters/",
|
|
12
12
|
"migrationPath": "core/server/data/migrations",
|
|
13
|
-
"publicFilePath": "core/
|
|
13
|
+
"publicFilePath": "core/frontend/public"
|
|
14
14
|
},
|
|
15
15
|
"apps": {
|
|
16
16
|
"internal": [
|
package/core/shared/express.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const debug = require('@tryghost/debug')('shared:express');
|
|
2
2
|
const express = require('express');
|
|
3
|
+
const {createLazyRouter} = require('express-lazy-router');
|
|
3
4
|
const sentry = require('./sentry');
|
|
4
5
|
|
|
6
|
+
const lazyLoad = createLazyRouter();
|
|
7
|
+
|
|
5
8
|
module.exports = (name) => {
|
|
6
9
|
debug('new app start', name);
|
|
7
10
|
const app = express();
|
|
@@ -14,6 +17,13 @@ module.exports = (name) => {
|
|
|
14
17
|
// Sentry must be our first error handler. Mounting it here means all custom error handlers will come after
|
|
15
18
|
app.use(sentry.errorHandler);
|
|
16
19
|
|
|
20
|
+
app.lazyUse = function lazyUse(mountPath, requireFn) {
|
|
21
|
+
app.use(mountPath, lazyLoad(() => {
|
|
22
|
+
debug(`lazy-loading on ${mountPath}`);
|
|
23
|
+
return Promise.resolve(requireFn());
|
|
24
|
+
}));
|
|
25
|
+
};
|
|
26
|
+
|
|
17
27
|
debug('new app end', name);
|
|
18
28
|
return app;
|
|
19
29
|
};
|
package/core/shared/labs.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
2
|
const Promise = require('bluebird');
|
|
3
|
-
const SafeString = require('express-hbs').SafeString;
|
|
4
3
|
const errors = require('@tryghost/errors');
|
|
5
4
|
const logging = require('@tryghost/logging');
|
|
6
5
|
const tpl = require('@tryghost/tpl');
|
|
@@ -14,21 +13,25 @@ const messages = {
|
|
|
14
13
|
errorHelp: 'See {url}'
|
|
15
14
|
};
|
|
16
15
|
|
|
16
|
+
// flags in this list always return `true`, allows quick global enable prior to full flag removal
|
|
17
|
+
const GA_FEATURES = [
|
|
18
|
+
'customThemeSettings',
|
|
19
|
+
'offers'
|
|
20
|
+
];
|
|
21
|
+
|
|
17
22
|
// NOTE: this allowlist is meant to be used to filter out any unexpected
|
|
18
23
|
// input for the "labs" setting value
|
|
19
24
|
const BETA_FEATURES = [
|
|
20
25
|
'activitypub',
|
|
21
|
-
'matchHelper',
|
|
22
26
|
'multipleProducts'
|
|
23
27
|
];
|
|
24
28
|
|
|
25
29
|
const ALPHA_FEATURES = [
|
|
26
30
|
'oauthLogin',
|
|
27
|
-
'
|
|
28
|
-
'membersActivity',
|
|
29
|
-
'offers'
|
|
31
|
+
'membersActivity'
|
|
30
32
|
];
|
|
31
33
|
|
|
34
|
+
module.exports.GA_KEYS = [...GA_FEATURES];
|
|
32
35
|
module.exports.WRITABLE_KEYS_ALLOWLIST = [...BETA_FEATURES, ...ALPHA_FEATURES];
|
|
33
36
|
|
|
34
37
|
module.exports.getAll = () => {
|
|
@@ -40,6 +43,10 @@ module.exports.getAll = () => {
|
|
|
40
43
|
}
|
|
41
44
|
});
|
|
42
45
|
|
|
46
|
+
GA_FEATURES.forEach((gaKey) => {
|
|
47
|
+
labs[gaKey] = true;
|
|
48
|
+
});
|
|
49
|
+
|
|
43
50
|
labs.members = settingsCache.get('members_signup_access') !== 'none';
|
|
44
51
|
|
|
45
52
|
return labs;
|
|
@@ -79,7 +86,7 @@ module.exports.enabledHelper = function enabledHelper(options, callback) {
|
|
|
79
86
|
}
|
|
80
87
|
|
|
81
88
|
// Else, the helper is not active and we need to handle this as an error
|
|
82
|
-
errDetails.message = tpl(options.errorMessage || messages.errorMessage, {helperName: options.helperName})
|
|
89
|
+
errDetails.message = tpl(options.errorMessage || messages.errorMessage, {helperName: options.helperName});
|
|
83
90
|
errDetails.context = tpl(options.errorContext || messages.errorContext, {
|
|
84
91
|
helperName: options.helperName,
|
|
85
92
|
flagName: options.flagName
|
|
@@ -88,6 +95,7 @@ module.exports.enabledHelper = function enabledHelper(options, callback) {
|
|
|
88
95
|
|
|
89
96
|
logging.error(new errors.DisabledFeatureError(errDetails));
|
|
90
97
|
|
|
98
|
+
const {SafeString} = require('express-hbs');
|
|
91
99
|
errString = new SafeString(`<script>console.error("${_.values(errDetails).join(' ')}");</script>`);
|
|
92
100
|
|
|
93
101
|
if (options.async) {
|
package/loggingrc.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const config = require('./core/shared/config');
|
|
2
|
+
const ghostVersion = require('@tryghost/version');
|
|
2
3
|
|
|
3
4
|
module.exports = {
|
|
4
5
|
name: config.get('logging:name'),
|
|
@@ -8,6 +9,15 @@ module.exports = {
|
|
|
8
9
|
mode: config.get('logging:mode'),
|
|
9
10
|
level: config.get('logging:level'),
|
|
10
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
|
+
},
|
|
11
21
|
gelf: config.get('logging:gelf'),
|
|
12
22
|
loggly: config.get('logging:loggly'),
|
|
13
23
|
elasticsearch: config.get('logging:elasticsearch'),
|