ghost 6.53.0 → 6.54.0
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/ghost-storage-base-3.0.0.tgz +0 -0
- package/components/tryghost-adapter-base-cache-0.2.0.tgz +0 -0
- package/components/tryghost-adapter-base-scheduling-0.1.1.tgz +0 -0
- package/components/tryghost-adapter-base-sso-0.1.1.tgz +0 -0
- package/components/tryghost-admin-api-schema-0.0.0.tgz +0 -0
- package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
- package/components/tryghost-i18n-0.0.0.tgz +0 -0
- package/components/tryghost-kg-converters-1.2.3.tgz +0 -0
- package/components/tryghost-kg-default-nodes-2.1.3.tgz +0 -0
- package/components/tryghost-kg-lexical-html-renderer-1.4.3.tgz +0 -0
- package/core/boot.js +9 -6
- package/core/built/admin/assets/Combination-CJG7Flp-.js +41 -0
- package/core/built/admin/assets/Growth-CSaHoSVD.js +3 -0
- package/core/built/admin/assets/Newsletters-C5cs6FGo.js +1 -0
- package/core/built/admin/assets/Overview-j4NaeUNm.js +1 -0
- package/core/built/admin/assets/{PolarAngleAxis-pciQ0MOy.js → PolarAngleAxis-BGjf7sBu.js} +1 -1
- package/core/built/admin/assets/{RadialBarChart-DWmw2PcX.js → RadialBarChart-zeFf9mBz.js} +1 -1
- package/core/built/admin/assets/Web-_fD935OX.js +2 -0
- package/core/built/admin/assets/account-migration-DLvVA5yq.js +1 -0
- package/core/built/admin/assets/activitypub/{account-migration-BPZG37DJ.js → account-migration-DHbZcxGM.js} +13 -13
- package/core/built/admin/assets/activitypub/activitypub.js +7 -7
- package/core/built/admin/assets/activitypub/{avatar-ZYco0ITb.js → avatar-B3DEDB1l.js} +10 -10
- package/core/built/admin/assets/activitypub/{avatar-flipboard-D541lc4F.js → avatar-flipboard-Cqrg0XMx.js} +3 -3
- package/core/built/admin/assets/activitypub/{bluesky-sharing-NOHUtHjl.js → bluesky-sharing-zfxUey_L.js} +38 -37
- package/core/built/admin/assets/activitypub/{chunk-KS7C4IRE-B-GOFDPZ.js → chunk-KS7C4IRE-D4HEcEwi.js} +716 -710
- package/core/built/admin/assets/activitypub/{content-formatters-bwrp4iEO.js → content-formatters-BpQARh28.js} +229 -181
- package/core/built/admin/assets/activitypub/{copy-C7m7ovHw.js → copy-D9UWIAan.js} +2 -2
- package/core/built/admin/assets/activitypub/{dist-B5ira32t.js → dist-Ba_QxHHl.js} +5 -5
- package/core/built/admin/assets/activitypub/{domain-iqE4YXwD.js → domain-CmwSZLHK.js} +33 -33
- package/core/built/admin/assets/activitypub/{edit-profile-B8MFYh28.js → edit-profile-CXdwNmVG.js} +46 -45
- package/core/built/admin/assets/activitypub/{explore-BbdKodp3.js → explore-DfbjzGM1.js} +20 -20
- package/core/built/admin/assets/activitypub/{feed-Cl3A5owG.js → feed-DSEBJOqf.js} +15 -15
- package/core/built/admin/assets/activitypub/{field-DL6WyR-c.js → field-CY7XVcx6.js} +13 -13
- package/core/built/admin/assets/activitypub/{hash-6G3DzwL9.js → hash-BC9Q0N4c.js} +2 -2
- package/core/built/admin/assets/activitypub/{inbox-YmhuBice.js → inbox-DQ4ZnC1m.js} +2 -2
- package/core/built/admin/assets/activitypub/inbox-DtQ0kytT.js +1221 -0
- package/core/built/admin/assets/activitypub/{label-DGbLjDvE.js → label-Dw96GQ7u.js} +6 -6
- package/core/built/admin/assets/activitypub/layout-IdVq3lRy.js +1 -0
- package/core/built/admin/assets/activitypub/{moderation-qnBtk1zS.js → moderation-Dg_-I-8C.js} +32 -31
- package/core/built/admin/assets/activitypub/{note-C7ZRoSJv.js → note-Cy1-uKMY.js} +21 -21
- package/core/built/admin/assets/activitypub/{notifications-DiEA4b1o.js → notifications-B_fvoLIM.js} +17 -17
- package/core/built/admin/assets/activitypub/{onboarding-_JVgEwgV.js → onboarding-BFDkzeR2.js} +2 -2
- package/core/built/admin/assets/activitypub/{onboarding-DG4zu3qM.js → onboarding-D6rcBdPe.js} +5 -5
- package/core/built/admin/assets/activitypub/{preferences-B3FtocnP.js → preferences-ByJseZp6.js} +1607 -1606
- package/core/built/admin/assets/activitypub/{profile-D8ZJfYXB.js → profile-BFtbnIjz.js} +264 -263
- package/core/built/admin/assets/activitypub/{reply-C1vggenw.js → reply-CpdMeAO5.js} +2 -2
- package/core/built/admin/assets/activitypub/{routes-BOii-V9n.js → routes-Dh3xXfce.js} +1311 -1295
- package/core/built/admin/assets/activitypub/{separator-1gNokN5S.js → separator-BI1FLsYM.js} +4 -4
- package/core/built/admin/assets/activitypub/{settings--9Sb0nbl.js → settings-DTgqJPxM.js} +14 -14
- package/core/built/admin/assets/activitypub/{site-fkMmqv0V.js → site-CdL9ZLqm.js} +10 -10
- package/core/built/admin/assets/activitypub/{step-1-QhivSMw2.js → step-1-DIDg4aHb.js} +15 -15
- package/core/built/admin/assets/activitypub/{step-2-pMk9YwqD.js → step-2-BfGe8BYt.js} +7 -7
- package/core/built/admin/assets/activitypub/{step-3-DvmVC1fo.js → step-3-mE9spAqw.js} +12 -12
- package/core/built/admin/assets/activitypub/{tabs-Dc0FEEYD.js → tabs-ogqwoBlb.js} +241 -237
- package/core/built/admin/assets/activitypub/{topic-filter-CuDyM5bD.js → topic-filter-DLHBZT93.js} +4 -4
- package/core/built/admin/assets/activitypub/use-activity-pub-queries-VzbN99u_.js +1957 -0
- package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-Drx1kdAK.js → use-navigate-with-base-path-CAwXTmqH.js} +165 -175
- package/core/built/admin/assets/activitypub/{use-reply-chain-data-BHkCHcW5.js → use-reply-chain-data-CxonteFD.js} +8 -8
- package/core/built/admin/assets/activitypub/users-BLeiOTHc.js +1464 -0
- package/core/built/admin/assets/activitypub/{x-BHCEe-c2.js → x-C8tAnXly.js} +2 -2
- package/core/built/admin/assets/{audience-adiFehTD.js → audience-BKRdsFmy.js} +1 -1
- package/core/built/admin/assets/{automated-emails-UWM02CMr.js → automated-emails-Cn87L5Md.js} +1 -1
- package/core/built/admin/assets/automations-B7-y3dXt.js +1 -0
- package/core/built/admin/assets/automations-BP_aHamJ.js +1 -0
- package/core/built/admin/assets/{avatar-flipboard-Lz3F9fNT.js → avatar-flipboard-C6Kj3Awu.js} +1 -1
- package/core/built/admin/assets/bluesky-sharing-Bh36XPh4.js +1 -0
- package/core/built/admin/assets/box-BWbhXh21.js +1 -0
- package/core/built/admin/assets/breadcrumb-D34YWnaw.js +1 -0
- package/core/built/admin/assets/card-DGoDJzrn.js +1 -0
- package/core/built/admin/assets/{chart-ChpW-NzQ.js → chart-BuRT2Y6p.js} +14 -14
- package/core/built/admin/assets/chart-helpers-DbklaJw9.js +1 -0
- package/core/built/admin/assets/checkbox-DA4-1UiI.js +1 -0
- package/core/built/admin/assets/chunk.524.45e0875f41b71e46e849.js +25 -0
- package/core/built/admin/assets/chunk.582.51defd4b009f0de8d4d5.js +27 -0
- package/core/built/admin/assets/{chunk.831.0703a12e49f51cec3f3a.js → chunk.589.096f4d0bb775e5229aa9.js} +78 -85
- package/core/built/admin/assets/{chunk.432.c2caa0b20f03e71d1a35.js → chunk.962.b73442b07be930bb5d85.js} +2216 -3188
- package/core/built/admin/assets/{chunk.432.c2caa0b20f03e71d1a35.js.LICENSE.txt → chunk.962.b73442b07be930bb5d85.js.LICENSE.txt} +0 -63
- package/core/built/admin/assets/code-editor-view-BKBrkffZ.js +1 -0
- package/core/built/admin/assets/comments-CzVNIT8b.js +1 -0
- package/core/built/admin/assets/container-BYz2Ed39.js +1 -0
- package/core/built/admin/assets/data-list-16rkJYYi.js +1 -0
- package/core/built/admin/assets/date-range-select-B5vSsrpx.js +1 -0
- package/core/built/admin/assets/disabled-sources-indicator-NkOIoMue.js +1 -0
- package/core/built/admin/assets/{dist-CsekE4FL.js → dist-CQJY6SVY.js} +1 -1
- package/core/built/admin/assets/dist-DGzPJ_bO.js +4 -0
- package/core/built/admin/assets/{dist-BbGrW05X.js → dist-DyViJwIy.js} +1 -1
- package/core/built/admin/assets/dist-Ndy-PuGN.js +1 -0
- package/core/built/admin/assets/dist-P_ohUlTi.js +1 -0
- package/core/built/admin/assets/domain-B7_n5nfx.js +1 -0
- package/core/built/admin/assets/dropzone-DcuJEEUf.js +5 -0
- package/core/built/admin/assets/edit-profile-rvDGrS8J.js +1 -0
- package/core/built/admin/assets/editor-BCiIyFjm.js +8 -0
- package/core/built/admin/assets/empty-indicator-oX1u1Pkn.js +1 -0
- package/core/built/admin/assets/esm-CFX93H5M.js +2 -0
- package/core/built/admin/assets/explore-BZAZOg5X.js +1 -0
- package/core/built/admin/assets/feed-CFV8xDw9.js +1 -0
- package/core/built/admin/assets/field-BW-M2Zwp.js +1 -0
- package/core/built/admin/assets/{filter-sources-v39ihhhV.js → filter-sources-Fx8wiYYw.js} +1 -1
- package/core/built/admin/assets/filters-CGX_pf2N.js +1 -0
- package/core/built/admin/assets/filters-DtcXMZDU.js +1 -0
- package/core/built/admin/assets/framework-provider-CmtnPXIT.js +4 -0
- package/core/built/admin/assets/{ghost-b57f077997b739a8ae9a70772dc016cb.js → ghost-b1dce91ad3232cc259ee5fbbf9526243.js} +294 -290
- package/core/built/admin/assets/ghost-dark-c8d0ab7f515b2010c173e23e9b32ea8a.css +1 -0
- package/core/built/admin/assets/gift-link-modal-Bk8qpnMw.js +1 -0
- package/core/built/admin/assets/{gift-links-CY3GwiVi.js → gift-links-nBxJjZiQ.js} +1 -1
- package/core/built/admin/assets/growth-Ck2s3JjR.js +1 -0
- package/core/built/admin/assets/hooks-BApwwBE0.js +2 -0
- package/core/built/admin/assets/{inbox-TEISAmth.js → inbox-BRp1_aaC.js} +35 -35
- package/core/built/admin/assets/index-BBf502Wg.js +69 -0
- package/core/built/admin/assets/index-BCCZKxP2.css +1 -0
- package/core/built/admin/assets/inline-EMAm3okk.js +1 -0
- package/core/built/admin/assets/input-group-DjuYnNCd.js +1 -0
- package/core/built/admin/assets/{react-dom-C6aoWSfl.js → jsx-runtime-DX3WBWVO.js} +1 -1
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +5 -2
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +2 -2
- package/core/built/admin/assets/{koenig-lexical-Di7b48ED.js → koenig-lexical-CM7UFNdL.js} +2 -2
- package/core/built/admin/assets/kpi-card-BrGH6FsT.js +1 -0
- package/core/built/admin/assets/kpi-card-CIGyijjx.js +1 -0
- package/core/built/admin/assets/kpi-helpers-_HRRsklE.js +1 -0
- package/core/built/admin/assets/kpi-tabs-BSvh9eoq.js +1 -0
- package/core/built/admin/assets/label-BOR9XdKl.js +1 -0
- package/core/built/admin/assets/label-picker-BdNAWuUX.js +1 -0
- package/core/built/admin/assets/{labels-GbxlXWtf.js → labels-Cyayfd-e.js} +1 -1
- package/core/built/admin/assets/layout-Bw4GnxXp.js +1 -0
- package/core/built/admin/assets/limit-service-9fwD33lU.js +20 -0
- package/core/built/admin/assets/link-helpers-tOlxmuH5.js +1 -0
- package/core/built/admin/assets/list-page-B6ANtzkd.js +1 -0
- package/core/built/admin/assets/mailchimp-Ds_NQ04w.svg +9 -0
- package/core/built/admin/assets/member-custom-fields-DvFyamLu.js +1 -0
- package/core/built/admin/assets/member-detail-Cg2vTqvJ.js +1 -0
- package/core/built/admin/assets/members-DsPxYAVm.js +10 -0
- package/core/built/admin/assets/modals-Bf_fyvHZ.js +31 -0
- package/core/built/admin/assets/moderation-Dlp7M5sa.js +1 -0
- package/core/built/admin/assets/multi-select-combobox-CH1o8XXQ.js +1 -0
- package/core/built/admin/assets/newsletter-CQ5CAYUI.js +1 -0
- package/core/built/admin/assets/{newsletters-DZm3yLj8.js → newsletters-D1jbtV-h.js} +1 -1
- package/core/built/admin/assets/note-BrAZ7Z0o.js +1 -0
- package/core/built/admin/assets/notifications-BnbHLOPC.js +1 -0
- package/core/built/admin/assets/nql-lang-B7faUf8D.js +19 -0
- package/core/built/admin/assets/{offers-D11QtPXX.js → offers-CrY6nSRR.js} +1 -1
- package/core/built/admin/assets/onboarding-route-eU146kuA.js +1 -0
- package/core/built/admin/assets/overview-BpbaK-xu.js +1 -0
- package/core/built/admin/assets/page-header-C0jVxtS8.js +1 -0
- package/core/built/admin/assets/{pages-BnObVRrf.js → pages-BbNWFcGj.js} +1 -1
- package/core/built/admin/assets/pintura-CXOmq-5H.svg +15 -0
- package/core/built/admin/assets/post-analytics-Iw7dk1mT.js +1 -0
- package/core/built/admin/assets/post-analytics-header-D9pJ4iNm.js +1 -0
- package/core/built/admin/assets/{post-analytics-provider-DSfBCtnj.js → post-analytics-provider-BDqcfBor.js} +1 -1
- package/core/built/admin/assets/post-share-modal-DBfKl2GZ.js +1 -0
- package/core/built/admin/assets/{posts-CwH8VJvB.js → posts-EWpZIjkr.js} +1 -1
- package/core/built/admin/assets/preferences-D4EANGoc.js +5 -0
- package/core/built/admin/assets/profile-dJ44Bn_W.js +1 -0
- package/core/built/admin/assets/{referrers-nxR52jPI.js → referrers-BCfFYSHc.js} +1 -1
- package/core/built/admin/assets/router-provider-C1R4AZ2o.js +1 -0
- package/core/built/admin/assets/select--2uVN9_-.js +1 -0
- package/core/built/admin/assets/settings-Bz3RZRmE.js +1 -0
- package/core/built/admin/assets/settings-SD9bxIpt.js +4 -0
- package/core/built/admin/assets/share-modal-CkdTTMJd.js +1 -0
- package/core/built/admin/assets/social-urls-BvFZwYcE.js +8 -0
- package/core/built/admin/assets/sort-button-DZp9Y2r1.js +1 -0
- package/core/built/admin/assets/source-icon-CHr9qJ2Y.js +1 -0
- package/core/built/admin/assets/stack-xiN0eQ6Z.js +1 -0
- package/core/built/admin/assets/stats-DGoXZxWE.js +1 -0
- package/core/built/admin/assets/stats-view-D2-1L0ms.js +1 -0
- package/core/built/admin/assets/step-1-RdahbwyG.js +1 -0
- package/core/built/admin/assets/step-2-D83PeRwd.js +1 -0
- package/core/built/admin/assets/step-3-p_Op4wv4.js +2 -0
- package/core/built/admin/assets/switch-qp518gFQ.js +1 -0
- package/core/built/admin/assets/table-B8LgTQJZ.js +1 -0
- package/core/built/admin/assets/tabs-D3ZOYkM7.js +1 -0
- package/core/built/admin/assets/tags-B4l891z2.js +1 -0
- package/core/built/admin/assets/text-DwtjwGkh.js +1 -0
- package/core/built/admin/assets/textarea-CTlb3Uu6.js +1 -0
- package/core/built/admin/assets/{tiers-EghDzCKc.js → tiers-BgYLWRJv.js} +1 -1
- package/core/built/admin/assets/toggle-group-DNXDkAwf.js +1 -0
- package/core/built/admin/assets/topic-filter-DZGjEcz3.js +1 -0
- package/core/built/admin/assets/{use-analytics-data-0l_OHtnR.js → use-analytics-data-CaT8RirX.js} +1 -1
- package/core/built/admin/assets/use-filter-params-DeQ8sX4N.js +1 -0
- package/core/built/admin/assets/use-growth-stats-9Db2CuJe.js +1 -0
- package/core/built/admin/assets/{use-post-referrers-DwI31Ril.js → use-post-referrers-BV54YcQS.js} +1 -1
- package/core/built/admin/assets/use-reply-chain-data-DuYZGDan.js +1 -0
- package/core/built/admin/assets/use-simple-pagination-8fTua9Nt.js +1 -0
- package/core/built/admin/assets/{use-tinybird-query-DvZBBMG7.js → use-tinybird-query-Dz156HvZ.js} +1 -1
- package/core/built/admin/assets/{use-tinybird-token-CQtebkvU.js → use-tinybird-token-C9RUdL_n.js} +1 -1
- package/core/built/admin/assets/{users-Pc8IRjk9.js → users-CcSCQFcQ.js} +1 -1
- package/core/built/admin/assets/virtual-list-BCvP0YF-.js +1 -0
- package/core/built/admin/assets/web-DTZnnUGr.js +1 -0
- package/core/built/admin/index.html +18 -22
- package/core/frontend/apps/private-blogging/index.js +1 -1
- package/core/frontend/apps/private-blogging/lib/middleware.js +1 -1
- package/core/frontend/helpers/split.js +2 -1
- package/core/frontend/meta/asset-url.js +1 -1
- package/core/frontend/meta/author-image.js +1 -1
- package/core/frontend/meta/blog-logo.js +1 -1
- package/core/frontend/meta/canonical-url.js +1 -1
- package/core/frontend/meta/cover-image.js +1 -1
- package/core/frontend/meta/get-meta.js +1 -1
- package/core/frontend/meta/og-image.js +1 -1
- package/core/frontend/meta/paginated-url.js +1 -1
- package/core/frontend/meta/twitter-image.js +1 -1
- package/core/frontend/meta/url.js +1 -1
- package/core/frontend/services/assets-minification/admin-auth-assets.js +1 -1
- package/core/frontend/services/llms/handler.js +1 -1
- package/core/frontend/services/proxy.js +31 -2
- package/core/frontend/services/routing/collection-router.js +1 -1
- package/core/frontend/services/routing/controllers/email-post.js +1 -1
- package/core/frontend/services/routing/controllers/entry/markdown.js +1 -1
- package/core/frontend/services/routing/controllers/entry/markdown.ts +1 -1
- package/core/frontend/services/routing/controllers/entry.js +1 -1
- package/core/frontend/services/routing/controllers/entry.ts +1 -1
- package/core/frontend/services/routing/controllers/previews.js +6 -7
- package/core/frontend/services/routing/controllers/unsubscribe.js +7 -3
- package/core/frontend/services/routing/email-router.js +1 -1
- package/core/frontend/services/routing/events.js +12 -0
- package/core/frontend/services/routing/middleware/page-param.js +1 -1
- package/core/frontend/services/routing/parent-router.js +1 -1
- package/core/frontend/services/routing/preview-router.js +1 -1
- package/core/frontend/services/routing/router-manager.js +4 -8
- package/core/frontend/services/routing/rss-router.js +1 -1
- package/core/frontend/services/routing/static-pages-router.js +1 -1
- package/core/frontend/services/routing/static-routes-router.js +1 -1
- package/core/frontend/services/routing/taxonomy-router.js +1 -1
- package/core/frontend/services/rss/generate-feed.js +1 -1
- package/core/frontend/services/sitemap/base-site-map-generator.js +23 -4
- package/core/frontend/services/sitemap/site-map-index-generator.js +1 -1
- package/core/frontend/services/sitemap/site-map-manager.js +14 -8
- package/core/frontend/services/sitemap/utils.js +1 -1
- package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +1 -1
- package/core/frontend/services/theme-engine/middleware/update-local-template-options.js +1 -1
- package/core/frontend/utils/images.js +1 -1
- package/core/frontend/web/middleware/admin-toolbar.js +1 -1
- package/core/frontend/web/middleware/handle-image-sizes.js +2 -2
- package/core/frontend/web/middleware/redirect-ghost-to-admin.js +1 -1
- package/core/frontend/web/routers/serve-favicon.js +1 -1
- package/core/frontend/web/routers/serve-public-file.js +1 -1
- package/core/frontend/web/site.js +5 -5
- package/core/server/adapters/cache/AdapterCacheMemoryTTL.js +2 -2
- package/core/server/adapters/cache/MemoryCache.js +2 -2
- package/core/server/adapters/cache/Redis.js +1 -1
- package/core/server/adapters/cache/index.js +1 -1
- package/core/server/adapters/lib/redis/AdapterCacheRedis.js +2 -2
- package/core/server/adapters/route-settings/FileStore.js +2 -8
- package/core/server/adapters/route-settings/FileStore.ts +1 -6
- package/core/server/adapters/route-settings/S3RouteSettingsStore.js +206 -0
- package/core/server/adapters/route-settings/S3RouteSettingsStore.ts +199 -0
- package/core/server/adapters/route-settings/utils.js +13 -0
- package/core/server/adapters/route-settings/utils.ts +7 -0
- package/core/server/adapters/scheduling/deps.d.ts +0 -2
- package/core/server/adapters/scheduling/error-capture.js +76 -0
- package/core/server/adapters/scheduling/error-capture.ts +91 -0
- package/core/server/adapters/scheduling/utils.js +18 -34
- package/core/server/adapters/scheduling/utils.ts +36 -0
- package/core/server/adapters/storage/LocalFilesStorage.js +1 -1
- package/core/server/adapters/storage/LocalImagesStorage.js +1 -1
- package/core/server/adapters/storage/LocalMediaStorage.js +1 -1
- package/core/server/adapters/storage/LocalStorageBase.js +3 -3
- package/core/server/adapters/storage/S3Storage.js +2 -2
- package/core/server/adapters/storage/S3Storage.ts +1 -1
- package/core/server/adapters/storage/utils.js +1 -1
- package/core/server/api/endpoints/authentication.js +1 -1
- package/core/server/api/endpoints/featurebase.js +1 -1
- package/core/server/api/endpoints/files.js +2 -2
- package/core/server/api/endpoints/images.js +2 -2
- package/core/server/api/endpoints/libraries.d.ts +0 -1
- package/core/server/api/endpoints/media.js +8 -5
- package/core/server/api/endpoints/member-custom-fields.js +4 -1
- package/core/server/api/endpoints/member-custom-fields.ts +4 -1
- package/core/server/api/endpoints/posts.js +17 -1
- package/core/server/api/endpoints/search-index-public.js +4 -3
- package/core/server/api/endpoints/search-index.js +5 -4
- package/core/server/api/endpoints/settings-public.js +1 -1
- package/core/server/api/endpoints/settings.js +3 -1
- package/core/server/api/endpoints/utils/serializers/input/utils/url.js +9 -1
- package/core/server/api/endpoints/utils/serializers/output/default.js +7 -0
- package/core/server/api/endpoints/utils/serializers/output/files.js +1 -1
- package/core/server/api/endpoints/utils/serializers/output/media.js +1 -1
- package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.js +7 -4
- package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.ts +8 -4
- package/core/server/api/endpoints/utils/serializers/output/members.js +16 -26
- package/core/server/api/endpoints/utils/serializers/output/pages.js +7 -0
- package/core/server/api/endpoints/utils/serializers/output/posts.js +13 -0
- package/core/server/api/endpoints/utils/serializers/output/utils/url.js +1 -1
- package/core/server/api/endpoints/utils/validators/input/members.js +2 -52
- package/core/server/data/db/backup.js +1 -1
- package/core/server/data/importer/handlers/image.js +3 -3
- package/core/server/data/importer/import-manager.js +6 -4
- package/core/server/data/importer/importers/content-file-importer.js +2 -2
- package/core/server/data/migrations/utils/schema.js +4 -2
- package/core/server/data/migrations/versions/6.54/2026-07-19-16-59-00-add-content-import-permission.js +10 -0
- package/core/server/data/migrations/versions/6.54/2026-07-20-13-59-21-drop-email-tracked-sent-count-from-automation-action-revisions.js +7 -0
- package/core/server/data/migrations/versions/6.54/2026-07-21-01-58-20-add-automation-run-steps-poller-index.js +3 -0
- package/core/server/data/migrations/versions/6.54/2026-07-21-21-08-15-add-automated-email-recipients-mailgun-message-id-index.js +3 -0
- package/core/server/data/migrations/versions/6.54/2026-07-22-10-41-08-add-click-tracking-to-automated-email-recipients.js +13 -0
- package/core/server/data/migrations/versions/6.54/2026-07-22-15-10-30-add-email-clicked-count-to-automation-action-revisions.js +7 -0
- package/core/server/data/migrations/versions/6.54/2026-07-23-10-24-18-add-automation-action-revision-to-redirects.js +9 -0
- package/core/server/data/schema/commands.js +37 -3
- package/core/server/data/schema/fixtures/fixtures.json +7 -0
- package/core/server/data/schema/lib/default-index-name.js +20 -0
- package/core/server/data/schema/schema.js +40 -17
- package/core/server/data/seeders/data-generator.js +4 -2
- package/core/server/lib/image/image-size.js +5 -7
- package/core/server/lib/image/image-utils.js +2 -2
- package/core/server/lib/image/index.js +4 -4
- package/core/server/lib/lexical.js +3 -3
- package/core/server/lib/mobiledoc.js +2 -2
- package/core/server/lib/validate-password.js +1 -1
- package/core/server/models/action.js +9 -0
- package/core/server/models/base/plugins/generate-slug.js +1 -1
- package/core/server/models/collection.js +1 -1
- package/core/server/models/custom-theme-setting.js +1 -1
- package/core/server/models/member.js +73 -0
- package/core/server/models/newsletter.js +1 -1
- package/core/server/models/post.js +19 -5
- package/core/server/models/posts-meta.js +1 -1
- package/core/server/models/redirect.js +1 -1
- package/core/server/models/settings.js +1 -1
- package/core/server/models/snippet.js +1 -1
- package/core/server/models/tag.js +1 -1
- package/core/server/models/user.js +1 -1
- package/core/server/models/welcome-email-automated-email.js +1 -1
- package/core/server/services/activitypub/activity-pub-service-wrapper.js +1 -1
- package/core/server/services/adapter-manager/adapter-manager.js +5 -1
- package/core/server/services/adapter-manager/adapter-manager.ts +7 -2
- package/core/server/services/adapter-manager/index.js +18 -15
- package/core/server/services/adapter-manager/index.ts +23 -17
- package/core/server/services/adapter-manager/utils.js +124 -14
- package/core/server/services/adapter-manager/utils.ts +130 -14
- package/core/server/services/api-version-compatibility/mw-version-rewrites.js +1 -1
- package/core/server/services/audience-feedback/index.js +1 -1
- package/core/server/services/auth/passwordreset.js +1 -1
- package/core/server/services/auth/session/express-session.js +1 -1
- package/core/server/services/auth/session/index.js +2 -2
- package/core/server/services/auth/session/session-service.js +1 -1
- package/core/server/services/automations/automations-api.js +2 -19
- package/core/server/services/automations/automations-api.ts +2 -31
- package/core/server/services/automations/automations-repository.ts +15 -0
- package/core/server/services/automations/database-automations-repository.js +30 -2
- package/core/server/services/automations/database-automations-repository.ts +33 -2
- package/core/server/services/automations/poll.js +16 -12
- package/core/server/services/automations/poll.ts +17 -15
- package/core/server/services/automations/service.js +1 -1
- package/core/server/services/automations/service.ts +3 -13
- package/core/server/services/automations/welcome-email-automation-poll.js +2 -1
- package/core/server/services/comments/index.js +1 -1
- package/core/server/services/custom-redirects/index.js +2 -2
- package/core/server/services/email-analytics/email-analytics-service-wrapper.js +14 -13
- package/core/server/services/email-analytics/email-analytics-service.js +1 -1
- package/core/server/services/email-analytics/events/start-email-analytics-job-event.js +11 -15
- package/core/server/services/email-analytics/events/start-email-analytics-job-event.ts +15 -0
- package/core/server/services/email-analytics/index.js +2 -3
- package/core/server/services/email-analytics/index.ts +1 -2
- package/core/server/services/email-analytics/jobs/email-analytics-job-scheduler.js +1 -6
- package/core/server/services/email-analytics/jobs/email-analytics-job-scheduler.ts +0 -9
- package/core/server/services/email-analytics/jobs/fetch-latest/index.js +1 -1
- package/core/server/services/email-analytics/jobs/index.js +0 -2
- package/core/server/services/email-service/email-service-wrapper.js +1 -1
- package/core/server/services/email-service/email-service.js +20 -4
- package/core/server/services/explore-ping/explore-ping-service.js +24 -39
- package/core/server/services/explore-ping/explore-ping-service.ts +198 -0
- package/core/server/services/explore-ping/index.js +11 -11
- package/core/server/services/explore-ping/index.ts +42 -0
- package/core/server/services/gifts/gift-reminder-scheduler.js +1 -1
- package/core/server/services/gifts/gift-reminder-scheduler.ts +1 -1
- package/core/server/services/gifts/gift-service-wrapper.js +1 -1
- package/core/server/services/identity-tokens/identity-token-service-wrapper.js +1 -1
- package/core/server/services/indexnow-ping/constants.js +30 -0
- package/core/server/services/indexnow-ping/constants.ts +32 -0
- package/core/server/services/indexnow-ping/index.js +29 -253
- package/core/server/services/indexnow-ping/index.ts +37 -0
- package/core/server/services/indexnow-ping/indexnow-ping-service.js +229 -0
- package/core/server/services/indexnow-ping/indexnow-ping-service.ts +319 -0
- package/core/server/services/invites/index.js +1 -1
- package/core/server/services/lib/mailgun-client.js +3 -3
- package/core/server/services/link-redirection/index.js +2 -2
- package/core/server/services/link-redirection/link-redirect-repository.js +1 -1
- package/core/server/services/link-redirection/link-redirect.js +12 -13
- package/core/server/services/link-redirection/link-redirect.ts +22 -0
- package/core/server/services/link-redirection/link-redirects-service.js +1 -1
- package/core/server/services/link-tracking/full-post-link.js +2 -2
- package/core/server/services/link-tracking/index.js +1 -1
- package/core/server/services/mail/ghost-mailer.js +1 -1
- package/core/server/services/mail/index.js +1 -1
- package/core/server/services/media-inliner/external-media-inliner.js +2 -2
- package/core/server/services/media-inliner/service.js +4 -3
- package/core/server/services/member-attribution/index.js +1 -1
- package/core/server/services/member-welcome-emails/service.js +1 -1
- package/core/server/services/members/api.js +8 -2
- package/core/server/services/members/csv/index.js +10 -0
- package/core/server/services/members/csv/index.ts +3 -0
- package/core/server/services/members/csv/parse.js +94 -0
- package/core/server/services/members/csv/parse.ts +111 -0
- package/core/server/services/members/csv/types.js +2 -0
- package/core/server/services/members/csv/types.ts +39 -0
- package/core/server/services/members/csv/unparse.js +69 -0
- package/core/server/services/members/csv/unparse.ts +79 -0
- package/core/server/services/members/exporter/query.js +35 -8
- package/core/server/services/members/importer/config.js +35 -0
- package/core/server/services/members/importer/config.ts +39 -0
- package/core/server/services/members/importer/members-csv-importer.js +31 -13
- package/core/server/services/members/members-api/members-api.js +4 -2
- package/core/server/services/members/members-api/repositories/event-repository.js +13 -2
- package/core/server/services/members/members-api/services/member-bread-service.js +42 -19
- package/core/server/services/members/middleware.js +1 -1
- package/core/server/services/members/service.js +15 -2
- package/core/server/services/members/stripe-connect.js +1 -1
- package/core/server/services/members-custom-fields/actions.js +3 -0
- package/core/server/services/members-custom-fields/actions.ts +6 -2
- package/core/server/services/members-custom-fields/config.js +34 -0
- package/core/server/services/members-custom-fields/config.ts +38 -0
- package/core/server/services/members-custom-fields/definitions-service.js +156 -21
- package/core/server/services/members-custom-fields/definitions-service.ts +170 -25
- package/core/server/services/members-custom-fields/index.js +16 -3
- package/core/server/services/members-custom-fields/index.ts +17 -3
- package/core/server/services/members-custom-fields/values-service.js +56 -10
- package/core/server/services/members-custom-fields/values-service.ts +62 -10
- package/core/server/services/mentions/mention-sending-service.js +22 -2
- package/core/server/services/mentions/service.js +21 -5
- package/core/server/services/newsletters/index.js +1 -1
- package/core/server/services/oembed/oembed-service.js +122 -33
- package/core/server/services/oembed/service.js +4 -2
- package/core/server/services/offers/service.js +1 -1
- package/core/server/services/post-scheduling/index.js +4 -3
- package/core/server/services/post-scheduling/index.ts +4 -3
- package/core/server/services/post-scheduling/post-scheduling.js +1 -1
- package/core/server/services/post-scheduling/post-scheduling.ts +1 -1
- package/core/server/services/posts/post-email-handler.js +13 -6
- package/core/server/services/posts/post-scheduling.js +1 -1
- package/core/server/services/posts/posts-service-instance.js +1 -1
- package/core/server/services/posts/posts-service.js +2 -2
- package/core/server/services/posts-public/service.js +1 -1
- package/core/server/services/public-config/site.js +1 -1
- package/core/server/services/recommendations/recommendation-service-wrapper.js +1 -1
- package/core/server/services/recommendations/service/libraries.d.ts +0 -2
- package/core/server/services/route-settings/dynamic-routing-service.js +2 -3
- package/core/server/services/route-settings/index.js +1 -1
- package/core/server/services/route-settings/route-settings-parser.js +134 -124
- package/core/server/services/route-settings/route-settings-parser.ts +160 -125
- package/core/server/services/route-settings/validation-errors.js +178 -0
- package/core/server/services/route-settings/validation-errors.ts +196 -0
- package/core/server/services/settings/settings-service.js +2 -2
- package/core/server/services/settings-helpers/index.js +1 -1
- package/core/server/services/slack-notifications/service.js +1 -1
- package/core/server/services/slack-ping/constants.js +16 -0
- package/core/server/services/slack-ping/constants.ts +15 -0
- package/core/server/services/slack-ping/index.js +26 -204
- package/core/server/services/slack-ping/index.ts +35 -0
- package/core/server/services/slack-ping/slack-ping-service.js +214 -0
- package/core/server/services/slack-ping/slack-ping-service.ts +296 -0
- package/core/server/services/staff/index.js +1 -1
- package/core/server/services/stats/posts-stats-service.js +1 -1
- package/core/server/services/stats/service.js +1 -1
- package/core/server/services/stripe/service.js +1 -1
- package/core/server/services/tags-public/service.js +1 -1
- package/core/server/services/themes/validate.js +1 -1
- package/core/server/services/update-check/index.js +1 -1
- package/core/server/services/url/lazy-url-service.js +66 -6
- package/core/server/services/url/lazy-url-service.ts +73 -6
- package/core/server/services/url/url-generator.js +1 -1
- package/core/server/services/url/url-service-facade.js +68 -3
- package/core/server/services/url/url-service-facade.ts +79 -4
- package/core/server/services/url/url-service.js +1 -1
- package/core/server/services/url/urls.js +1 -1
- package/core/server/services/webhooks/index.js +19 -2
- package/core/server/services/webhooks/listen.js +6 -11
- package/core/server/services/webhooks/payload.js +1 -3
- package/core/server/services/webhooks/serialize.js +16 -1
- package/core/server/web/admin/app.js +1 -1
- package/core/server/web/admin/middleware/redirect-admin-urls.js +1 -1
- package/core/server/web/api/endpoints/admin/routes.js +1 -0
- package/core/server/web/api/middleware/cors.js +1 -1
- package/core/server/web/api/middleware/upload.js +4 -0
- package/core/server/web/gift-preview/controller.js +1 -1
- package/core/server/web/shared/middleware/redirect-amp-urls.js +1 -1
- package/core/server/web/shared/middleware/uncapitalise.js +2 -2
- package/core/server/web/shared/middleware/url-redirects.js +1 -1
- package/core/shared/config/defaults.json +8 -1
- package/core/shared/config/overrides.json +4 -0
- package/core/shared/url-utils.js +19 -15
- package/core/shared/url-utils.ts +20 -0
- package/ghost.js +0 -1
- package/package.json +26 -31
- package/pnpm-lock.yaml +681 -2789
- package/pnpm-workspace.yaml +31 -17
- package/components/tryghost-adapter-base-scheduling-0.0.0.tgz +0 -0
- package/components/tryghost-adapter-base-sso-0.0.0.tgz +0 -0
- package/core/built/admin/assets/Combination--5EZGaDs.js +0 -43
- package/core/built/admin/assets/Growth-C0NoKcHQ.js +0 -3
- package/core/built/admin/assets/Newsletters-Ed8kDjdy.js +0 -1
- package/core/built/admin/assets/Overview-CArPgRZt.js +0 -1
- package/core/built/admin/assets/Web-CjjYoVM3.js +0 -2
- package/core/built/admin/assets/account-migration-mfa5mNI9.js +0 -1
- package/core/built/admin/assets/activitypub/inbox-B3rjKMTv.js +0 -1221
- package/core/built/admin/assets/activitypub/layout-jcurg3rU.js +0 -1
- package/core/built/admin/assets/activitypub/use-activity-pub-queries-yqGRcnLn.js +0 -2569
- package/core/built/admin/assets/activitypub/users-CfyHIsTG.js +0 -1316
- package/core/built/admin/assets/automations-DkUnxNdv.js +0 -1
- package/core/built/admin/assets/automations-vjXofmV_.js +0 -1
- package/core/built/admin/assets/bluesky-sharing-T-pO3RcP.js +0 -1
- package/core/built/admin/assets/breadcrumb-CekPYTCn.js +0 -1
- package/core/built/admin/assets/button--i2uMDDn.js +0 -4
- package/core/built/admin/assets/card-CSWz_BXq.js +0 -1
- package/core/built/admin/assets/chart-helpers-C_4Ka_vT.js +0 -1
- package/core/built/admin/assets/chunk.524.8ce2c741473e2f0929dc.js +0 -25
- package/core/built/admin/assets/chunk.582.453459d6228d2955408b.js +0 -27
- package/core/built/admin/assets/code-editor-view-BfkwQto2.js +0 -1
- package/core/built/admin/assets/command-K75Jzs0G.js +0 -1
- package/core/built/admin/assets/comments-BEIi1DH-.js +0 -1
- package/core/built/admin/assets/container-BNXvlcjA.js +0 -1
- package/core/built/admin/assets/data-list-BmK5QMab.js +0 -1
- package/core/built/admin/assets/date-range-select-5sKzwbt7.js +0 -1
- package/core/built/admin/assets/disabled-sources-indicator-L_ssJTNr.js +0 -1
- package/core/built/admin/assets/dist-BBIJuyPg.js +0 -1
- package/core/built/admin/assets/dist-BHE0dp6o.js +0 -1
- package/core/built/admin/assets/dist-DJ6c4_De.js +0 -1
- package/core/built/admin/assets/dist-DW0QXQO3.js +0 -1
- package/core/built/admin/assets/dist-DxFLceO5.js +0 -1
- package/core/built/admin/assets/dist-QcACAOAD.js +0 -1
- package/core/built/admin/assets/dist-duxRDcQu.js +0 -177
- package/core/built/admin/assets/domain-CLaPZ9Rc.js +0 -1
- package/core/built/admin/assets/dropzone-E0bSX4_a.js +0 -5
- package/core/built/admin/assets/edit-profile-DqNPKaA4.js +0 -1
- package/core/built/admin/assets/editor-CkLXQDRp.js +0 -8
- package/core/built/admin/assets/empty-indicator-BTtOlgIo.js +0 -1
- package/core/built/admin/assets/esm-TSfGW7nz.js +0 -2
- package/core/built/admin/assets/explore-BEstLxKr.js +0 -1
- package/core/built/admin/assets/feed-C58p2voG.js +0 -1
- package/core/built/admin/assets/field-BSbDUHPv.js +0 -1
- package/core/built/admin/assets/filters-BgYv8Gt7.js +0 -1
- package/core/built/admin/assets/filters-DvenFkmK.js +0 -1
- package/core/built/admin/assets/framework-provider-jQktxm9P.js +0 -4
- package/core/built/admin/assets/ghost-dark-8590dea6cd695ff90f27d262c4464538.css +0 -1
- package/core/built/admin/assets/gift-link-modal-BPjXkEFt.js +0 -1
- package/core/built/admin/assets/growth-D4JNiVTe.js +0 -1
- package/core/built/admin/assets/hooks-Cjxexi_I.js +0 -2
- package/core/built/admin/assets/index-BacwlcOy.js +0 -67
- package/core/built/admin/assets/index-DxRNHH0o.css +0 -1
- package/core/built/admin/assets/inline-C22rnPro.js +0 -1
- package/core/built/admin/assets/input-group-CKfrILLP.js +0 -1
- package/core/built/admin/assets/jsx-runtime-CtMZ-PAS.js +0 -1
- package/core/built/admin/assets/kpi-card-DZxQKAIb.js +0 -1
- package/core/built/admin/assets/kpi-card-FidQ5zg3.js +0 -1
- package/core/built/admin/assets/kpi-helpers-C5T8Vaf1.js +0 -1
- package/core/built/admin/assets/kpi-tabs-_VRK6hGV.js +0 -1
- package/core/built/admin/assets/label-Cza7hPgn.js +0 -1
- package/core/built/admin/assets/label-picker-DgC_zLaw.js +0 -1
- package/core/built/admin/assets/layout-BxsXnKFX.js +0 -1
- package/core/built/admin/assets/limit-service-CTurluJQ.js +0 -20
- package/core/built/admin/assets/link-helpers-C3Gqy2cz.js +0 -1
- package/core/built/admin/assets/list-page-BtqCnow_.js +0 -1
- package/core/built/admin/assets/member-custom-fields-9uXFBqSt.js +0 -1
- package/core/built/admin/assets/member-detail-Dq6ZDIxo.js +0 -1
- package/core/built/admin/assets/members-CUWD9jal.js +0 -10
- package/core/built/admin/assets/modals-CIdwHVga.js +0 -31
- package/core/built/admin/assets/moderation-DTt04UDA.js +0 -1
- package/core/built/admin/assets/newsletter-cC8vcc9h.js +0 -1
- package/core/built/admin/assets/note-DZU0IY9e.js +0 -1
- package/core/built/admin/assets/notifications-NoHpBHJ4.js +0 -1
- package/core/built/admin/assets/nql-lang-CvCSOQG3.js +0 -19
- package/core/built/admin/assets/onboarding-route-Deg2hNm8.js +0 -1
- package/core/built/admin/assets/overview-BQPt_9w3.js +0 -1
- package/core/built/admin/assets/page-header-D6bEqPo2.js +0 -1
- package/core/built/admin/assets/post-analytics-header-BPw_B2_D.js +0 -1
- package/core/built/admin/assets/post-analytics-kp2_--XO.js +0 -1
- package/core/built/admin/assets/post-share-modal-Cave3Z4W.js +0 -1
- package/core/built/admin/assets/preferences-C7h3j_uy.js +0 -5
- package/core/built/admin/assets/profile-B2x4q2oB.js +0 -1
- package/core/built/admin/assets/router-provider-5fsX1CYn.js +0 -1
- package/core/built/admin/assets/select-PhPjIBBT.js +0 -1
- package/core/built/admin/assets/settings-D5P9Gwgo.js +0 -6
- package/core/built/admin/assets/settings-zUOzQV5I.js +0 -1
- package/core/built/admin/assets/share-modal-EfpfbuWF.js +0 -1
- package/core/built/admin/assets/social-urls-DgAF08Xc.js +0 -18
- package/core/built/admin/assets/sort-button-WOQYJm2H.js +0 -1
- package/core/built/admin/assets/source-icon-hm8Cj-Gx.js +0 -1
- package/core/built/admin/assets/stats-CnQDb62m.js +0 -1
- package/core/built/admin/assets/stats-view-CCfTJgSe.js +0 -1
- package/core/built/admin/assets/step-1-BGlhY4DS.js +0 -1
- package/core/built/admin/assets/step-2-D3sDEyFH.js +0 -1
- package/core/built/admin/assets/step-3-CvZoUdsc.js +0 -2
- package/core/built/admin/assets/switch-CNjkOmwz.js +0 -1
- package/core/built/admin/assets/table-C5nZYPnW.js +0 -1
- package/core/built/admin/assets/tabs-dtOcExye.js +0 -1
- package/core/built/admin/assets/tags-Dhm0FB_g.js +0 -1
- package/core/built/admin/assets/textarea-CeKw3wmV.js +0 -1
- package/core/built/admin/assets/toggle-group-DfhZIMTW.js +0 -1
- package/core/built/admin/assets/topic-filter-Cxe1Il41.js +0 -1
- package/core/built/admin/assets/typeof-Ca-duI-z.js +0 -1
- package/core/built/admin/assets/use-filter-params-Bub6BqNy.js +0 -1
- package/core/built/admin/assets/use-growth-stats-BJORomv0.js +0 -1
- package/core/built/admin/assets/use-reply-chain-data-B89YjVoo.js +0 -1
- package/core/built/admin/assets/use-simple-pagination-BL2SYXKi.js +0 -1
- package/core/built/admin/assets/virtual-list-DNJOSK9I.js +0 -1
- package/core/built/admin/assets/web-BHUE3YQc.js +0 -1
- package/core/server/adapters/scheduling/scheduling-base.js +0 -5
- package/core/server/adapters/sso/SSOBase.js +0 -5
- package/core/server/adapters/storage/index.js +0 -17
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import {
|
|
4
|
+
CopyObjectCommand,
|
|
5
|
+
GetObjectCommand,
|
|
6
|
+
HeadObjectCommand,
|
|
7
|
+
NoSuchKey,
|
|
8
|
+
NotFound,
|
|
9
|
+
PutObjectCommand,
|
|
10
|
+
S3Client,
|
|
11
|
+
S3ClientConfig
|
|
12
|
+
} from '@aws-sdk/client-s3';
|
|
13
|
+
import {z} from 'zod';
|
|
14
|
+
import tpl from '@tryghost/tpl';
|
|
15
|
+
import * as errors from '@tryghost/errors';
|
|
16
|
+
import {RouteSettingsStoreBase, type RouteSettings} from '@tryghost/adapter-base-route-settings';
|
|
17
|
+
|
|
18
|
+
import parseYaml from '../../services/route-settings/yaml-parser';
|
|
19
|
+
import {parseRouteSettings} from '../../services/route-settings/route-settings-parser';
|
|
20
|
+
import {getBackupRouteSettingsFilePath} from './utils';
|
|
21
|
+
|
|
22
|
+
const YAML_FILENAME = 'routes.yaml';
|
|
23
|
+
const DEFAULT_SETTINGS_FILENAME = 'default-routes.yaml';
|
|
24
|
+
|
|
25
|
+
const CONTENT_TYPE = 'application/yaml; charset=utf-8';
|
|
26
|
+
|
|
27
|
+
const messages = {
|
|
28
|
+
missingBucket: 'S3RouteSettingsStore requires a bucket name',
|
|
29
|
+
missingStaticFileURLPrefix: 'S3RouteSettingsStore requires a staticFileURLPrefix',
|
|
30
|
+
missingDefaultSettingsBasePath: 'S3RouteSettingsStore requires a defaultSettingsBasePath',
|
|
31
|
+
partialCredentials: 'S3RouteSettingsStore requires both accessKeyId and secretAccessKey when either is provided',
|
|
32
|
+
missingResponseBody: 'S3 GetObject returned no body',
|
|
33
|
+
ensureDefaults: 'Error trying to access the default settings file in {path}.'
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const stripLeadingAndTrailingSlashes = (value = '') => value.replace(/^\/+|\/+$/g, '');
|
|
37
|
+
|
|
38
|
+
const configSchema = z.object({
|
|
39
|
+
bucket: z.string({error: tpl(messages.missingBucket)}).min(1, {error: tpl(messages.missingBucket)}),
|
|
40
|
+
staticFileURLPrefix: z.string({error: tpl(messages.missingStaticFileURLPrefix)})
|
|
41
|
+
.transform(stripLeadingAndTrailingSlashes)
|
|
42
|
+
.refine(value => value.length > 0, {error: tpl(messages.missingStaticFileURLPrefix)}),
|
|
43
|
+
defaultSettingsBasePath: z.string({error: tpl(messages.missingDefaultSettingsBasePath)})
|
|
44
|
+
.min(1, {error: tpl(messages.missingDefaultSettingsBasePath)}),
|
|
45
|
+
tenantPrefix: z.string().transform(stripLeadingAndTrailingSlashes).optional(),
|
|
46
|
+
region: z.string().optional(),
|
|
47
|
+
endpoint: z.string().optional(),
|
|
48
|
+
forcePathStyle: z.boolean().optional(),
|
|
49
|
+
accessKeyId: z.string().optional(),
|
|
50
|
+
secretAccessKey: z.string().optional(),
|
|
51
|
+
sessionToken: z.string().optional()
|
|
52
|
+
}).refine((config) => {
|
|
53
|
+
const hasAccessKey = Boolean(config.accessKeyId);
|
|
54
|
+
const hasSecretKey = Boolean(config.secretAccessKey);
|
|
55
|
+
const hasSessionToken = Boolean(config.sessionToken);
|
|
56
|
+
const hasCredentialPair = hasAccessKey && hasSecretKey;
|
|
57
|
+
return !((hasAccessKey || hasSecretKey || hasSessionToken) && !hasCredentialPair);
|
|
58
|
+
}, {error: tpl(messages.partialCredentials)});
|
|
59
|
+
|
|
60
|
+
export type S3RouteSettingsStoreOptions = z.infer<typeof configSchema>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Remote store for route settings backed by an S3-compatible bucket (MinIO in
|
|
64
|
+
* tests, GCS in production). Reads and writes the operator's original
|
|
65
|
+
* `routes.yaml` verbatim.
|
|
66
|
+
*/
|
|
67
|
+
export default class S3RouteSettingsStore extends RouteSettingsStoreBase {
|
|
68
|
+
private readonly client: S3Client;
|
|
69
|
+
private readonly bucket: string;
|
|
70
|
+
private readonly staticFileURLPrefix: string;
|
|
71
|
+
private readonly tenantPrefix: string;
|
|
72
|
+
private readonly defaultSettingsBasePath: string;
|
|
73
|
+
|
|
74
|
+
private static parseConfig(config: unknown): z.infer<typeof configSchema> {
|
|
75
|
+
const result = configSchema.safeParse(config);
|
|
76
|
+
if (!result.success) {
|
|
77
|
+
throw new errors.IncorrectUsageError({
|
|
78
|
+
message: [...new Set(result.error.issues.map(issue => issue.message))].join('; ')
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return result.data;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static validate(config: unknown): asserts config is S3RouteSettingsStoreOptions {
|
|
85
|
+
S3RouteSettingsStore.parseConfig(config);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
constructor(config: unknown) {
|
|
89
|
+
super();
|
|
90
|
+
|
|
91
|
+
const options = S3RouteSettingsStore.parseConfig(config);
|
|
92
|
+
|
|
93
|
+
const hasCredentialPair = Boolean(options.accessKeyId) && Boolean(options.secretAccessKey);
|
|
94
|
+
|
|
95
|
+
this.bucket = options.bucket;
|
|
96
|
+
this.staticFileURLPrefix = options.staticFileURLPrefix;
|
|
97
|
+
this.tenantPrefix = options.tenantPrefix ?? '';
|
|
98
|
+
this.defaultSettingsBasePath = options.defaultSettingsBasePath;
|
|
99
|
+
|
|
100
|
+
const clientConfig: S3ClientConfig = {
|
|
101
|
+
region: options.region,
|
|
102
|
+
endpoint: options.endpoint,
|
|
103
|
+
forcePathStyle: options.forcePathStyle
|
|
104
|
+
};
|
|
105
|
+
if (hasCredentialPair) {
|
|
106
|
+
clientConfig.credentials = {
|
|
107
|
+
accessKeyId: options.accessKeyId!,
|
|
108
|
+
secretAccessKey: options.secretAccessKey!,
|
|
109
|
+
sessionToken: options.sessionToken
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// `s3Client` is a test-only injection seam — it never comes from config
|
|
114
|
+
// (nconf holds static values), so it's read from the raw input rather
|
|
115
|
+
// than the validated schema output.
|
|
116
|
+
const injectedClient = (config as {s3Client?: S3Client} | null | undefined)?.s3Client;
|
|
117
|
+
this.client = injectedClient || new S3Client(clientConfig);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async get(): Promise<RouteSettings> {
|
|
121
|
+
let body: string;
|
|
122
|
+
try {
|
|
123
|
+
const response = await this.client.send(new GetObjectCommand({
|
|
124
|
+
Bucket: this.bucket,
|
|
125
|
+
Key: this.buildKey()
|
|
126
|
+
}));
|
|
127
|
+
if (!response.Body) {
|
|
128
|
+
throw new errors.InternalServerError({
|
|
129
|
+
message: tpl(messages.missingResponseBody)
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
body = await response.Body.transformToString('utf-8');
|
|
133
|
+
} catch (err) {
|
|
134
|
+
if (this._isNotFound(err)) {
|
|
135
|
+
const defaultContent = await this.readDefaultSettings();
|
|
136
|
+
return parseRouteSettings(parseYaml(defaultContent), defaultContent);
|
|
137
|
+
}
|
|
138
|
+
throw err;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return parseRouteSettings(parseYaml(body), body);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async replace(settings: RouteSettings): Promise<void> {
|
|
145
|
+
const key = this.buildKey();
|
|
146
|
+
|
|
147
|
+
if (await this._canonicalExists()) {
|
|
148
|
+
await this.client.send(new CopyObjectCommand({
|
|
149
|
+
Bucket: this.bucket,
|
|
150
|
+
Key: getBackupRouteSettingsFilePath(key),
|
|
151
|
+
CopySource: `${this.bucket}/${key}`
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
await this.client.send(new PutObjectCommand({
|
|
156
|
+
Bucket: this.bucket,
|
|
157
|
+
Key: key,
|
|
158
|
+
Body: settings.yamlSource,
|
|
159
|
+
ContentType: CONTENT_TYPE
|
|
160
|
+
}));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private buildKey(): string {
|
|
164
|
+
const parts = [this.tenantPrefix, this.staticFileURLPrefix, YAML_FILENAME].filter(Boolean);
|
|
165
|
+
return parts.join('/');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private async _canonicalExists(): Promise<boolean> {
|
|
169
|
+
try {
|
|
170
|
+
await this.client.send(new HeadObjectCommand({
|
|
171
|
+
Bucket: this.bucket,
|
|
172
|
+
Key: this.buildKey()
|
|
173
|
+
}));
|
|
174
|
+
return true;
|
|
175
|
+
} catch (err) {
|
|
176
|
+
if (this._isNotFound(err)) {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
throw err;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private async readDefaultSettings(): Promise<string> {
|
|
184
|
+
const defaultFilePath = path.join(this.defaultSettingsBasePath, DEFAULT_SETTINGS_FILENAME);
|
|
185
|
+
try {
|
|
186
|
+
return await fs.readFile(defaultFilePath, 'utf8');
|
|
187
|
+
} catch (err) {
|
|
188
|
+
throw new errors.InternalServerError({
|
|
189
|
+
message: tpl(messages.ensureDefaults, {path: this.defaultSettingsBasePath}),
|
|
190
|
+
err: err as Error,
|
|
191
|
+
context: (err as NodeJS.ErrnoException).path
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private _isNotFound(err: unknown): boolean {
|
|
197
|
+
return err instanceof NotFound || err instanceof NoSuchKey;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getBackupRouteSettingsFilePath = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const date_fns_1 = require("date-fns");
|
|
9
|
+
const getBackupRouteSettingsFilePath = (filePath) => {
|
|
10
|
+
const { dir, name, ext } = path_1.default.parse(filePath);
|
|
11
|
+
return path_1.default.join(dir, `${name}-${(0, date_fns_1.format)(new Date(), 'yyyy-MM-dd-HH-mm-ss')}${ext}`);
|
|
12
|
+
};
|
|
13
|
+
exports.getBackupRouteSettingsFilePath = getBackupRouteSettingsFilePath;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import {format} from 'date-fns';
|
|
3
|
+
|
|
4
|
+
export const getBackupRouteSettingsFilePath = (filePath: string): string => {
|
|
5
|
+
const {dir, name, ext} = path.parse(filePath);
|
|
6
|
+
return path.join(dir, `${name}-${format(new Date(), 'yyyy-MM-dd-HH-mm-ss')}${ext}`);
|
|
7
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ErrorCapturingSchedulingAdapter = void 0;
|
|
7
|
+
exports.withErrorCapture = withErrorCapture;
|
|
8
|
+
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
9
|
+
// CJS-only module without TS declarations.
|
|
10
|
+
// TODO: replace with dependency injection once the sentry module is TS
|
|
11
|
+
const sentry = require('../../../shared/sentry');
|
|
12
|
+
/**
|
|
13
|
+
* Job URLs carry a signed admin token in their query string which stays valid
|
|
14
|
+
* for hours after the scheduled time, so only the path is safe to report.
|
|
15
|
+
*/
|
|
16
|
+
function redactToken(url) {
|
|
17
|
+
return url.split('?')[0];
|
|
18
|
+
}
|
|
19
|
+
function report(err, operation, job) {
|
|
20
|
+
sentry.captureException(err);
|
|
21
|
+
logging_1.default.error({
|
|
22
|
+
event: { name: `scheduler.${operation}.failed` },
|
|
23
|
+
err,
|
|
24
|
+
url: redactToken(job.url),
|
|
25
|
+
time: job.time
|
|
26
|
+
}, `Scheduler failed to ${operation} a job`);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Decorates a scheduling adapter so that failures from `schedule`/`unschedule`
|
|
30
|
+
* are reported by Ghost rather than by each adapter. Adapters signal failure
|
|
31
|
+
* however the contract permits — throwing, or rejecting the returned promise —
|
|
32
|
+
* and both are handled here.
|
|
33
|
+
*
|
|
34
|
+
* Failures are reported rather than propagated because no caller awaits these:
|
|
35
|
+
* `rescheduleAll` queues one job per scheduled post, and awaiting each would
|
|
36
|
+
* stall boot behind an adapter's rate limiting.
|
|
37
|
+
*/
|
|
38
|
+
class ErrorCapturingSchedulingAdapter {
|
|
39
|
+
#adapter;
|
|
40
|
+
constructor(adapter) {
|
|
41
|
+
this.#adapter = adapter;
|
|
42
|
+
}
|
|
43
|
+
get rescheduleOnBoot() {
|
|
44
|
+
return this.#adapter.rescheduleOnBoot;
|
|
45
|
+
}
|
|
46
|
+
run() {
|
|
47
|
+
return this.#adapter.run();
|
|
48
|
+
}
|
|
49
|
+
register(rescheduler) {
|
|
50
|
+
this.#adapter.register(rescheduler);
|
|
51
|
+
}
|
|
52
|
+
rescheduleAll(opts) {
|
|
53
|
+
return this.#adapter.rescheduleAll(opts);
|
|
54
|
+
}
|
|
55
|
+
schedule(job) {
|
|
56
|
+
this.#capture(() => this.#adapter.schedule(job), 'schedule', job);
|
|
57
|
+
}
|
|
58
|
+
unschedule(job, opts) {
|
|
59
|
+
this.#capture(() => this.#adapter.unschedule(job, opts), 'unschedule', job);
|
|
60
|
+
}
|
|
61
|
+
#capture(run, operation, job) {
|
|
62
|
+
try {
|
|
63
|
+
const result = run();
|
|
64
|
+
if (result) {
|
|
65
|
+
Promise.resolve(result).catch(err => report(err, operation, job));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
report(err, operation, job);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.ErrorCapturingSchedulingAdapter = ErrorCapturingSchedulingAdapter;
|
|
74
|
+
function withErrorCapture(adapter) {
|
|
75
|
+
return new ErrorCapturingSchedulingAdapter(adapter);
|
|
76
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import logging from '@tryghost/logging';
|
|
2
|
+
import type {RescheduleOpts, Rescheduler, SchedulerAdapter, SchedulerJob} from '@tryghost/adapter-base-scheduling';
|
|
3
|
+
|
|
4
|
+
// CJS-only module without TS declarations.
|
|
5
|
+
// TODO: replace with dependency injection once the sentry module is TS
|
|
6
|
+
const sentry = require('../../../shared/sentry');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The surface Ghost consumes from a resolved scheduling adapter: the
|
|
10
|
+
* `SchedulerAdapter` contract, plus the members `SchedulingBase` supplies that
|
|
11
|
+
* the contract itself doesn't declare.
|
|
12
|
+
*/
|
|
13
|
+
export interface SchedulingAdapter extends SchedulerAdapter {
|
|
14
|
+
rescheduleAll(opts?: RescheduleOpts): Promise<unknown>;
|
|
15
|
+
rescheduleOnBoot?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Job URLs carry a signed admin token in their query string which stays valid
|
|
20
|
+
* for hours after the scheduled time, so only the path is safe to report.
|
|
21
|
+
*/
|
|
22
|
+
function redactToken(url: string): string {
|
|
23
|
+
return url.split('?')[0];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function report(err: unknown, operation: 'schedule' | 'unschedule', job: SchedulerJob): void {
|
|
27
|
+
sentry.captureException(err);
|
|
28
|
+
logging.error({
|
|
29
|
+
event: {name: `scheduler.${operation}.failed`},
|
|
30
|
+
err,
|
|
31
|
+
url: redactToken(job.url),
|
|
32
|
+
time: job.time
|
|
33
|
+
}, `Scheduler failed to ${operation} a job`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Decorates a scheduling adapter so that failures from `schedule`/`unschedule`
|
|
38
|
+
* are reported by Ghost rather than by each adapter. Adapters signal failure
|
|
39
|
+
* however the contract permits — throwing, or rejecting the returned promise —
|
|
40
|
+
* and both are handled here.
|
|
41
|
+
*
|
|
42
|
+
* Failures are reported rather than propagated because no caller awaits these:
|
|
43
|
+
* `rescheduleAll` queues one job per scheduled post, and awaiting each would
|
|
44
|
+
* stall boot behind an adapter's rate limiting.
|
|
45
|
+
*/
|
|
46
|
+
export class ErrorCapturingSchedulingAdapter implements SchedulingAdapter {
|
|
47
|
+
readonly #adapter: SchedulingAdapter;
|
|
48
|
+
|
|
49
|
+
constructor(adapter: SchedulingAdapter) {
|
|
50
|
+
this.#adapter = adapter;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get rescheduleOnBoot(): boolean | undefined {
|
|
54
|
+
return this.#adapter.rescheduleOnBoot;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
run(): void | Promise<void> {
|
|
58
|
+
return this.#adapter.run();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
register(rescheduler: Rescheduler): void {
|
|
62
|
+
this.#adapter.register(rescheduler);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
rescheduleAll(opts?: RescheduleOpts): Promise<unknown> {
|
|
66
|
+
return this.#adapter.rescheduleAll(opts);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
schedule(job: SchedulerJob): void {
|
|
70
|
+
this.#capture(() => this.#adapter.schedule(job), 'schedule', job);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
unschedule(job: SchedulerJob, opts?: {bootstrap?: boolean}): void {
|
|
74
|
+
this.#capture(() => this.#adapter.unschedule(job, opts), 'unschedule', job);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#capture(run: () => void | Promise<void>, operation: 'schedule' | 'unschedule', job: SchedulerJob): void {
|
|
78
|
+
try {
|
|
79
|
+
const result = run();
|
|
80
|
+
if (result) {
|
|
81
|
+
Promise.resolve(result).catch(err => report(err, operation, job));
|
|
82
|
+
}
|
|
83
|
+
} catch (err) {
|
|
84
|
+
report(err, operation, job);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function withErrorCapture(adapter: SchedulingAdapter): SchedulingAdapter {
|
|
90
|
+
return new ErrorCapturingSchedulingAdapter(adapter);
|
|
91
|
+
}
|
|
@@ -1,44 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
exports.createAdapter = function createAdapter() {
|
|
6
|
-
return adapterManager.getAdapter('scheduling');
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
4
|
};
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* @param {string} options.apiUrl - url of the JWT's audience
|
|
15
|
-
* @param {import('../../services/internal-keys').InternalApiKey} options.key
|
|
16
|
-
*
|
|
17
|
-
* @return {string} the JSON Web Token
|
|
18
|
-
*/
|
|
19
|
-
exports.getSignedAdminToken = function ({publishedAt, apiUrl, key}) {
|
|
20
|
-
const JWT_OPTIONS = /** @type {const} */ ({
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getSignedAdminToken = getSignedAdminToken;
|
|
7
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
8
|
+
const moment_1 = __importDefault(require("moment"));
|
|
9
|
+
function getSignedAdminToken({ publishedAt, apiUrl, key }) {
|
|
10
|
+
const opts = {
|
|
21
11
|
keyid: key.id,
|
|
22
12
|
algorithm: 'HS256',
|
|
23
13
|
audience: apiUrl,
|
|
24
14
|
noTimestamp: true
|
|
25
|
-
}
|
|
26
|
-
|
|
15
|
+
};
|
|
27
16
|
// Default token expiry is till 6 hours after scheduled time
|
|
28
17
|
// or if published_at is in past then till 6 hours after blog start
|
|
29
18
|
// to allow for retries in case of network issues
|
|
30
19
|
// and never before 10 mins to publish time
|
|
31
|
-
let tokenExpiry =
|
|
32
|
-
if (tokenExpiry.isBefore(
|
|
33
|
-
tokenExpiry =
|
|
20
|
+
let tokenExpiry = (0, moment_1.default)(publishedAt).add(6, 'h');
|
|
21
|
+
if (tokenExpiry.isBefore((0, moment_1.default)())) {
|
|
22
|
+
tokenExpiry = (0, moment_1.default)().add(6, 'h');
|
|
34
23
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
},
|
|
41
|
-
Buffer.from(key.secret, 'hex'),
|
|
42
|
-
JWT_OPTIONS
|
|
43
|
-
);
|
|
44
|
-
};
|
|
24
|
+
return jsonwebtoken_1.default.sign({
|
|
25
|
+
exp: tokenExpiry.unix(),
|
|
26
|
+
nbf: (0, moment_1.default)(publishedAt).subtract(10, 'm').unix(),
|
|
27
|
+
}, Buffer.from(key.secret, 'hex'), opts);
|
|
28
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import jwt, {type SignOptions} from 'jsonwebtoken'
|
|
2
|
+
import moment from 'moment'
|
|
3
|
+
import type {InternalApiKey} from '../../services/internal-keys'
|
|
4
|
+
|
|
5
|
+
type GetSignedAdminTokenOptions = {
|
|
6
|
+
publishedAt: string
|
|
7
|
+
apiUrl: string
|
|
8
|
+
key: InternalApiKey
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function getSignedAdminToken({publishedAt, apiUrl, key}: GetSignedAdminTokenOptions): string {
|
|
12
|
+
const opts: SignOptions = {
|
|
13
|
+
keyid: key.id,
|
|
14
|
+
algorithm: 'HS256',
|
|
15
|
+
audience: apiUrl,
|
|
16
|
+
noTimestamp: true
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Default token expiry is till 6 hours after scheduled time
|
|
20
|
+
// or if published_at is in past then till 6 hours after blog start
|
|
21
|
+
// to allow for retries in case of network issues
|
|
22
|
+
// and never before 10 mins to publish time
|
|
23
|
+
let tokenExpiry = moment(publishedAt).add(6, 'h');
|
|
24
|
+
if (tokenExpiry.isBefore(moment())) {
|
|
25
|
+
tokenExpiry = moment().add(6, 'h');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return jwt.sign(
|
|
29
|
+
{
|
|
30
|
+
exp: tokenExpiry.unix(),
|
|
31
|
+
nbf: moment(publishedAt).subtract(10, 'm').unix(),
|
|
32
|
+
},
|
|
33
|
+
Buffer.from(key.secret, 'hex'),
|
|
34
|
+
opts
|
|
35
|
+
);
|
|
36
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// # Local File System Storage module
|
|
2
2
|
// The (default) module for storing media, using the local file system
|
|
3
3
|
const config = require('../../../shared/config');
|
|
4
|
-
const urlUtils = require('../../../shared/url-utils');
|
|
4
|
+
const urlUtils = require('../../../shared/url-utils').default;
|
|
5
5
|
const LocalStorageBase = require('./LocalStorageBase');
|
|
6
6
|
|
|
7
7
|
const messages = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// # Local File System Image Storage module
|
|
2
2
|
// The (default) module for storing images, using the local file system
|
|
3
3
|
const config = require('../../../shared/config');
|
|
4
|
-
const urlUtils = require('../../../shared/url-utils');
|
|
4
|
+
const urlUtils = require('../../../shared/url-utils').default;
|
|
5
5
|
const LocalStorageBase = require('./LocalStorageBase');
|
|
6
6
|
|
|
7
7
|
let messages = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// # Local File System Media Storage module
|
|
2
2
|
// The (default) module for storing media, using the local file system
|
|
3
3
|
const config = require('../../../shared/config');
|
|
4
|
-
const urlUtils = require('../../../shared/url-utils');
|
|
4
|
+
const urlUtils = require('../../../shared/url-utils').default;
|
|
5
5
|
const LocalStorageBase = require('./LocalStorageBase');
|
|
6
6
|
|
|
7
7
|
const messages = {
|
|
@@ -6,8 +6,8 @@ const fs = require('fs-extra');
|
|
|
6
6
|
const path = require('path');
|
|
7
7
|
const tpl = require('@tryghost/tpl');
|
|
8
8
|
const errors = require('@tryghost/errors');
|
|
9
|
-
const urlUtils = require('../../../shared/url-utils');
|
|
10
|
-
const StorageBase = require('ghost-storage-base');
|
|
9
|
+
const urlUtils = require('../../../shared/url-utils').default;
|
|
10
|
+
const {StorageBase} = require('ghost-storage-base');
|
|
11
11
|
|
|
12
12
|
const messages = {
|
|
13
13
|
notFound: 'File not found',
|
|
@@ -112,7 +112,7 @@ class LocalStorageBase extends StorageBase {
|
|
|
112
112
|
* Saves the file to storage (the file system)
|
|
113
113
|
* - returns a promise which ultimately returns the full url to the uploaded file
|
|
114
114
|
*
|
|
115
|
-
* @param {
|
|
115
|
+
* @param {import('ghost-storage-base').StorageFile} file
|
|
116
116
|
* @param {string} targetDir
|
|
117
117
|
* @returns {Promise<String>}
|
|
118
118
|
*/
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
7
7
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
8
|
const zod_1 = require("zod");
|
|
9
|
-
const ghost_storage_base_1 =
|
|
9
|
+
const ghost_storage_base_1 = require("ghost-storage-base");
|
|
10
10
|
const tpl_1 = __importDefault(require("@tryghost/tpl"));
|
|
11
11
|
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
12
12
|
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
@@ -81,7 +81,7 @@ const configSchema = zod_1.z.object({
|
|
|
81
81
|
const hasCredentialPair = hasAccessKey && hasSecretKey;
|
|
82
82
|
return !((hasAccessKey || hasSecretKey || hasSessionToken) && !hasCredentialPair);
|
|
83
83
|
}, { error: (0, tpl_1.default)(messages.partialCredentials) });
|
|
84
|
-
class S3Storage extends ghost_storage_base_1.
|
|
84
|
+
class S3Storage extends ghost_storage_base_1.StorageBase {
|
|
85
85
|
client;
|
|
86
86
|
bucket;
|
|
87
87
|
tenantPrefix;
|
|
@@ -2,7 +2,7 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import type {Request, Response, NextFunction, RequestHandler} from 'express';
|
|
4
4
|
import {z} from 'zod';
|
|
5
|
-
import StorageBase from 'ghost-storage-base';
|
|
5
|
+
import {StorageBase} from 'ghost-storage-base';
|
|
6
6
|
import tpl from '@tryghost/tpl';
|
|
7
7
|
import errors from '@tryghost/errors';
|
|
8
8
|
import logging from '@tryghost/logging';
|
|
@@ -12,7 +12,7 @@ const apiMail = require('./index').mail;
|
|
|
12
12
|
const apiSettings = require('./index').settings;
|
|
13
13
|
const UsersService = require('../../services/users');
|
|
14
14
|
const userService = new UsersService({dbBackup, models, auth, apiMail, apiSettings});
|
|
15
|
-
const adapterManager = require('../../services/adapter-manager');
|
|
15
|
+
const adapterManager = require('../../services/adapter-manager').default;
|
|
16
16
|
const schedulerAdapter = adapterManager.getAdapter('scheduling');
|
|
17
17
|
|
|
18
18
|
async function destroyRequestSession(req) {
|
|
@@ -2,7 +2,7 @@ const jwt = require('jsonwebtoken');
|
|
|
2
2
|
const errors = require('@tryghost/errors');
|
|
3
3
|
const config = require('../../../shared/config');
|
|
4
4
|
const settingsCache = require('../../../shared/settings-cache');
|
|
5
|
-
const urlUtils = require('../../../shared/url-utils');
|
|
5
|
+
const urlUtils = require('../../../shared/url-utils').default;
|
|
6
6
|
|
|
7
7
|
function generateJWTToken(frame) {
|
|
8
8
|
const userData = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const storage = require('../../adapters/storage');
|
|
2
1
|
const {getStorageContentType} = require('../../services/files/file-type-utils');
|
|
2
|
+
const adapterManager = require('../../services/adapter-manager').default;
|
|
3
3
|
|
|
4
4
|
/** @type {import('@tryghost/api-framework').Controller} */
|
|
5
5
|
const controller = {
|
|
@@ -11,7 +11,7 @@ const controller = {
|
|
|
11
11
|
},
|
|
12
12
|
permissions: false,
|
|
13
13
|
async query(frame) {
|
|
14
|
-
const filePath = await
|
|
14
|
+
const filePath = await adapterManager.getAdapter('storage:files').save({
|
|
15
15
|
name: frame.file.originalname,
|
|
16
16
|
path: frame.file.path,
|
|
17
17
|
type: getStorageContentType(frame.file.originalname)
|
|
@@ -3,7 +3,7 @@ const path = require('path');
|
|
|
3
3
|
const errors = require('@tryghost/errors');
|
|
4
4
|
const imageTransform = require('@tryghost/image-transform');
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const adapterManager = require('../../services/adapter-manager').default;
|
|
7
7
|
const config = require('../../../shared/config');
|
|
8
8
|
|
|
9
9
|
/** @type {import('@tryghost/api-framework').Controller} */
|
|
@@ -16,7 +16,7 @@ const controller = {
|
|
|
16
16
|
},
|
|
17
17
|
permissions: false,
|
|
18
18
|
async query(frame) {
|
|
19
|
-
const store =
|
|
19
|
+
const store = adapterManager.getAdapter('storage:images');
|
|
20
20
|
|
|
21
21
|
// Normalize
|
|
22
22
|
const imageOptimizationOptions = config.get('imageOptimization');
|