ghost 5.119.3 → 5.120.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/components/tryghost-i18n-5.120.1.tgz +0 -0
- package/core/boot.js +0 -2
- package/core/built/admin/assets/admin-x-activitypub/admin-x-activitypub.js +7555 -7216
- package/core/built/admin/assets/admin-x-settings/{CodeEditorView-60ce658c.mjs → CodeEditorView-1c5b0683.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-8480baa8.mjs → index-14e518a7.mjs} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-a2648c61.mjs → index-fc9f985b.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{modals-6900c1d5.mjs → modals-15bc6a0f.mjs} +7192 -6656
- package/core/built/admin/assets/{chunk.137.c9bf40f01afeeadb4660.js → chunk.383.25fca2f09b4896656125.js} +76 -59
- package/core/built/admin/assets/chunk.524.24ab802c6c20f2da3449.js +28 -0
- package/core/built/admin/assets/{chunk.582.2697b46a5652693fc674.js → chunk.582.ebfc460cd2d6864d2cc9.js} +20 -27
- package/core/built/admin/assets/{ghost-843572e9507d099162ae744d791daba1.js → ghost-b3b44421acca3b3eec76bfbb6ba0e81b.js} +3 -3
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +12578 -12352
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +423 -211
- package/core/built/admin/assets/posts/posts.js +13680 -13671
- package/core/built/admin/assets/stats/stats.js +16457 -16635
- package/core/built/admin/assets/{vendor-8f805740fee4db959a5b2119001a56b1.js → vendor-4ce6d282a2a00fe486a0951e0591da19.js} +11 -9
- package/core/built/admin/index.html +5 -5
- package/core/frontend/helpers/match.js +6 -0
- package/core/frontend/services/routing/ParentRouter.js +1 -1
- package/core/frontend/services/routing/controllers/email-post.js +0 -2
- package/core/frontend/services/routing/controllers/previews.js +0 -3
- package/core/frontend/web/middleware/frontend-caching.js +2 -2
- package/core/server/api/endpoints/authentication.js +37 -73
- package/core/server/api/endpoints/authors-public.js +8 -9
- package/core/server/api/endpoints/db.js +34 -35
- package/core/server/api/endpoints/emails.js +8 -10
- package/core/server/api/endpoints/integrations.js +20 -18
- package/core/server/api/endpoints/invites.js +8 -10
- package/core/server/api/endpoints/labels.js +19 -23
- package/core/server/api/endpoints/notifications.js +3 -4
- package/core/server/api/endpoints/pages-public.js +8 -10
- package/core/server/api/endpoints/pages.js +14 -18
- package/core/server/api/endpoints/posts-public.js +8 -10
- package/core/server/api/endpoints/posts.js +6 -8
- package/core/server/api/endpoints/previews.js +8 -10
- package/core/server/api/endpoints/redirects.js +7 -8
- package/core/server/api/endpoints/schedules.js +5 -7
- package/core/server/api/endpoints/slugs.js +7 -9
- package/core/server/api/endpoints/snippets.js +16 -20
- package/core/server/api/endpoints/tags-public.js +8 -10
- package/core/server/api/endpoints/tags.js +19 -23
- package/core/server/api/endpoints/themes.js +6 -8
- package/core/server/api/endpoints/users.js +31 -36
- package/core/server/api/endpoints/utils/permissions.js +10 -10
- package/core/server/api/endpoints/utils/serializers/output/roles.js +9 -10
- package/core/server/api/endpoints/utils/validators/input/images.js +43 -52
- package/core/server/api/endpoints/utils/validators/input/invites.js +6 -8
- package/core/server/api/endpoints/webhooks.js +38 -42
- package/core/server/data/migrations/versions/5.120/2025-05-07-14-57-38-add-newsletters-button-corners-column.js +8 -0
- package/core/server/data/migrations/versions/5.120/2025-05-13-17-36-56-add-newsletters-button-style-column.js +8 -0
- package/core/server/data/migrations/versions/5.120/2025-05-14-20-00-15-add-newsletters-setting-columns.js +22 -0
- package/core/server/data/schema/schema.js +6 -1
- package/core/server/lib/image/Gravatar.js +12 -13
- package/core/server/lib/lexical.js +3 -1
- package/core/server/models/newsletter.js +6 -1
- package/core/server/services/api-version-compatibility/index.js +1 -33
- package/core/server/services/auth/session/emails/signin.js +3 -3
- package/core/server/services/email-address/EmailAddressParser.js +70 -0
- package/core/server/services/email-address/EmailAddressParser.js.d.ts +13 -0
- package/core/server/services/email-address/EmailAddressService.js +142 -0
- package/core/server/services/email-address/EmailAddressService.ts +183 -0
- package/core/server/services/email-address/EmailAddressServiceWrapper.js +2 -4
- package/core/server/services/email-analytics/EmailAnalyticsService.js +1 -1
- package/core/server/services/email-analytics/EmailAnalyticsServiceWrapper.js +2 -1
- package/core/server/services/email-service/BatchSendingService.js +703 -0
- package/core/server/services/email-service/EmailBodyCache.js +20 -0
- package/core/server/services/email-service/EmailController.js +94 -0
- package/core/server/services/email-service/EmailEventProcessor.js +267 -0
- package/core/server/services/email-service/EmailEventStorage.js +187 -0
- package/core/server/services/email-service/EmailRenderer.js +1263 -0
- package/core/server/services/email-service/EmailSegmenter.js +74 -0
- package/core/server/services/email-service/EmailService.js +310 -0
- package/core/server/services/email-service/EmailServiceWrapper.js +9 -2
- package/core/server/services/email-service/MailgunEmailProvider.js +191 -0
- package/core/server/services/email-service/SendingService.js +173 -0
- package/core/server/services/email-service/email-templates/partials/feedback-button.hbs +7 -0
- package/core/server/services/email-service/email-templates/partials/latest-posts.hbs +39 -0
- package/core/server/services/email-service/email-templates/partials/paywall.hbs +20 -0
- package/core/server/services/email-service/email-templates/partials/styles.hbs +2348 -0
- package/core/server/services/email-service/email-templates/template.hbs +238 -0
- package/core/server/services/email-service/events/EmailBouncedEvent.js +63 -0
- package/core/server/services/email-service/events/EmailDeliveredEvent.js +49 -0
- package/core/server/services/email-service/events/EmailOpenedEvent.js +49 -0
- package/core/server/services/email-service/events/EmailTemporaryBouncedEvent.js +63 -0
- package/core/server/services/email-service/events/EmailUnsubscribedEvent.js +42 -0
- package/core/server/services/email-service/events/SpamComplaintEvent.js +42 -0
- package/core/server/services/email-service/helpers/register-helpers.js +59 -0
- package/core/server/services/email-suppression-list/MailgunEmailSuppressionList.js +2 -1
- package/core/server/services/explore-ping/index.js +2 -1
- package/core/server/services/mail/GhostMailer.js +1 -1
- package/core/server/services/media-inliner/ExternalMediaInliner.js +2 -1
- package/core/server/services/members/api.js +15 -15
- package/core/server/services/members/emails/signin.js +4 -4
- package/core/server/services/members/emails/signup-paid.js +3 -4
- package/core/server/services/members/emails/signup.js +3 -3
- package/core/server/services/members/emails/subscribe.js +3 -3
- package/core/server/services/members/members-api/repositories/MemberRepository.js +92 -92
- package/core/server/services/members-events/LastSeenAtUpdater.js +1 -1
- package/core/server/services/settings-helpers/SettingsHelpers.js +1 -1
- package/core/server/services/staff/StaffServiceEmails.js +1 -1
- package/core/server/services/stats/PostsStatsService.js +28 -7
- package/core/server/web/api/app.js +0 -1
- package/core/server/web/api/endpoints/admin/app.js +0 -2
- package/core/server/web/api/endpoints/content/app.js +0 -2
- package/core/server/web/api/middleware/upload.js +2 -2
- package/core/shared/custom-theme-settings-cache/CustomThemeSettingsService.js +2 -1
- package/package.json +39 -97
- package/tsconfig.tsbuildinfo +1 -1
- package/yarn.lock +385 -517
- package/components/tryghost-api-framework-5.119.3.tgz +0 -0
- package/components/tryghost-custom-fonts-5.119.3.tgz +0 -0
- package/components/tryghost-domain-events-5.119.3.tgz +0 -0
- package/components/tryghost-email-addresses-5.119.3.tgz +0 -0
- package/components/tryghost-email-service-5.119.3.tgz +0 -0
- package/components/tryghost-html-to-plaintext-5.119.3.tgz +0 -0
- package/components/tryghost-i18n-5.119.3.tgz +0 -0
- package/components/tryghost-job-manager-5.119.3.tgz +0 -0
- package/components/tryghost-members-csv-5.119.3.tgz +0 -0
- package/components/tryghost-mw-error-handler-5.119.3.tgz +0 -0
- package/components/tryghost-mw-vhost-5.119.3.tgz +0 -0
- package/components/tryghost-prometheus-metrics-5.119.3.tgz +0 -0
- package/components/tryghost-security-5.119.3.tgz +0 -0
- package/core/built/admin/assets/chunk.524.c86e2e1b3e94d7cb1e4c.js +0 -35
- package/core/server/services/api-version-compatibility/APIVersionCompatibilityService.js +0 -99
- package/core/server/services/api-version-compatibility/VersionNotificationsDataService.js +0 -80
- package/core/server/services/api-version-compatibility/extract-api-key.js +0 -57
- package/core/server/services/api-version-compatibility/mw-api-version-mismatch.js +0 -31
- /package/core/built/admin/assets/{chunk.137.c9bf40f01afeeadb4660.js.LICENSE.txt → chunk.383.25fca2f09b4896656125.js.LICENSE.txt} +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
var __ember_auto_import__;(()=>{var e,r={9589:(e,r,t)=>{const n=t(68125),s=t(78695),o=["id","email","name","note","subscribed_to_emails","complimentary_plan","stripe_customer_id","created_at","deleted_at","labels","tiers"]
|
|
2
|
-
e.exports=(e,r=o.slice())=>{r=r.map((e=>"subscribed"===e?"subscribed_to_emails":e))
|
|
3
|
-
const t=e.map((e=>{e.error&&!r.includes("error")&&r.push("error")
|
|
4
|
-
let t=""
|
|
5
|
-
"string"==typeof e.labels?t=e.labels:Array.isArray(e.labels)&&(t=e.labels.map((e=>"string"==typeof e?e:e.name)).join(","))
|
|
6
|
-
let s=""
|
|
7
|
-
return Array.isArray(e.tiers)&&(s=e.tiers.map((e=>e.name)).join(",")),{id:e.id,email:e.email,name:e.name,note:e.note,subscribed_to_emails:"subscribed"in e?e.subscribed:e.subscribed_to_emails,complimentary_plan:e.comped||e.complimentary_plan,stripe_customer_id:n.get(e,"subscriptions[0].customer.id")||e.stripe_customer_id,created_at:e.created_at,deleted_at:e.deleted_at,labels:t,tiers:s,import_tier:e.import_tier||null,error:e.error||null}}))
|
|
8
|
-
return s.unparse(t,{escapeFormulae:!0,columns:r})}},31048:()=>{},32186:e=>{"use strict"
|
|
9
|
-
e.exports=require("@ember/test-waiters")},54571:(e,r,t)=>{e.exports=function(){var e=_eai_d,r=_eai_r
|
|
10
|
-
function n(e){return e&&e.__esModule?e:Object.assign({default:e},e)}window.emberAutoImportDynamic=function(e){return 1===arguments.length?r("_eai_dyn_"+e):r("_eai_dynt_"+e)(Array.prototype.slice.call(arguments,1))},window.emberAutoImportSync=function(e){return r("_eai_sync_"+e)(Array.prototype.slice.call(arguments,1))},e("@sentry/browser",[],(function(){return n(t(51294))})),e("@sentry/core",[],(function(){return n(t(16154))})),e("@sentry/integrations",[],(function(){return n(t(20080))})),e("@sentry/replay",[],(function(){return n(t(51633))})),e("@sentry/utils",[],(function(){return n(t(88414))})),e("@tryghost/color-utils",[],(function(){return n(t(86797))})),e("@tryghost/kg-clean-basic-html",[],(function(){return n(t(56035))})),e("@tryghost/kg-converters",[],(function(){return n(t(23075))})),e("@tryghost/limit-service",[],(function(){return n(t(55983))})),e("@tryghost/members-csv/lib/unparse",[],(function(){return n(t(9589))})),e("@tryghost/nql",[],(function(){return n(t(39365))})),e("@tryghost/nql-lang",[],(function(){return n(t(716))})),e("@tryghost/string",[],(function(){return n(t(96107))})),e("@tryghost/timezone-data",[],(function(){return n(t(27019))})),e("animejs/lib/anime.es.js",[],(function(){return n(t(62282))})),e("element-resize-detector",[],(function(){return n(t(29540))})),e("ember-assign-helper/helpers/assign",[],(function(){return n(t(31113))})),e("ember-css-transitions/modifiers/css-transition",["@ember/test-waiters"],(function(){return n(t(95895))})),e("ember-keyboard/helpers/if-key.js",[],(function(){return n(t(10530))})),e("ember-keyboard/helpers/on-key.js",[],(function(){return n(t(13692))})),e("ember-keyboard/modifiers/on-key.js",[],(function(){return n(t(40985))})),e("ember-keyboard/services/keyboard.js",[],(function(){return n(t(89697))})),e("ember-modifier",[],(function(){return n(t(37777))})),e("ember-moment/helpers/-base",[],(function(){return n(t(91366))})),e("ember-moment/helpers/is-after",[],(function(){return n(t(91461))})),e("ember-moment/helpers/is-before",[],(function(){return n(t(61e3))})),e("ember-moment/helpers/is-between",[],(function(){return n(t(447))})),e("ember-moment/helpers/is-same",[],(function(){return n(t(64193))})),e("ember-moment/helpers/is-same-or-after",[],(function(){return n(t(7916))})),e("ember-moment/helpers/is-same-or-before",[],(function(){return n(t(54351))})),e("ember-moment/helpers/moment",[],(function(){return n(t(41678))})),e("ember-moment/helpers/moment-add",[],(function(){return n(t(50080))})),e("ember-moment/helpers/moment-calendar",[],(function(){return n(t(96625))})),e("ember-moment/helpers/moment-diff",[],(function(){return n(t(85340))})),e("ember-moment/helpers/moment-duration",[],(function(){return n(t(42967))})),e("ember-moment/helpers/moment-format",[],(function(){return n(t(10536))})),e("ember-moment/helpers/moment-from",[],(function(){return n(t(50727))})),e("ember-moment/helpers/moment-from-now",[],(function(){return n(t(706))})),e("ember-moment/helpers/moment-subtract",[],(function(){return n(t(54651))})),e("ember-moment/helpers/moment-to",[],(function(){return n(t(84818))})),e("ember-moment/helpers/moment-to-date",[],(function(){return n(t(81183))})),e("ember-moment/helpers/moment-to-now",[],(function(){return n(t(17083))})),e("ember-moment/helpers/now",[],(function(){return n(t(34980))})),e("ember-moment/helpers/unix",[],(function(){return n(t(79272))})),e("ember-moment/helpers/utc",[],(function(){return n(t(36022))})),e("ember-moment/services/moment",[],(function(){return n(t(39879))})),e("fast-deep-equal",[],(function(){return n(t(25383))})),e("flexsearch",[],(function(){return n(t(12248))})),e("focus-trap",[],(function(){return n(t(39632))})),e("intersection-observer-admin",[],(function(){return n(t(21431))})),e("jose",[],(function(){return n(t(82765))})),e("microdiff",[],(function(){return n(t(59086))})),e("moment-timezone",[],(function(){return n(t(41101))})),e("papaparse",[],(function(){return n(t(78695))})),e("raf-pool",[],(function(){return n(t(60695))})),e("react",[],(function(){return n(t(72854))})),e("react-dom",[],(function(){return n(t(95303))})),e("react-dom/client",[],(function(){return n(t(70816))})),e("semver/functions/coerce",[],(function(){return n(t(18576))})),e("semver/functions/lt",[],(function(){return n(t(32817))})),e("semver/functions/parse",[],(function(){return n(t(47898))})),e("tooltip.js",[],(function(){return n(t(85557))})),e("tracked-built-ins",["ember-tracked-storage-polyfill"],(function(){return n(t(67708))})),e("validator",[],(function(){return n(t(26058))})),e("_eai_dyn_@sentry/browser",[],(function(){return Promise.resolve().then(t.bind(t,51294))}))}()},56857:(e,r,t)=>{var n={"./af":58547,"./af.js":58547,"./ar":28167,"./ar-dz":35298,"./ar-dz.js":35298,"./ar-kw":11314,"./ar-kw.js":11314,"./ar-ly":66455,"./ar-ly.js":66455,"./ar-ma":15998,"./ar-ma.js":15998,"./ar-sa":55388,"./ar-sa.js":55388,"./ar-tn":73358,"./ar-tn.js":73358,"./ar.js":28167,"./az":92367,"./az.js":92367,"./be":9161,"./be.js":9161,"./bg":359,"./bg.js":359,"./bm":32625,"./bm.js":32625,"./bn":52984,"./bn.js":52984,"./bo":87343,"./bo.js":87343,"./br":87948,"./br.js":87948,"./bs":88211,"./bs.js":88211,"./ca":34700,"./ca.js":34700,"./cs":27430,"./cs.js":27430,"./cv":55913,"./cv.js":55913,"./cy":16004,"./cy.js":16004,"./da":26839,"./da.js":26839,"./de":22131,"./de-at":6729,"./de-at.js":6729,"./de-ch":74743,"./de-ch.js":74743,"./de.js":22131,"./dv":14598,"./dv.js":14598,"./el":38737,"./el.js":38737,"./en-SG":94978,"./en-SG.js":94978,"./en-au":22606,"./en-au.js":22606,"./en-ca":60052,"./en-ca.js":60052,"./en-gb":17305,"./en-gb.js":17305,"./en-ie":76390,"./en-ie.js":76390,"./en-il":89549,"./en-il.js":89549,"./en-nz":67584,"./en-nz.js":67584,"./eo":24408,"./eo.js":24408,"./es":45644,"./es-do":21888,"./es-do.js":21888,"./es-us":23537,"./es-us.js":23537,"./es.js":45644,"./et":27257,"./et.js":27257,"./eu":57002,"./eu.js":57002,"./fa":90241,"./fa.js":90241,"./fi":74009,"./fi.js":74009,"./fo":81267,"./fo.js":81267,"./fr":71160,"./fr-ca":39433,"./fr-ca.js":39433,"./fr-ch":20130,"./fr-ch.js":20130,"./fr.js":71160,"./fy":20553,"./fy.js":20553,"./ga":18232,"./ga.js":18232,"./gd":33771,"./gd.js":33771,"./gl":99747,"./gl.js":99747,"./gom-latn":80289,"./gom-latn.js":80289,"./gu":148,"./gu.js":148,"./he":68247,"./he.js":68247,"./hi":39835,"./hi.js":39835,"./hr":69734,"./hr.js":69734,"./hu":40999,"./hu.js":40999,"./hy-am":95002,"./hy-am.js":95002,"./id":23021,"./id.js":23021,"./is":96232,"./is.js":96232,"./it":15581,"./it-ch":4809,"./it-ch.js":4809,"./it.js":15581,"./ja":45981,"./ja.js":45981,"./jv":12568,"./jv.js":12568,"./ka":17924,"./ka.js":17924,"./kk":1062,"./kk.js":1062,"./km":65456,"./km.js":65456,"./kn":15817,"./kn.js":15817,"./ko":45306,"./ko.js":45306,"./ku":39016,"./ku.js":39016,"./ky":71308,"./ky.js":71308,"./lb":67330,"./lb.js":67330,"./lo":18949,"./lo.js":18949,"./lt":58804,"./lt.js":58804,"./lv":47006,"./lv.js":47006,"./me":83346,"./me.js":83346,"./mi":630,"./mi.js":630,"./mk":88876,"./mk.js":88876,"./ml":86841,"./ml.js":86841,"./mn":93847,"./mn.js":93847,"./mr":57515,"./mr.js":57515,"./ms":51844,"./ms-my":44391,"./ms-my.js":44391,"./ms.js":51844,"./mt":81969,"./mt.js":81969,"./my":34982,"./my.js":34982,"./nb":41632,"./nb.js":41632,"./ne":81781,"./ne.js":81781,"./nl":14910,"./nl-be":72506,"./nl-be.js":72506,"./nl.js":14910,"./nn":12980,"./nn.js":12980,"./pa-in":33791,"./pa-in.js":33791,"./pl":1872,"./pl.js":1872,"./pt":9064,"./pt-br":85273,"./pt-br.js":85273,"./pt.js":9064,"./ro":63167,"./ro.js":63167,"./ru":28649,"./ru.js":28649,"./sd":14823,"./sd.js":14823,"./se":90672,"./se.js":90672,"./si":26244,"./si.js":26244,"./sk":40654,"./sk.js":40654,"./sl":44335,"./sl.js":44335,"./sq":79116,"./sq.js":79116,"./sr":60693,"./sr-cyrl":1436,"./sr-cyrl.js":1436,"./sr.js":60693,"./ss":51734,"./ss.js":51734,"./sv":37945,"./sv.js":37945,"./sw":41514,"./sw.js":41514,"./ta":1991,"./ta.js":1991,"./te":95011,"./te.js":95011,"./tet":19463,"./tet.js":19463,"./tg":43109,"./tg.js":43109,"./th":97144,"./th.js":97144,"./tl-ph":70401,"./tl-ph.js":70401,"./tlh":26678,"./tlh.js":26678,"./tr":28682,"./tr.js":28682,"./tzl":59084,"./tzl.js":59084,"./tzm":64307,"./tzm-latn":68869,"./tzm-latn.js":68869,"./tzm.js":64307,"./ug-cn":78812,"./ug-cn.js":78812,"./uk":25812,"./uk.js":25812,"./ur":25411,"./ur.js":25411,"./uz":59435,"./uz-latn":94589,"./uz-latn.js":94589,"./uz.js":59435,"./vi":50569,"./vi.js":50569,"./x-pseudo":85241,"./x-pseudo.js":85241,"./yo":96972,"./yo.js":96972,"./zh-cn":18422,"./zh-cn.js":18422,"./zh-hk":84106,"./zh-hk.js":84106,"./zh-tw":69362,"./zh-tw.js":69362}
|
|
11
|
-
function s(e){var r=o(e)
|
|
12
|
-
return t(r)}function o(e){if(!t.o(n,e)){var r=new Error("Cannot find module '"+e+"'")
|
|
13
|
-
throw r.code="MODULE_NOT_FOUND",r}return n[e]}s.keys=function(){return Object.keys(n)},s.resolve=o,e.exports=s,s.id=56857},61542:function(e,r){window._eai_r=require,window._eai_d=define},80032:e=>{"use strict"
|
|
14
|
-
e.exports=require("ember-tracked-storage-polyfill")},86625:()=>{}},t={}
|
|
15
|
-
function n(e){var s=t[e]
|
|
16
|
-
if(void 0!==s)return s.exports
|
|
17
|
-
var o=t[e]={id:e,loaded:!1,exports:{}}
|
|
18
|
-
return r[e].call(o.exports,o,o.exports,n),o.loaded=!0,o.exports}n.m=r,n.c=t,e=[],n.O=(r,t,s,o)=>{if(!t){var i=1/0
|
|
19
|
-
for(c=0;c<e.length;c++){for(var[t,s,o]=e[c],u=!0,m=0;m<t.length;m++)(!1&o||i>=o)&&Object.keys(n.O).every((e=>n.O[e](t[m])))?t.splice(m--,1):(u=!1,o<i&&(i=o))
|
|
20
|
-
if(u){e.splice(c--,1)
|
|
21
|
-
var a=s()
|
|
22
|
-
void 0!==a&&(r=a)}}return r}o=o||0
|
|
23
|
-
for(var c=e.length;c>0&&e[c-1][2]>o;c--)e[c]=e[c-1]
|
|
24
|
-
e[c]=[t,s,o]},n.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e
|
|
25
|
-
return n.d(r,{a:r}),r},n.d=(e,r)=>{for(var t in r)n.o(r,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},n.hmd=e=>((e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set:()=>{throw new Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e),n.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e={524:0}
|
|
26
|
-
n.O.j=r=>0===e[r]
|
|
27
|
-
var r=(r,t)=>{var s,o,[i,u,m]=t,a=0
|
|
28
|
-
if(i.some((r=>0!==e[r]))){for(s in u)n.o(u,s)&&(n.m[s]=u[s])
|
|
29
|
-
if(m)var c=m(n)}for(r&&r(t);a<i.length;a++)o=i[a],n.o(e,o)&&e[o]&&e[o][0](),e[o]=0
|
|
30
|
-
return n.O(c)},t=globalThis.webpackChunk_ember_auto_import_=globalThis.webpackChunk_ember_auto_import_||[]
|
|
31
|
-
t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})(),n.O(void 0,[137],(()=>n(n.s=61542)))
|
|
32
|
-
var s=n.O(void 0,[137],(()=>n(n.s=54571)))
|
|
33
|
-
s=n.O(s),__ember_auto_import__=s})()
|
|
34
|
-
|
|
35
|
-
//# sourceMappingURL=chunk.524.c86e2e1b3e94d7cb1e4c.map
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const VersionNotificationsDataService = require('./VersionNotificationsDataService');
|
|
3
|
-
const EmailContentGenerator = require('../lib/EmailContentGenerator');
|
|
4
|
-
|
|
5
|
-
class APIVersionCompatibilityService {
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
8
|
-
* @param {Object} options
|
|
9
|
-
* @param {Object} options.UserModel - ghost user model
|
|
10
|
-
* @param {Object} options.ApiKeyModel - ghost api key model
|
|
11
|
-
* @param {Object} options.settingsService - ghost settings service
|
|
12
|
-
* @param {(Object: {subject: String, to: String, text: String, html: String}) => Promise<any>} options.sendEmail - email sending function
|
|
13
|
-
* @param {Function} options.getSiteUrl
|
|
14
|
-
* @param {Function} options.getSiteTitle
|
|
15
|
-
*/
|
|
16
|
-
constructor({UserModel, ApiKeyModel, settingsService, sendEmail, getSiteUrl, getSiteTitle}) {
|
|
17
|
-
this.sendEmail = sendEmail;
|
|
18
|
-
|
|
19
|
-
this.versionNotificationsDataService = new VersionNotificationsDataService({
|
|
20
|
-
UserModel,
|
|
21
|
-
ApiKeyModel,
|
|
22
|
-
settingsService
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
this.emailContentGenerator = new EmailContentGenerator({
|
|
26
|
-
getSiteUrl,
|
|
27
|
-
getSiteTitle,
|
|
28
|
-
templatesDir: path.join(__dirname, 'templates')
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Version mismatch handler doing the logic of picking a template and sending a notification email
|
|
34
|
-
* @param {Object} options
|
|
35
|
-
* @param {string} options.acceptVersion - client's accept-version header value
|
|
36
|
-
* @param {string} options.contentVersion - server's content-version header value
|
|
37
|
-
* @param {string} options.apiKeyValue - key value (secret for Content API and kid for Admin API) used to access the API
|
|
38
|
-
* @param {string} options.apiKeyType - key type used to access the API
|
|
39
|
-
* @param {string} options.requestURL - url that was requested and failed compatibility test
|
|
40
|
-
* @param {string} [options.userAgent] - client's user-agent header value
|
|
41
|
-
*/
|
|
42
|
-
async handleMismatch({acceptVersion, contentVersion, apiKeyValue, apiKeyType, requestURL, userAgent = ''}) {
|
|
43
|
-
if (!await this.versionNotificationsDataService.fetchNotification(acceptVersion)) {
|
|
44
|
-
const integration = await this.versionNotificationsDataService.getIntegration(apiKeyValue, apiKeyType);
|
|
45
|
-
|
|
46
|
-
// We couldn't find the integration
|
|
47
|
-
if (!integration) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const {
|
|
52
|
-
name: integrationName,
|
|
53
|
-
type: integrationType
|
|
54
|
-
} = integration;
|
|
55
|
-
|
|
56
|
-
// @NOTE: "internal" or "core" integrations (https://ghost.notion.site/Data-Types-e5dc54dd0078443f9afd6b2abda443c4)
|
|
57
|
-
// are maintained by Ghost team, so there is no sense notifying the instance owner about it's incompatibility.
|
|
58
|
-
// The other two integration types: "builtin" and "custom", is when we want to notify about incompatibility.
|
|
59
|
-
if (['internal', 'core'].includes(integrationType)) {
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const trimmedUseAgent = userAgent.split('/')[0];
|
|
64
|
-
const emails = await this.versionNotificationsDataService.getNotificationEmails();
|
|
65
|
-
|
|
66
|
-
for (const email of emails) {
|
|
67
|
-
const template = (trimmedUseAgent === 'Zapier')
|
|
68
|
-
? 'zapier-mismatch'
|
|
69
|
-
: 'generic-mismatch';
|
|
70
|
-
|
|
71
|
-
const subject = (trimmedUseAgent === 'Zapier')
|
|
72
|
-
? 'Attention required: One of your Zaps has failed'
|
|
73
|
-
: `Attention required: Your ${integrationName} integration has failed`;
|
|
74
|
-
|
|
75
|
-
const {html, text} = await this.emailContentGenerator.getContent({
|
|
76
|
-
template,
|
|
77
|
-
data: {
|
|
78
|
-
acceptVersion,
|
|
79
|
-
contentVersion,
|
|
80
|
-
clientName: integrationName,
|
|
81
|
-
recipientEmail: email,
|
|
82
|
-
requestURL: requestURL
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
await this.sendEmail({
|
|
87
|
-
subject,
|
|
88
|
-
to: email,
|
|
89
|
-
html,
|
|
90
|
-
text
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
await this.versionNotificationsDataService.saveNotification(acceptVersion);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
module.exports = APIVersionCompatibilityService;
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
const internalContext = {
|
|
2
|
-
internal: true
|
|
3
|
-
};
|
|
4
|
-
|
|
5
|
-
class VersionNotificationsDataService {
|
|
6
|
-
/**
|
|
7
|
-
* @param {Object} options
|
|
8
|
-
* @param {Object} options.UserModel - ghost user model
|
|
9
|
-
* @param {Object} options.ApiKeyModel - ghost api key model
|
|
10
|
-
* @param {Object} options.settingsService - ghost settings service
|
|
11
|
-
*/
|
|
12
|
-
constructor({UserModel, ApiKeyModel, settingsService}) {
|
|
13
|
-
this.UserModel = UserModel;
|
|
14
|
-
this.ApiKeyModel = ApiKeyModel;
|
|
15
|
-
this.settingsService = settingsService;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async fetchNotification(acceptVersion) {
|
|
19
|
-
const setting = await this.settingsService.read('version_notifications', internalContext);
|
|
20
|
-
const versionNotifications = JSON.parse(setting.version_notifications.value);
|
|
21
|
-
|
|
22
|
-
return versionNotifications.find(version => version === acceptVersion);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async saveNotification(acceptVersion) {
|
|
26
|
-
const setting = await this.settingsService.read('version_notifications', internalContext);
|
|
27
|
-
const versionNotifications = JSON.parse(setting.version_notifications.value);
|
|
28
|
-
|
|
29
|
-
if (!versionNotifications.find(version => version === acceptVersion)) {
|
|
30
|
-
versionNotifications.push(acceptVersion);
|
|
31
|
-
|
|
32
|
-
return this.settingsService.edit([{
|
|
33
|
-
key: 'version_notifications',
|
|
34
|
-
value: JSON.stringify(versionNotifications)
|
|
35
|
-
}], {
|
|
36
|
-
context: internalContext
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async getNotificationEmails() {
|
|
42
|
-
const data = await this.UserModel.findAll(Object.assign({
|
|
43
|
-
withRelated: ['roles'],
|
|
44
|
-
filter: 'status:active'
|
|
45
|
-
}, internalContext));
|
|
46
|
-
|
|
47
|
-
const adminEmails = data
|
|
48
|
-
.toJSON()
|
|
49
|
-
.filter(user => ['Owner', 'Administrator'].includes(user.roles[0].name))
|
|
50
|
-
.map(user => user.email);
|
|
51
|
-
|
|
52
|
-
return adminEmails;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* This method is for internal use only.
|
|
57
|
-
*
|
|
58
|
-
* @param {String} key - api key identification value, it's "secret" in case of Content API key and "id" for Admin API
|
|
59
|
-
* @param {String} type - one of "content" or "admin" values
|
|
60
|
-
* @returns {Promise<Object | null>} Integration JSON object
|
|
61
|
-
*/
|
|
62
|
-
async getIntegration(key, type) {
|
|
63
|
-
let queryOptions = null;
|
|
64
|
-
|
|
65
|
-
if (type === 'content') {
|
|
66
|
-
queryOptions = {secret: key};
|
|
67
|
-
} else if (type === 'admin') {
|
|
68
|
-
queryOptions = {id: key};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const apiKey = await this.ApiKeyModel.findOne(queryOptions, {withRelated: ['integration']});
|
|
72
|
-
if (!apiKey) {
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return apiKey.relations.integration.toJSON();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
module.exports = VersionNotificationsDataService;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
const jwt = require('jsonwebtoken');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Remove 'Ghost' from raw authorization header and extract the JWT token.
|
|
5
|
-
* Eg. Authorization: Ghost ${JWT}
|
|
6
|
-
* @param {string} header
|
|
7
|
-
*/
|
|
8
|
-
const extractTokenFromHeader = (header) => {
|
|
9
|
-
const [scheme, token] = header.split(' ');
|
|
10
|
-
|
|
11
|
-
if (/^Ghost$/i.test(scheme)) {
|
|
12
|
-
return token;
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const extractAdminAPIKey = (token) => {
|
|
17
|
-
const decoded = jwt.decode(token, {complete: true});
|
|
18
|
-
|
|
19
|
-
if (!decoded || !decoded.header || !decoded.header.kid) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return decoded.header.kid;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @typedef {object} ApiKey
|
|
28
|
-
* @prop {string} key
|
|
29
|
-
* @prop {string} type
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* When it's a Content API the function resolves with the value of the key secret.
|
|
34
|
-
* When it's an Admin API the function resolves with the value of the key id.
|
|
35
|
-
*
|
|
36
|
-
* @param {import('express').Request} req
|
|
37
|
-
* @returns {ApiKey}
|
|
38
|
-
*/
|
|
39
|
-
const extractAPIKey = (req) => {
|
|
40
|
-
let keyValue = null;
|
|
41
|
-
let keyType = null;
|
|
42
|
-
|
|
43
|
-
if (req.query && req.query.key) {
|
|
44
|
-
keyValue = req.query.key;
|
|
45
|
-
keyType = 'content';
|
|
46
|
-
} else if (req.headers && req.headers.authorization) {
|
|
47
|
-
keyValue = extractAdminAPIKey(extractTokenFromHeader(req.headers.authorization));
|
|
48
|
-
keyType = 'admin';
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
key: keyValue,
|
|
53
|
-
type: keyType
|
|
54
|
-
};
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
module.exports = extractAPIKey;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
const extractApiKey = require('./extract-api-key');
|
|
2
|
-
|
|
3
|
-
const versionMismatchHandler = (APIVersionCompatibilityService) => {
|
|
4
|
-
/**
|
|
5
|
-
* @param {Object} err
|
|
6
|
-
* @param {import('express').Request} req
|
|
7
|
-
* @param {import('express').Response} res
|
|
8
|
-
* @param {import('express').NextFunction} next
|
|
9
|
-
*/
|
|
10
|
-
return async function versionMismatchHandlerMiddleware(err, req, res, next) {
|
|
11
|
-
if (err && err.errorType === 'RequestNotAcceptableError') {
|
|
12
|
-
if (err.code === 'UPDATE_CLIENT') {
|
|
13
|
-
const {key, type} = extractApiKey(req);
|
|
14
|
-
const requestURL = req.originalUrl.split('?').shift();
|
|
15
|
-
|
|
16
|
-
await APIVersionCompatibilityService.handleMismatch({
|
|
17
|
-
acceptVersion: req.headers['accept-version'],
|
|
18
|
-
contentVersion: `v${res.locals.safeVersion}`,
|
|
19
|
-
requestURL,
|
|
20
|
-
userAgent: req.headers['user-agent'],
|
|
21
|
-
apiKeyValue: key,
|
|
22
|
-
apiKeyType: type
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
next(err);
|
|
28
|
-
};
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
module.exports = versionMismatchHandler;
|