ghost 5.87.1 → 5.87.3
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/components/tryghost-adapter-cache-memory-ttl-5.87.3.tgz +0 -0
- package/components/tryghost-adapter-cache-redis-5.87.3.tgz +0 -0
- package/components/{tryghost-adapter-manager-5.87.1.tgz → tryghost-adapter-manager-5.87.3.tgz} +0 -0
- package/components/{tryghost-announcement-bar-settings-5.87.1.tgz → tryghost-announcement-bar-settings-5.87.3.tgz} +0 -0
- package/components/{tryghost-api-framework-5.87.1.tgz → tryghost-api-framework-5.87.3.tgz} +0 -0
- package/components/{tryghost-api-version-compatibility-service-5.87.1.tgz → tryghost-api-version-compatibility-service-5.87.3.tgz} +0 -0
- package/components/tryghost-audience-feedback-5.87.3.tgz +0 -0
- package/components/tryghost-bookshelf-repository-5.87.3.tgz +0 -0
- package/components/{tryghost-bootstrap-socket-5.87.1.tgz → tryghost-bootstrap-socket-5.87.3.tgz} +0 -0
- package/components/tryghost-collections-5.87.3.tgz +0 -0
- package/components/{tryghost-constants-5.87.1.tgz → tryghost-constants-5.87.3.tgz} +0 -0
- package/components/{tryghost-custom-theme-settings-service-5.87.1.tgz → tryghost-custom-theme-settings-service-5.87.3.tgz} +0 -0
- package/components/{tryghost-data-generator-5.87.1.tgz → tryghost-data-generator-5.87.3.tgz} +0 -0
- package/components/tryghost-domain-events-5.87.3.tgz +0 -0
- package/components/tryghost-donations-5.87.3.tgz +0 -0
- package/components/tryghost-dynamic-routing-events-5.87.3.tgz +0 -0
- package/components/tryghost-email-addresses-5.87.3.tgz +0 -0
- package/components/tryghost-email-analytics-provider-mailgun-5.87.3.tgz +0 -0
- package/components/{tryghost-email-analytics-service-5.87.1.tgz → tryghost-email-analytics-service-5.87.3.tgz} +0 -0
- package/components/tryghost-email-content-generator-5.87.3.tgz +0 -0
- package/components/{tryghost-email-events-5.87.1.tgz → tryghost-email-events-5.87.3.tgz} +0 -0
- package/components/tryghost-email-service-5.87.3.tgz +0 -0
- package/components/tryghost-email-suppression-list-5.87.3.tgz +0 -0
- package/components/tryghost-express-dynamic-redirects-5.87.3.tgz +0 -0
- package/components/tryghost-external-media-inliner-5.87.3.tgz +0 -0
- package/components/tryghost-extract-api-key-5.87.3.tgz +0 -0
- package/components/tryghost-ghost-5.87.3.tgz +0 -0
- package/components/tryghost-html-to-plaintext-5.87.3.tgz +0 -0
- package/components/tryghost-i18n-5.87.3.tgz +0 -0
- package/components/tryghost-importer-handler-content-files-5.87.3.tgz +0 -0
- package/components/{tryghost-importer-revue-5.87.1.tgz → tryghost-importer-revue-5.87.3.tgz} +0 -0
- package/components/tryghost-in-memory-repository-5.87.3.tgz +0 -0
- package/components/{tryghost-job-manager-5.87.1.tgz → tryghost-job-manager-5.87.3.tgz} +0 -0
- package/components/tryghost-link-redirects-5.87.3.tgz +0 -0
- package/components/tryghost-link-replacer-5.87.3.tgz +0 -0
- package/components/{tryghost-link-tracking-5.87.1.tgz → tryghost-link-tracking-5.87.3.tgz} +0 -0
- package/components/{tryghost-magic-link-5.87.1.tgz → tryghost-magic-link-5.87.3.tgz} +0 -0
- package/components/tryghost-mail-events-5.87.3.tgz +0 -0
- package/components/tryghost-mailgun-client-5.87.3.tgz +0 -0
- package/components/{tryghost-member-attribution-5.87.1.tgz → tryghost-member-attribution-5.87.3.tgz} +0 -0
- package/components/tryghost-member-events-5.87.3.tgz +0 -0
- package/components/tryghost-members-api-5.87.3.tgz +0 -0
- package/components/tryghost-members-csv-5.87.3.tgz +0 -0
- package/components/tryghost-members-events-service-5.87.3.tgz +0 -0
- package/components/{tryghost-members-importer-5.87.1.tgz → tryghost-members-importer-5.87.3.tgz} +0 -0
- package/components/{tryghost-members-offers-5.87.1.tgz → tryghost-members-offers-5.87.3.tgz} +0 -0
- package/components/{tryghost-members-payments-5.87.1.tgz → tryghost-members-payments-5.87.3.tgz} +0 -0
- package/components/{tryghost-members-ssr-5.87.1.tgz → tryghost-members-ssr-5.87.3.tgz} +0 -0
- package/components/tryghost-members-stripe-service-5.87.3.tgz +0 -0
- package/components/{tryghost-mentions-email-report-5.87.1.tgz → tryghost-mentions-email-report-5.87.3.tgz} +0 -0
- package/components/tryghost-milestones-5.87.3.tgz +0 -0
- package/components/{tryghost-minifier-5.87.1.tgz → tryghost-minifier-5.87.3.tgz} +0 -0
- package/components/tryghost-model-to-domain-event-interceptor-5.87.3.tgz +0 -0
- package/components/tryghost-mw-api-version-mismatch-5.87.3.tgz +0 -0
- package/components/tryghost-mw-cache-control-5.87.3.tgz +0 -0
- package/components/{tryghost-mw-error-handler-5.87.1.tgz → tryghost-mw-error-handler-5.87.3.tgz} +0 -0
- package/components/tryghost-mw-session-from-token-5.87.3.tgz +0 -0
- package/components/tryghost-mw-update-user-last-seen-5.87.3.tgz +0 -0
- package/components/tryghost-mw-version-match-5.87.3.tgz +0 -0
- package/components/tryghost-mw-vhost-5.87.3.tgz +0 -0
- package/components/tryghost-nql-filter-expansions-5.87.3.tgz +0 -0
- package/components/tryghost-oembed-service-5.87.3.tgz +0 -0
- package/components/{tryghost-package-json-5.87.1.tgz → tryghost-package-json-5.87.3.tgz} +0 -0
- package/components/tryghost-post-events-5.87.3.tgz +0 -0
- package/components/tryghost-post-revisions-5.87.3.tgz +0 -0
- package/components/{tryghost-posts-service-5.87.1.tgz → tryghost-posts-service-5.87.3.tgz} +0 -0
- package/components/tryghost-recommendations-5.87.3.tgz +0 -0
- package/components/tryghost-referrers-5.87.3.tgz +0 -0
- package/components/{tryghost-security-5.87.1.tgz → tryghost-security-5.87.3.tgz} +0 -0
- package/components/{tryghost-session-service-5.87.1.tgz → tryghost-session-service-5.87.3.tgz} +0 -0
- package/components/tryghost-settings-path-manager-5.87.3.tgz +0 -0
- package/components/{tryghost-slack-notifications-5.87.1.tgz → tryghost-slack-notifications-5.87.3.tgz} +0 -0
- package/components/{tryghost-staff-service-5.87.1.tgz → tryghost-staff-service-5.87.3.tgz} +0 -0
- package/components/{tryghost-stats-service-5.87.1.tgz → tryghost-stats-service-5.87.3.tgz} +0 -0
- package/components/{tryghost-tiers-5.87.1.tgz → tryghost-tiers-5.87.3.tgz} +0 -0
- package/components/{tryghost-update-check-service-5.87.1.tgz → tryghost-update-check-service-5.87.3.tgz} +0 -0
- package/components/tryghost-verification-trigger-5.87.3.tgz +0 -0
- package/components/tryghost-version-notifications-data-service-5.87.3.tgz +0 -0
- package/components/tryghost-webmentions-5.87.3.tgz +0 -0
- 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/screen.css +2 -0
- package/content/themes/casper/package.json +1 -1
- package/content/themes/source/assets/built/screen.css +1 -1
- package/content/themes/source/assets/built/screen.css.map +1 -1
- package/content/themes/source/assets/css/screen.css +1 -0
- package/content/themes/source/package.json +1 -1
- package/core/built/admin/assets/admin-x-activitypub/admin-x-activitypub.js +2 -2
- package/core/built/admin/assets/admin-x-activitypub/{index-9a6a8e4b.mjs → index-b4a353e7.mjs} +4481 -4431
- package/core/built/admin/assets/admin-x-activitypub/{modals-5aad7e41.mjs → modals-f64a65f9.mjs} +213 -215
- package/core/built/admin/assets/admin-x-demo/admin-x-demo.js +2 -2
- package/core/built/admin/assets/admin-x-demo/{index-f1fae1e6.mjs → index-5e68f89b.mjs} +4 -4
- package/core/built/admin/assets/admin-x-demo/{modals-344029a3.mjs → modals-f789a6c4.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{CodeEditorView-1a93227f.mjs → CodeEditorView-e762149f.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-1caa03f1.mjs → index-b5d002c9.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-bb355172.mjs → index-e85d0dcf.mjs} +2441 -2441
- package/core/built/admin/assets/admin-x-settings/{modals-f496bf28.mjs → modals-ccd29d36.mjs} +278 -282
- package/core/built/admin/assets/{chunk.42.167fc5e3f3a1c1088f2e.js → chunk.42.0879e40a4de3db25b177.js} +6292 -6282
- package/core/built/admin/assets/{chunk.42.167fc5e3f3a1c1088f2e.js.LICENSE.txt → chunk.42.0879e40a4de3db25b177.js.LICENSE.txt} +1 -1
- package/core/built/admin/assets/{chunk.524.a032fbf6d6bbe20b0eb3.js → chunk.524.036bdde7e8805a7ab0a7.js} +5 -5
- package/core/built/admin/assets/{chunk.582.bc65953e4022c385c144.js → chunk.582.e06ceab285e98b1aa982.js} +6 -6
- package/core/built/admin/assets/{ghost-b645099f33022aa37d96a2be8d8ddad1.js → ghost-07422c98448d7259d957d65c6737a274.js} +371 -372
- package/core/built/admin/assets/{ghost-cc31d867156dbb76ec96cdd93bd39d36.css → ghost-cb98187b163a0d8b42d752ab890e039a.css} +1 -1
- package/core/built/admin/assets/{ghost-dark-69968977cce01f9101da418724176290.css → ghost-dark-0d78b0a11f5c2604992de20c1bfe396f.css} +1 -1
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +28961 -30084
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +176 -162
- package/core/built/admin/assets/{vendor-4e0f92ca2b1c0850606b912c70852e32.js → vendor-051d43ec47258b77ffd2fcc21a6d8c50.js} +64 -63
- package/core/built/admin/index.html +6 -6
- package/core/frontend/services/routing/controllers/unsubscribe.js +1 -2
- package/core/frontend/src/cards/css/bookmark.css +1 -1
- package/core/frontend/src/member-attribution/member-attribution.js +15 -1
- package/core/server/data/importer/importers/data/ProductsImporter.js +18 -0
- package/core/server/lib/image/ImageSize.js +15 -3
- package/core/server/lib/image/ImageUtils.js +2 -1
- package/core/server/services/custom-redirects/CustomRedirectsAPI.js +3 -4
- package/core/server/services/custom-redirects/validation.js +3 -21
- package/core/server/services/recommendations/RecommendationServiceWrapper.js +6 -11
- package/core/shared/labs.js +0 -4
- package/package.json +152 -153
- package/yarn.lock +955 -434
- package/components/tryghost-adapter-cache-memory-ttl-5.87.1.tgz +0 -0
- package/components/tryghost-adapter-cache-redis-5.87.1.tgz +0 -0
- package/components/tryghost-audience-feedback-5.87.1.tgz +0 -0
- package/components/tryghost-bookshelf-repository-5.87.1.tgz +0 -0
- package/components/tryghost-collections-5.87.1.tgz +0 -0
- package/components/tryghost-domain-events-5.87.1.tgz +0 -0
- package/components/tryghost-donations-5.87.1.tgz +0 -0
- package/components/tryghost-dynamic-routing-events-5.87.1.tgz +0 -0
- package/components/tryghost-email-addresses-5.87.1.tgz +0 -0
- package/components/tryghost-email-analytics-provider-mailgun-5.87.1.tgz +0 -0
- package/components/tryghost-email-content-generator-5.87.1.tgz +0 -0
- package/components/tryghost-email-service-5.87.1.tgz +0 -0
- package/components/tryghost-email-suppression-list-5.87.1.tgz +0 -0
- package/components/tryghost-express-dynamic-redirects-5.87.1.tgz +0 -0
- package/components/tryghost-external-media-inliner-5.87.1.tgz +0 -0
- package/components/tryghost-extract-api-key-5.87.1.tgz +0 -0
- package/components/tryghost-ghost-5.87.1.tgz +0 -0
- package/components/tryghost-html-to-plaintext-5.87.1.tgz +0 -0
- package/components/tryghost-i18n-5.87.1.tgz +0 -0
- package/components/tryghost-importer-handler-content-files-5.87.1.tgz +0 -0
- package/components/tryghost-in-memory-repository-5.87.1.tgz +0 -0
- package/components/tryghost-link-redirects-5.87.1.tgz +0 -0
- package/components/tryghost-link-replacer-5.87.1.tgz +0 -0
- package/components/tryghost-mail-events-5.87.1.tgz +0 -0
- package/components/tryghost-mailgun-client-5.87.1.tgz +0 -0
- package/components/tryghost-member-events-5.87.1.tgz +0 -0
- package/components/tryghost-members-api-5.87.1.tgz +0 -0
- package/components/tryghost-members-csv-5.87.1.tgz +0 -0
- package/components/tryghost-members-events-service-5.87.1.tgz +0 -0
- package/components/tryghost-members-stripe-service-5.87.1.tgz +0 -0
- package/components/tryghost-milestones-5.87.1.tgz +0 -0
- package/components/tryghost-model-to-domain-event-interceptor-5.87.1.tgz +0 -0
- package/components/tryghost-mw-api-version-mismatch-5.87.1.tgz +0 -0
- package/components/tryghost-mw-cache-control-5.87.1.tgz +0 -0
- package/components/tryghost-mw-session-from-token-5.87.1.tgz +0 -0
- package/components/tryghost-mw-update-user-last-seen-5.87.1.tgz +0 -0
- package/components/tryghost-mw-version-match-5.87.1.tgz +0 -0
- package/components/tryghost-mw-vhost-5.87.1.tgz +0 -0
- package/components/tryghost-nql-filter-expansions-5.87.1.tgz +0 -0
- package/components/tryghost-oembed-service-5.87.1.tgz +0 -0
- package/components/tryghost-post-events-5.87.1.tgz +0 -0
- package/components/tryghost-post-revisions-5.87.1.tgz +0 -0
- package/components/tryghost-recommendations-5.87.1.tgz +0 -0
- package/components/tryghost-referrers-5.87.1.tgz +0 -0
- package/components/tryghost-settings-path-manager-5.87.1.tgz +0 -0
- package/components/tryghost-verification-trigger-5.87.1.tgz +0 -0
- package/components/tryghost-version-notifications-data-service-5.87.1.tgz +0 -0
- package/components/tryghost-webmentions-5.87.1.tgz +0 -0
|
@@ -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%22cdnUrl%22%3A%22%22%2C%22editorUrl%22%3A%22%22%2C%22rootURL%22%3A%22%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%225.87%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%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%2C%22editorFilename%22%3A%22koenig-lexical.umd.js%22%2C%22editorHash%22%3A%
|
|
11
|
+
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22cdnUrl%22%3A%22%22%2C%22editorUrl%22%3A%22%22%2C%22rootURL%22%3A%22%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%225.87%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%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%2C%22editorFilename%22%3A%22koenig-lexical.umd.js%22%2C%22editorHash%22%3A%2208854be47b%22%2C%22adminXDemoFilename%22%3A%22admin-x-demo.js%22%2C%22adminXDemoHash%22%3A%220539de3930%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%22e8dff6adeb%22%2C%22adminXActivitypubFilename%22%3A%22admin-x-activitypub.js%22%2C%22adminXActivitypubHash%22%3A%22a94b140a1a%22%7D" />
|
|
12
12
|
|
|
13
13
|
<meta name="HandheldFriendly" content="True" />
|
|
14
14
|
<meta name="MobileOptimized" content="320" />
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
</style>
|
|
38
38
|
|
|
39
39
|
<link integrity="" rel="stylesheet" href="assets/vendor-0ede59da8efb5e28fa929557f7ff7154.css">
|
|
40
|
-
<link integrity="" rel="stylesheet" href="assets/ghost-
|
|
40
|
+
<link integrity="" rel="stylesheet" href="assets/ghost-cb98187b163a0d8b42d752ab890e039a.css" title="light">
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
</head>
|
|
@@ -56,9 +56,9 @@
|
|
|
56
56
|
|
|
57
57
|
<div id="ember-basic-dropdown-wormhole"></div>
|
|
58
58
|
|
|
59
|
-
<script src="assets/vendor-
|
|
60
|
-
<script src="assets/chunk.42.
|
|
61
|
-
<script src="assets/chunk.524.
|
|
62
|
-
<script src="assets/ghost-
|
|
59
|
+
<script src="assets/vendor-051d43ec47258b77ffd2fcc21a6d8c50.js"></script>
|
|
60
|
+
<script src="assets/chunk.42.0879e40a4de3db25b177.js"></script>
|
|
61
|
+
<script src="assets/chunk.524.036bdde7e8805a7ab0a7.js"></script>
|
|
62
|
+
<script src="assets/ghost-07422c98448d7259d957d65c6737a274.js"></script>
|
|
63
63
|
</body>
|
|
64
64
|
</html>
|
|
@@ -2,7 +2,6 @@ const debug = require('@tryghost/debug')('services:routing:controllers:unsubscri
|
|
|
2
2
|
const url = require('url');
|
|
3
3
|
const members = require('../../../../server/services/members');
|
|
4
4
|
const urlUtils = require('../../../../shared/url-utils');
|
|
5
|
-
const labs = require('../../../../shared/labs');
|
|
6
5
|
const logging = require('@tryghost/logging');
|
|
7
6
|
|
|
8
7
|
module.exports = async function unsubscribeController(req, res) {
|
|
@@ -15,7 +14,7 @@ module.exports = async function unsubscribeController(req, res) {
|
|
|
15
14
|
return res.end('Email address not found.');
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
if (req.method === 'POST'
|
|
17
|
+
if (req.method === 'POST') {
|
|
19
18
|
logging.info('[List-Unsubscribe] Received POST unsubscribe for ' + query.uuid + ', newsletter: ' + (query.newsletter ?? 'null') + ', comments: ' + (query.comments ?? 'false'));
|
|
20
19
|
|
|
21
20
|
// Do an actual unsubscribe
|
|
@@ -76,6 +76,8 @@ const LIMIT = 15;
|
|
|
76
76
|
let sourceParam;
|
|
77
77
|
let utmSourceParam;
|
|
78
78
|
let utmMediumParam;
|
|
79
|
+
let referrerSource;
|
|
80
|
+
|
|
79
81
|
try {
|
|
80
82
|
// Fetch source/medium from query param
|
|
81
83
|
const url = new URL(window.location.href);
|
|
@@ -83,11 +85,23 @@ const LIMIT = 15;
|
|
|
83
85
|
sourceParam = url.searchParams.get('source');
|
|
84
86
|
utmSourceParam = url.searchParams.get('utm_source');
|
|
85
87
|
utmMediumParam = url.searchParams.get('utm_medium');
|
|
88
|
+
|
|
89
|
+
referrerSource = refParam || sourceParam || utmSourceParam || null;
|
|
90
|
+
|
|
91
|
+
// if referrerSource is not set, check to see if the url contains a hash like ghost.org/#/portal/signup?ref=ghost and pull the ref from the hash
|
|
92
|
+
if (!referrerSource && url.hash && url.hash.includes('#/portal')) {
|
|
93
|
+
const hashUrl = new URL(window.location.href.replace('/#/portal', ''));
|
|
94
|
+
refParam = hashUrl.searchParams.get('ref');
|
|
95
|
+
sourceParam = hashUrl.searchParams.get('source');
|
|
96
|
+
utmSourceParam = hashUrl.searchParams.get('utm_source');
|
|
97
|
+
utmMediumParam = hashUrl.searchParams.get('utm_medium');
|
|
98
|
+
|
|
99
|
+
referrerSource = refParam || sourceParam || utmSourceParam || null;
|
|
100
|
+
}
|
|
86
101
|
} catch (e) {
|
|
87
102
|
console.error('[Member Attribution] Parsing referrer from querystring failed', e);
|
|
88
103
|
}
|
|
89
104
|
|
|
90
|
-
const referrerSource = refParam || sourceParam || utmSourceParam || null;
|
|
91
105
|
const referrerMedium = utmMediumParam || null;
|
|
92
106
|
const referrerUrl = window.document.referrer || null;
|
|
93
107
|
|
|
@@ -122,8 +122,26 @@ class ProductsImporter extends BaseImporter {
|
|
|
122
122
|
this.dataToImport = this.dataToImport.filter(item => !duplicateProducts.includes(item.id));
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
preventInvalidFree() {
|
|
126
|
+
let invalidFreeProducts = [];
|
|
127
|
+
_.each(this.dataToImport, (product) => {
|
|
128
|
+
// A free product must not have any pricing data (otherwise it wouldn't be free, duh!)
|
|
129
|
+
if (product.type === 'free' && product.currency && product.monthly_price && product.yearly_price) {
|
|
130
|
+
this.problems.push({
|
|
131
|
+
message: 'Entry was not imported and ignored. Detected invalid entry.',
|
|
132
|
+
help: this.modelName,
|
|
133
|
+
context: JSON.stringify({product})
|
|
134
|
+
});
|
|
135
|
+
invalidFreeProducts.push(product.id);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
// ignore invalid free products
|
|
139
|
+
this.dataToImport = this.dataToImport.filter(item => !invalidFreeProducts.includes(item.id));
|
|
140
|
+
}
|
|
141
|
+
|
|
125
142
|
beforeImport() {
|
|
126
143
|
this.populatePriceData();
|
|
144
|
+
this.preventInvalidFree();
|
|
127
145
|
return super.beforeImport();
|
|
128
146
|
}
|
|
129
147
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const debug = require('@tryghost/debug')('utils:image-size');
|
|
2
2
|
const sizeOf = require('image-size');
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
const url = require('url');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const _ = require('lodash');
|
|
@@ -17,13 +17,14 @@ const FETCH_ONLY_FORMATS = [
|
|
|
17
17
|
];
|
|
18
18
|
|
|
19
19
|
class ImageSize {
|
|
20
|
-
constructor({config, storage, storageUtils, validator, urlUtils, request}) {
|
|
20
|
+
constructor({config, storage, storageUtils, validator, urlUtils, request, probe}) {
|
|
21
21
|
this.config = config;
|
|
22
22
|
this.storage = storage;
|
|
23
23
|
this.storageUtils = storageUtils;
|
|
24
24
|
this.validator = validator;
|
|
25
25
|
this.urlUtils = urlUtils;
|
|
26
26
|
this.request = request;
|
|
27
|
+
this.probe = probe;
|
|
27
28
|
|
|
28
29
|
this.REQUEST_OPTIONS = {
|
|
29
30
|
// we need the user-agent, otherwise some https request may fail (e.g. cloudfare)
|
|
@@ -82,7 +83,18 @@ class ImageSize {
|
|
|
82
83
|
}));
|
|
83
84
|
}
|
|
84
85
|
|
|
85
|
-
|
|
86
|
+
// wrap probe-image-size in a promise in case it is unresponsive/the timeout itself doesn't work
|
|
87
|
+
return (Promise.race([
|
|
88
|
+
this.probe(imageUrl, this.NEEDLE_OPTIONS),
|
|
89
|
+
new Promise((res, rej) => {
|
|
90
|
+
setTimeout(() => {
|
|
91
|
+
rej(new errors.InternalServerError({
|
|
92
|
+
message: 'Probe unresponsive.',
|
|
93
|
+
code: 'IMAGE_SIZE_URL'
|
|
94
|
+
}));
|
|
95
|
+
}, this.NEEDLE_OPTIONS.response_timeout);
|
|
96
|
+
})
|
|
97
|
+
]));
|
|
86
98
|
}
|
|
87
99
|
|
|
88
100
|
// download full image then use image-size to get it's dimensions
|
|
@@ -2,11 +2,12 @@ const BlogIcon = require('./BlogIcon');
|
|
|
2
2
|
const CachedImageSizeFromUrl = require('./CachedImageSizeFromUrl');
|
|
3
3
|
const Gravatar = require('./Gravatar');
|
|
4
4
|
const ImageSize = require('./ImageSize');
|
|
5
|
+
const probe = require('probe-image-size');
|
|
5
6
|
|
|
6
7
|
class ImageUtils {
|
|
7
8
|
constructor({config, urlUtils, settingsCache, storageUtils, storage, validator, request, cacheStore}) {
|
|
8
9
|
this.blogIcon = new BlogIcon({config, urlUtils, settingsCache, storageUtils});
|
|
9
|
-
this.imageSize = new ImageSize({config, storage, storageUtils, validator, urlUtils, request});
|
|
10
|
+
this.imageSize = new ImageSize({config, storage, storageUtils, validator, urlUtils, request, probe});
|
|
10
11
|
this.cachedImageSizeFromUrl = new CachedImageSizeFromUrl({
|
|
11
12
|
getImageSizeFromUrl: this.imageSize.getImageSizeFromUrl.bind(this.imageSize),
|
|
12
13
|
cache: cacheStore
|
|
@@ -211,6 +211,9 @@ class CustomRedirectsAPI {
|
|
|
211
211
|
*/
|
|
212
212
|
async setFromFilePath(filePath, ext = '.json') {
|
|
213
213
|
const redirectsFilePath = await this.getRedirectsFilePath();
|
|
214
|
+
const content = await readRedirectsFile(filePath);
|
|
215
|
+
const parsed = parseRedirectsFile(content, ext);
|
|
216
|
+
this.validate(parsed);
|
|
214
217
|
|
|
215
218
|
if (redirectsFilePath) {
|
|
216
219
|
const backupRedirectsPath = this.getBackupFilePath(redirectsFilePath);
|
|
@@ -223,10 +226,6 @@ class CustomRedirectsAPI {
|
|
|
223
226
|
await fs.move(redirectsFilePath, backupRedirectsPath);
|
|
224
227
|
}
|
|
225
228
|
|
|
226
|
-
const content = await readRedirectsFile(filePath);
|
|
227
|
-
const parsed = parseRedirectsFile(content, ext);
|
|
228
|
-
this.validate(parsed);
|
|
229
|
-
|
|
230
229
|
if (ext === '.json') {
|
|
231
230
|
await fs.writeFile(this.createRedirectsFilePath('.json'), JSON.stringify(parsed), 'utf-8');
|
|
232
231
|
} else if (ext === '.yaml') {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
2
|
const tpl = require('@tryghost/tpl');
|
|
3
3
|
const errors = require('@tryghost/errors');
|
|
4
|
-
const {isSafePattern} = require('redos-detector');
|
|
5
4
|
|
|
6
5
|
const messages = {
|
|
7
6
|
redirectsWrongFormat: 'Incorrect redirects file format.',
|
|
@@ -34,35 +33,18 @@ const validate = (redirects) => {
|
|
|
34
33
|
if (!redirect.from || !redirect.to) {
|
|
35
34
|
throw new errors.ValidationError({
|
|
36
35
|
message: tpl(messages.redirectsWrongFormat),
|
|
36
|
+
context: redirect,
|
|
37
37
|
help: tpl(messages.redirectsHelp)
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
// Ensure valid regex
|
|
42
41
|
try {
|
|
42
|
+
// each 'from' property should be a valid RegExp string
|
|
43
43
|
new RegExp(redirect.from);
|
|
44
44
|
} catch (error) {
|
|
45
45
|
throw new errors.ValidationError({
|
|
46
46
|
message: tpl(messages.invalidRedirectsFromRegex),
|
|
47
|
-
|
|
48
|
-
redirect,
|
|
49
|
-
invalid: true
|
|
50
|
-
},
|
|
51
|
-
help: tpl(messages.redirectsHelp)
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Ensure safe regex
|
|
56
|
-
const analysis = isSafePattern(redirect.from);
|
|
57
|
-
|
|
58
|
-
if (analysis.safe === false) {
|
|
59
|
-
throw new errors.ValidationError({
|
|
60
|
-
message: tpl(messages.invalidRedirectsFromRegex),
|
|
61
|
-
errorDetails: {
|
|
62
|
-
redirect,
|
|
63
|
-
unsafe: true,
|
|
64
|
-
reason: analysis.error
|
|
65
|
-
},
|
|
47
|
+
context: redirect,
|
|
66
48
|
help: tpl(messages.redirectsHelp)
|
|
67
49
|
});
|
|
68
50
|
}
|
|
@@ -43,7 +43,6 @@ class RecommendationServiceWrapper {
|
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const labs = require('../../../shared/labs');
|
|
47
46
|
const config = require('../../../shared/config');
|
|
48
47
|
const urlUtils = require('../../../shared/url-utils');
|
|
49
48
|
const models = require('../../models');
|
|
@@ -146,10 +145,8 @@ class RecommendationServiceWrapper {
|
|
|
146
145
|
service: this.incomingRecommendationService
|
|
147
146
|
});
|
|
148
147
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
this.incomingRecommendationService.init().catch(logging.error);
|
|
152
|
-
}
|
|
148
|
+
this.service.init().catch(logging.error);
|
|
149
|
+
this.incomingRecommendationService.init().catch(logging.error);
|
|
153
150
|
|
|
154
151
|
const PATH_SUFFIX = '/.well-known/recommendations.json';
|
|
155
152
|
|
|
@@ -169,12 +166,10 @@ class RecommendationServiceWrapper {
|
|
|
169
166
|
|
|
170
167
|
// Listen for incoming webmentions
|
|
171
168
|
DomainEvents.subscribe(MentionCreatedEvent, async (event) => {
|
|
172
|
-
if
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
await this.incomingRecommendationService.sendRecommendationEmail(event.data.mention);
|
|
177
|
-
}
|
|
169
|
+
// Check if this is a recommendation
|
|
170
|
+
if (event.data.mention.verified && isRecommendationUrl(event.data.mention.source)) {
|
|
171
|
+
logging.info('[INCOMING RECOMMENDATION] Received recommendation from ' + event.data.mention.source);
|
|
172
|
+
await this.incomingRecommendationService.sendRecommendationEmail(event.data.mention);
|
|
178
173
|
}
|
|
179
174
|
});
|
|
180
175
|
}
|
package/core/shared/labs.js
CHANGED