ghost 6.56.0 → 6.57.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/bin/validate-adapters.js +74 -0
- package/bin/validate-adapters.ts +87 -0
- package/bin/warm-compile-cache.sh +60 -0
- package/components/tryghost-adapter-base-scheduling-0.2.1.tgz +0 -0
- package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
- package/components/tryghost-kg-converters-1.2.4.tgz +0 -0
- package/components/tryghost-kg-default-cards-10.3.4.tgz +0 -0
- package/components/tryghost-kg-default-nodes-2.1.5.tgz +0 -0
- package/components/tryghost-kg-default-transforms-1.3.3.tgz +0 -0
- package/components/tryghost-kg-html-to-lexical-1.3.3.tgz +0 -0
- package/components/tryghost-kg-lexical-html-renderer-1.4.3.tgz +0 -0
- package/components/tryghost-parse-email-address-0.0.0.tgz +0 -0
- package/core/app.js +1 -1
- package/core/boot.js +21 -25
- package/core/bridge.js +10 -12
- package/core/built/admin/assets/Combination-BDvCdg1t.js +41 -0
- package/core/built/admin/assets/about-BNojRaxf.js +1 -0
- package/core/built/admin/assets/{account-migration-D3O_yVck.js → account-migration-DMS8JsM-.js} +1 -1
- package/core/built/admin/assets/action-list-lGzZLHc8.js +1 -0
- package/core/built/admin/assets/activitypub/{account-migration-D8FbP-Z-.js → account-migration-DHFbePl6.js} +7 -7
- package/core/built/admin/assets/activitypub/activitypub.js +3 -3
- package/core/built/admin/assets/activitypub/{avatar-11EA1VSs.js → avatar-CT4tS2_S.js} +2 -2
- package/core/built/admin/assets/activitypub/{avatar-flipboard-jfbLG-xe.js → avatar-flipboard-ByYWKipo.js} +2 -2
- package/core/built/admin/assets/activitypub/{bluesky-sharing-f1jTQe2P.js → bluesky-sharing-srVnSHDz.js} +8 -8
- package/core/built/admin/assets/activitypub/{content-formatters-nmTOPY9M.js → content-formatters-C2sos5Ht.js} +3 -3
- package/core/built/admin/assets/activitypub/{copy-BCwo9ep3.js → copy-B1UBTOoZ.js} +2 -2
- package/core/built/admin/assets/activitypub/{dist-BEfX-0aW.js → dist-MPsb2WZ1.js} +4 -4
- package/core/built/admin/assets/activitypub/{domain-AaDlZlrA.js → domain-DzcM9Dzo.js} +9 -9
- package/core/built/admin/assets/activitypub/{edit-profile-DPi8Tl5M.js → edit-profile-CsQ_4xAk.js} +5 -5
- package/core/built/admin/assets/activitypub/{explore-CxTzjILQ.js → explore-CJe0DZBK.js} +8 -8
- package/core/built/admin/assets/activitypub/{feed-DPv5x2MX.js → feed-CKV3qWON.js} +9 -9
- package/core/built/admin/assets/activitypub/{field-DbgA8lat.js → field-DckHfDJf.js} +3 -3
- package/core/built/admin/assets/activitypub/{hash-BWuZoYkA.js → hash-Dlp8RM55.js} +2 -2
- package/core/built/admin/assets/activitypub/{inbox-35VDQ2K2.js → inbox-CsPy4R0M.js} +2 -2
- package/core/built/admin/assets/activitypub/{inbox-DSrF_i1O.js → inbox-DAsjzUUe.js} +10 -10
- package/core/built/admin/assets/activitypub/{label-CPjFBbo7.js → label-DWyo9E5T.js} +3 -3
- package/core/built/admin/assets/activitypub/layout-DM_3pqsU.js +1 -0
- package/core/built/admin/assets/activitypub/{moderation-BkDC1XVZ.js → moderation-B0Inc03M.js} +7 -7
- package/core/built/admin/assets/activitypub/{note-xEyH4xT-.js → note-CSE54lER.js} +7 -7
- package/core/built/admin/assets/activitypub/{notifications-DClaL3ui.js → notifications-RSwbKqdh.js} +9 -9
- package/core/built/admin/assets/activitypub/{preferences-DpnOa-4Z.js → preferences-CE231n2_.js} +11 -11
- package/core/built/admin/assets/activitypub/{profile-Dvi9mz-6.js → profile-aaQ1j1Eo.js} +13 -13
- package/core/built/admin/assets/activitypub/{reply-Cs9ySd6Z.js → reply-Cjb0Vs3m.js} +2 -2
- package/core/built/admin/assets/activitypub/{routes-DFBeTnfn.js → routes-Djb0mc9k.js} +26 -26
- package/core/built/admin/assets/activitypub/{separator-C5u_VjzY.js → separator-D8pROI5n.js} +3 -3
- package/core/built/admin/assets/activitypub/{settings-CV2fFu6D.js → settings-DMc32IQl.js} +5 -5
- package/core/built/admin/assets/activitypub/{site-_TgDd_EM.js → site-DVIcsohX.js} +4 -4
- package/core/built/admin/assets/activitypub/{step-1-BfnNL2oF.js → step-1-9Yey9usF.js} +5 -5
- package/core/built/admin/assets/activitypub/{step-2-DLndZkO-.js → step-2-DdYmKRXV.js} +6 -6
- package/core/built/admin/assets/activitypub/{step-3-A-PZTtRE.js → step-3-hdSkcjZU.js} +10 -10
- package/core/built/admin/assets/activitypub/{tabs-BUbz7tea.js → tabs-CUqseYzQ.js} +6 -6
- package/core/built/admin/assets/activitypub/{topic-filter-BdX_xYYT.js → topic-filter-Coni6OXM.js} +3 -3
- package/core/built/admin/assets/activitypub/{use-activity-pub-queries-EwuRemHh.js → use-activity-pub-queries-MeHTPMQv.js} +2 -2
- package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-cy4ACBc4.js → use-navigate-with-base-path-B046AM38.js} +24 -7
- package/core/built/admin/assets/activitypub/{use-reply-chain-data-CyFcGfan.js → use-reply-chain-data-1AO-Xob6.js} +5 -5
- package/core/built/admin/assets/activitypub/{x-7zk8mV2p.js → x-BRfRYd16.js} +2 -2
- package/core/built/admin/assets/add-integration-modal-DU9ghGLS.js +1 -0
- package/core/built/admin/assets/add-newsletter-modal-DFxuQrYu.js +1 -0
- package/core/built/admin/assets/add-recommendation-modal-D-3LOrdd.js +1 -0
- package/core/built/admin/assets/analytics-DTIMRhWw.js +1 -0
- package/core/built/admin/assets/announcement-bar-modal-DGCcezB6.js +1 -0
- package/core/built/admin/assets/api-keys-Dx4NeNpK.js +1 -0
- package/core/built/admin/assets/api-keys-_iCT4dxr.js +1 -0
- package/core/built/admin/assets/{audience-CkBb2LlO.js → audience-DkknNqhZ.js} +1 -1
- package/core/built/admin/assets/automated-emails-PayPCT8L.js +1 -0
- package/core/built/admin/assets/{automations-DhKeS_U5.js → automations-162q5HjL.js} +1 -1
- package/core/built/admin/assets/{automations-cMllU545.js → automations-DvSU7QhW.js} +1 -1
- package/core/built/admin/assets/{bluesky-sharing-DPGpyD-G.js → bluesky-sharing-yZ9A_jL8.js} +1 -1
- package/core/built/admin/assets/brand-icon-09YqFZjV.js +1 -0
- package/core/built/admin/assets/{breadcrumb-DIfcF5ow.js → breadcrumb-CjOH7LCU.js} +1 -1
- package/core/built/admin/assets/{chart-helpers-DV0FkdcD.js → chart-helpers-DGxvWnBT.js} +1 -1
- package/core/built/admin/assets/checkbox-BSUcnNq_.js +1 -0
- package/core/built/admin/assets/{chunk.332.05991a101d67f732dec3.js → chunk.424.4a27628efdade15c2dab.js} +28 -27
- package/core/built/admin/assets/chunk.524.dce1c51e0bc30fb2718e.js +25 -0
- package/core/built/admin/assets/{chunk.211.6f7328d63c41536451b3.js → chunk.571.40f093ed6d883993714e.js} +5 -5
- package/core/built/admin/assets/chunk.582.3a430d5c6a744fd475b6.js +27 -0
- package/core/built/admin/assets/code-editor-view-BcyKABrG.js +1 -0
- package/core/built/admin/assets/color-picker-field-8NoSnhNI.js +1 -0
- package/core/built/admin/assets/color-utils-Dzeeuj1F.js +1 -0
- package/core/built/admin/assets/combobox-5rdgDrDV.js +1 -0
- package/core/built/admin/assets/command-BOYMbZa_.js +1 -0
- package/core/built/admin/assets/comments-BhNM5CYl.js +1 -0
- package/core/built/admin/assets/components-CwL6a6As-B0E0-NBJ.js +1 -0
- package/core/built/admin/assets/confirmation-modal-CYD7x3UQ.js +1 -0
- package/core/built/admin/assets/content-api-modal-BtW4Z1-1.js +1 -0
- package/core/built/admin/assets/copy-field-CEp_XieW.js +1 -0
- package/core/built/admin/assets/currency-Dy4Tc2R2.js +1 -0
- package/core/built/admin/assets/custom-integration-modal-bk3lNEuQ.js +1 -0
- package/core/built/admin/assets/{date-range-select-dXc-GsVe.js → date-range-select-B3Ij1Rqg.js} +1 -1
- package/core/built/admin/assets/debounce-Cx5B_9OI.js +3 -0
- package/core/built/admin/assets/design-and-theme-modal-B2xYKS1I.js +23 -0
- package/core/built/admin/assets/dirty-confirm-dialog-YE9L21gY.js +1 -0
- package/core/built/admin/assets/disabled-sources-indicator-uIzbWL7K.js +1 -0
- package/core/built/admin/assets/{dist-pHiOxyxa.js → dist-ARN6XTcR.js} +1 -1
- package/core/built/admin/assets/dist-B2PvRwLn.js +1 -0
- package/core/built/admin/assets/{dist-DyViJwIy.js → dist-Bg8bSvLA.js} +3 -3
- package/core/built/admin/assets/dist-CsvXCJSe.js +23 -0
- package/core/built/admin/assets/dist-DlCyLrOC.js +1 -0
- package/core/built/admin/assets/dist-j1xxxnY8.js +1 -0
- package/core/built/admin/assets/dist-myQaY0ka.js +1 -0
- package/core/built/admin/assets/{domain-B5ogXUBa.js → domain-DzrOAPY8.js} +1 -1
- package/core/built/admin/assets/{dropzone-BnFG7dDP.js → dropzone-CzhP33wa.js} +1 -1
- package/core/built/admin/assets/{edit-profile-B07jCZy9.js → edit-profile-oufs4R4n.js} +1 -1
- package/core/built/admin/assets/editor-BBKrunMK.js +8 -0
- package/core/built/admin/assets/embed-signup-form-modal-Ch3s6lqA.js +9 -0
- package/core/built/admin/assets/{explore-Ca1y8HW_.js → explore-CA-R01Br.js} +1 -1
- package/core/built/admin/assets/{feed-x4iFMBP4.js → feed-ClC8_Gld.js} +1 -1
- package/core/built/admin/assets/{field-ChCAabZg.js → field-B3OPenbP.js} +1 -1
- package/core/built/admin/assets/{filter-sources-LdtH1e-T.js → filter-sources-CiPLnG9A.js} +1 -1
- package/core/built/admin/assets/filters-Bz0HsRie.js +1 -0
- package/core/built/admin/assets/{filters-CjVKRP8U.js → filters-yFvybRMe.js} +1 -1
- package/core/built/admin/assets/first-promoter-modal-BC0UpYCD.js +1 -0
- package/core/built/admin/assets/format-url-C-t8G6Qd.js +1 -0
- package/core/built/admin/assets/{ghost-7f01131115186d1af84ead76e79646dd.js → ghost-d683fbeb945b13155ea669caa5d8db41.js} +300 -298
- package/core/built/admin/assets/{gift-link-modal-Buqh2vXh.js → gift-link-modal-BKRuqo-k.js} +1 -1
- package/core/built/admin/assets/{gift-links-CsUhefWG.js → gift-links-CVuqLhsZ.js} +1 -1
- package/core/built/admin/assets/global-data-provider-RzW6Bnlf.js +1 -0
- package/core/built/admin/assets/grid-CUciBfjf.js +1 -0
- package/core/built/admin/assets/{growth-DajOBdN0.js → growth-ClNAldfL.js} +1 -1
- package/core/built/admin/assets/{growth-Dy2UOSay.js → growth-Dz8OSG06.js} +2 -2
- package/core/built/admin/assets/history-modal-DIVuQ5Ct.js +1 -0
- package/core/built/admin/assets/{hooks-CixO01lL.js → hooks-D6EE7BIt.js} +2 -2
- package/core/built/admin/assets/html-field-CVZ2sMxw.js +1 -0
- package/core/built/admin/assets/iframe-buffering-e8vH4-Qn.js +1 -0
- package/core/built/admin/assets/images-Ok8FFJ3A.js +1 -0
- package/core/built/admin/assets/{inbox-BUOLDoji.js → inbox-CMUVI6qb.js} +13 -13
- package/core/built/admin/assets/index-DUXM0NlS.js +67 -0
- package/core/built/admin/assets/index-Ds2iUoF6.css +1 -0
- package/core/built/admin/assets/index.es-B9tvf-t4.js +1 -0
- package/core/built/admin/assets/{input-group-uSK3XT7b.js → input-group-2XU-iuh_.js} +1 -1
- package/core/built/admin/assets/integration-header-B4DyXV06.js +1 -0
- package/core/built/admin/assets/integrations-BT6_iJvu.js +1 -0
- package/core/built/admin/assets/invite-user-modal-DrZ7xxrZ.js +1 -0
- package/core/built/admin/assets/isEmail-BOfC647y.js +1 -0
- package/core/built/admin/assets/koenig-editor-base-BPj4S760.js +1 -0
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +9254 -9251
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +124 -124
- package/core/built/admin/assets/{koenig-lexical-BFc4yFed.js → koenig-lexical-Cdjv-m3_.js} +98 -98
- package/core/built/admin/assets/{kpi-card-CCt-qeWD.js → kpi-card-J8Mj1sDX.js} +1 -1
- package/core/built/admin/assets/{kpi-card-BN-E6WYX.js → kpi-card-awos0BMH.js} +1 -1
- package/core/built/admin/assets/{kpi-helpers-DlxTbTs4.js → kpi-helpers-SEhvH-8E.js} +1 -1
- package/core/built/admin/assets/{kpi-tabs-BlcUttpn.js → kpi-tabs-R6BjsKhd.js} +1 -1
- package/core/built/admin/assets/{label-AVrxwmsz.js → label-BMC3dzLI.js} +1 -1
- package/core/built/admin/assets/label-picker-Bnlru5tO.js +1 -0
- package/core/built/admin/assets/{labels-DAIqKed7.js → labels-DAPjKPy2.js} +1 -1
- package/core/built/admin/assets/layout-yR9rlvEw.js +1 -0
- package/core/built/admin/assets/limit-modal-COmLevuY.js +1 -0
- package/core/built/admin/assets/{link-helpers-D9LsDOkG.js → link-helpers-Bzkk68GD.js} +1 -1
- package/core/built/admin/assets/member-custom-fields-BvFKEpxJ.js +1 -0
- package/core/built/admin/assets/member-detail-CWdPAe3p.js +1 -0
- package/core/built/admin/assets/members-Bnt0ih2R.js +11 -0
- package/core/built/admin/assets/modal-page-BMTzFHVO.js +1 -0
- package/core/built/admin/assets/{moderation-CQ3urTFE.js → moderation-mPjYHgZW.js} +1 -1
- package/core/built/admin/assets/multi-select-combobox-CsoyHAiX.js +1 -0
- package/core/built/admin/assets/navigation-modal-D_c0badj.js +1 -0
- package/core/built/admin/assets/newsletter-DR49NyGS.js +1 -0
- package/core/built/admin/assets/newsletter-detail-modal-B45pL1pb.js +1 -0
- package/core/built/admin/assets/newsletter-emails-B-OLfrvr.js +1 -0
- package/core/built/admin/assets/{newsletters-vt3Ni1Ov.js → newsletters-DGs5BaKH.js} +1 -1
- package/core/built/admin/assets/{newsletters-BXJbJgA-.js → newsletters-Du0lzskS.js} +1 -1
- package/core/built/admin/assets/{note-Dk877BTv.js → note-CSVsUKBm.js} +1 -1
- package/core/built/admin/assets/{notifications-CPlLjPxO.js → notifications-DV9FRtDw.js} +1 -1
- package/core/built/admin/assets/{offers-DEniVRD5.js → offers-Um6ab71O.js} +1 -1
- package/core/built/admin/assets/offers-container-modal-B0hFS8nk.js +1 -0
- package/core/built/admin/assets/{onboarding-route-DdStOtjy.js → onboarding-route--jL5KLPD.js} +1 -1
- package/core/built/admin/assets/overview-B-ZPNqMo.js +1 -0
- package/core/built/admin/assets/overview-D96iwoJi.js +1 -0
- package/core/built/admin/assets/{page-header-pp4dWmOS.js → page-header-DAvDYKO9.js} +1 -1
- package/core/built/admin/assets/{pages-B4goRPUn.js → pages-BVMnpI2O.js} +1 -1
- package/core/built/admin/assets/pintura-modal-jiUCxX0Q.js +1 -0
- package/core/built/admin/assets/portal-frame-D4D4nEO6.js +1 -0
- package/core/built/admin/assets/portal-modal-BLFdYeDH.js +1 -0
- package/core/built/admin/assets/{post-analytics-BMJrI81R.js → post-analytics-BhAtiFJp.js} +1 -1
- package/core/built/admin/assets/post-analytics-header-DK27VjJm.js +1 -0
- package/core/built/admin/assets/{post-analytics-provider-Btml5vJI.js → post-analytics-provider-DGg0FUqs.js} +1 -1
- package/core/built/admin/assets/{post-share-modal-AcUZkbfL.js → post-share-modal-DtFAC132.js} +1 -1
- package/core/built/admin/assets/{posts-DhXE7b6r.js → posts-CxG7v0-M.js} +1 -1
- package/core/built/admin/assets/preferences-CuWLISHa.js +5 -0
- package/core/built/admin/assets/preview-chrome-BOVO6_PE.js +1 -0
- package/core/built/admin/assets/preview-modal-DctYx20m.js +1 -0
- package/core/built/admin/assets/profile-BsKYYtuL.js +1 -0
- package/core/built/admin/assets/radio-group-CI5_Kf_d.js +1 -0
- package/core/built/admin/assets/{referrers-pmJT4k3-.js → referrers-B9QDAfYm.js} +1 -1
- package/core/built/admin/assets/{router-provider-BmEZf6c6.js → router-provider-DSQfprxH.js} +1 -1
- package/core/built/admin/assets/select-CkXqNJDJ.js +1 -0
- package/core/built/admin/assets/settings-B4vM-rgV.js +4 -0
- package/core/built/admin/assets/{settings-BGgk7oCI.js → settings-ZCj-W56o.js} +1 -1
- package/core/built/admin/assets/settings-breadcrumbs-DIq31FwA.js +1 -0
- package/core/built/admin/assets/{share-modal-BeuydaBf.js → share-modal-BNj14g79.js} +1 -1
- package/core/built/admin/assets/slack-modal-C6SpMQ-q.js +1 -0
- package/core/built/admin/assets/social-urls-CHQ9cTAK.js +1 -0
- package/core/built/admin/assets/{sort-button-Df4t2AL8.js → sort-button-B-k54ow2.js} +1 -1
- package/core/built/admin/assets/{source-icon-ajoaKb41.js → source-icon-Cej3sZM6.js} +1 -1
- package/core/built/admin/assets/{stats-C_lfxZAw.js → stats-B2KW8E2y.js} +1 -1
- package/core/built/admin/assets/{stats-view-Cxot1iD8.js → stats-view-CVzU2-p5.js} +1 -1
- package/core/built/admin/assets/{step-1-ogAA4lDr.js → step-1-Dbn1iIMU.js} +1 -1
- package/core/built/admin/assets/{step-2-C5Xini-7.js → step-2-BahnSuN6.js} +1 -1
- package/core/built/admin/assets/{step-3-CZv1FV81.js → step-3-CW04e2ZJ.js} +2 -2
- package/core/built/admin/assets/stripe-button-BkBZqaGG.js +1 -0
- package/core/built/admin/assets/stripe-connect-modal-CYDDrSJm.js +1 -0
- package/core/built/admin/assets/switch-CE2NuMn-.js +1 -0
- package/core/built/admin/assets/{table-DFj1wiYv.js → table-BtLcEi1M.js} +1 -1
- package/core/built/admin/assets/tabs-BaWRfg8j.js +1 -0
- package/core/built/admin/assets/tag-detail-CmqiC32L.js +1 -0
- package/core/built/admin/assets/tags-BbygUvNB.js +1 -0
- package/core/built/admin/assets/tags-BwCgmr5v.js +1 -0
- package/core/built/admin/assets/testimonials-modal--bdzppyh.js +1 -0
- package/core/built/admin/assets/tier-detail-modal-BZmAsIy4.js +1 -0
- package/core/built/admin/assets/{tiers-DYsa4DCo.js → tiers-Da6kxHQP.js} +1 -1
- package/core/built/admin/assets/toggle-group-CVl-Xigr.js +1 -0
- package/core/built/admin/assets/{topic-filter-DGDxDalo.js → topic-filter-BoRHRbL1.js} +1 -1
- package/core/built/admin/assets/transistor-modal-CBPDqEGy.js +1 -0
- package/core/built/admin/assets/unsplash-modal-CixoRAO2.js +1 -0
- package/core/built/admin/assets/{use-analytics-data-C76v4LIp.js → use-analytics-data-BiWvcf1u.js} +1 -1
- package/core/built/admin/assets/use-check-theme-limit-error-B14lZukR.js +2 -0
- package/core/built/admin/assets/use-feature-flag-BmJoc5WN.js +1 -0
- package/core/built/admin/assets/use-filter-params-ChoV72Hw.js +1 -0
- package/core/built/admin/assets/use-filterable-api-iMpDZBxD.js +1 -0
- package/core/built/admin/assets/use-form-vRjI0Kwk.js +1 -0
- package/core/built/admin/assets/{use-growth-stats-aNXJOmQr.js → use-growth-stats-Dom8xVzo.js} +1 -1
- package/core/built/admin/assets/use-hash-link-navigation-guard-B9j6HIrV.js +1 -0
- package/core/built/admin/assets/use-limiter-Dwg8ivgQ.js +2 -0
- package/core/built/admin/assets/use-pintura-config-Bj4QmiVk.js +1 -0
- package/core/built/admin/assets/use-pintura-editor-DvrslmPE.js +1 -0
- package/core/built/admin/assets/{use-post-referrers-CG0SZioj.js → use-post-referrers-pxIHTXFs.js} +1 -1
- package/core/built/admin/assets/use-query-params-DHhhu8wi.js +1 -0
- package/core/built/admin/assets/{use-reply-chain-data-RLdPKRmS.js → use-reply-chain-data-CmFe0N6F.js} +1 -1
- package/core/built/admin/assets/use-setting-group-Cmp_sy-d.js +1 -0
- package/core/built/admin/assets/use-settings-navigation-BmROPrls.js +1 -0
- package/core/built/admin/assets/{use-simple-pagination-DgcF69KI.js → use-simple-pagination-D5rL3YwO.js} +1 -1
- package/core/built/admin/assets/{use-tinybird-query-C1R_Kbmy.js → use-tinybird-query-DP2dMaq7.js} +1 -1
- package/core/built/admin/assets/{use-tinybird-token-C9fPjVM_.js → use-tinybird-token-DrK_skPQ.js} +1 -1
- package/core/built/admin/assets/use-url-input-ChrUZBFf.js +5 -0
- package/core/built/admin/assets/user-detail-modal-XODpOqNC.js +1 -0
- package/core/built/admin/assets/{users-Dkv8NQZe.js → users-B6hIds6n.js} +1 -1
- package/core/built/admin/assets/validator-Cr0sMKuW.js +7 -0
- package/core/built/admin/assets/{virtual-list-BmTUzeoF.js → virtual-list-Dnoafqbk.js} +1 -1
- package/core/built/admin/assets/web-D71mjB2r.js +1 -0
- package/core/built/admin/assets/web-z71lA1Y3.js +2 -0
- package/core/built/admin/assets/zapier-modal-Bp507Um7.js +1 -0
- package/core/built/admin/index.html +16 -14
- package/core/frontend/helpers/authors.js +1 -1
- package/core/frontend/helpers/link.js +3 -8
- package/core/frontend/helpers/tags.js +1 -1
- package/core/frontend/meta/author-url.js +2 -2
- package/core/frontend/meta/url.js +4 -4
- package/core/frontend/services/proxy.js +1 -1
- package/core/frontend/services/routing/events.js +20 -6
- package/core/frontend/services/routing/permalink-adapter.js +0 -13
- package/core/frontend/services/routing/permalink-adapter.ts +0 -13
- package/core/frontend/services/routing/router-manager.js +15 -9
- package/core/frontend/services/sitemap/base-site-map-generator.js +1 -28
- package/core/frontend/services/sitemap/site-map-manager.js +22 -57
- package/core/frontend/web/middleware/admin-toolbar.js +1 -1
- package/core/frontend/web/middleware/serve-indexnow-key.js +1 -7
- package/core/server/adapters/route-settings/utils.js +10 -2
- package/core/server/adapters/route-settings/utils.ts +12 -2
- package/core/server/api/endpoints/email-post.js +1 -1
- package/core/server/api/endpoints/index.js +2 -2
- package/core/server/api/endpoints/previews.js +1 -1
- package/core/server/api/endpoints/search-index-public.js +3 -3
- package/core/server/api/endpoints/search-index.js +4 -4
- package/core/server/api/endpoints/themes.js +6 -1
- package/core/server/api/endpoints/utils/serializers/input/authors.js +2 -2
- package/core/server/api/endpoints/utils/serializers/input/comments.js +1 -1
- package/core/server/api/endpoints/utils/serializers/input/pages.js +3 -3
- package/core/server/api/endpoints/utils/serializers/input/posts.js +3 -3
- package/core/server/api/endpoints/utils/serializers/input/tags.js +1 -1
- package/core/server/api/endpoints/utils/serializers/input/users.js +2 -2
- package/core/server/api/endpoints/utils/serializers/input/utils/url.js +31 -13
- package/core/server/api/endpoints/utils/serializers/output/mappers/posts.js +2 -2
- package/core/server/api/endpoints/utils/serializers/output/mappers/tags.js +2 -2
- package/core/server/api/endpoints/utils/serializers/output/mappers/users.js +8 -0
- package/core/server/api/endpoints/utils/serializers/output/utils/url.js +18 -11
- package/core/server/data/migrations/versions/6.57/2026-08-04-18-00-00-store-custom-field-values-as-leaf-rows.js +74 -0
- package/core/server/data/migrations/versions/6.57/2026-08-04-18-54-14-reset-automation-email-analytics.js +25 -0
- package/core/server/data/schema/commands.js +21 -5
- package/core/server/data/schema/schema.js +24 -5
- package/core/server/lib/common/to-plain.ts +1 -1
- package/core/server/models/base/plugins/overrides.js +7 -5
- package/core/server/models/post.js +2 -2
- package/core/server/services/adapter-manager/adapter-manager.js +1 -45
- package/core/server/services/adapter-manager/adapter-manager.ts +2 -48
- package/core/server/services/adapter-manager/adapter-paths.js +28 -0
- package/core/server/services/adapter-manager/adapter-paths.ts +26 -0
- package/core/server/services/adapter-manager/base-classes.js +22 -0
- package/core/server/services/adapter-manager/base-classes.ts +22 -0
- package/core/server/services/adapter-manager/index.js +4 -27
- package/core/server/services/adapter-manager/index.ts +4 -31
- package/core/server/services/adapter-manager/utils.js +50 -0
- package/core/server/services/adapter-manager/utils.ts +57 -0
- package/core/server/services/audience-feedback/audience-feedback-controller.js +11 -2
- package/core/server/services/audience-feedback/audience-feedback-service.js +2 -2
- package/core/server/services/audience-feedback/feedback-repository.js +4 -1
- package/core/server/services/auth/session/session-service.js +18 -3
- package/core/server/services/automations/database-automations-repository.js +5 -5
- package/core/server/services/automations/database-automations-repository.ts +12 -12
- package/core/server/services/automations/database-date.js +52 -3
- package/core/server/services/automations/database-date.ts +23 -2
- package/core/server/services/automations/service.js +2 -2
- package/core/server/services/automations/service.ts +2 -2
- package/core/server/services/comments/comments-service-emails.js +1 -1
- package/core/server/services/comments/comments-service.js +1 -1
- package/core/server/services/email-analytics/email-analytics-service-wrapper.js +12 -3
- package/core/server/services/email-analytics/email-analytics-service.js +4 -3
- 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/lib/queries.js +91 -124
- package/core/server/services/email-analytics/lib/queries.ts +341 -0
- package/core/server/services/email-service/email-service-wrapper.js +2 -1
- package/core/server/services/email-service/mailgun-email-provider.js +15 -0
- package/core/server/services/indexnow-ping/index.js +0 -2
- package/core/server/services/indexnow-ping/index.ts +0 -2
- package/core/server/services/indexnow-ping/indexnow-ping-service.js +6 -8
- package/core/server/services/indexnow-ping/indexnow-ping-service.ts +9 -17
- package/core/server/services/lib/mailgun-client.js +3 -3
- package/core/server/services/media-inliner/external-media-inliner.js +12 -8
- package/core/server/services/member-attribution/url-translator.js +5 -7
- package/core/server/services/member-welcome-emails/service.js +72 -12
- package/core/server/services/members/api.js +1 -1
- package/core/server/services/members/import-export/import/completion-email.js +8 -4
- package/core/server/services/members/import-export/import/completion-email.ts +9 -4
- package/core/server/services/members/import-export/import/importer.js +25 -4
- package/core/server/services/members/import-export/import/importer.ts +26 -6
- package/core/server/services/members/import-export/import/row.ts +5 -1
- package/core/server/services/members/import-export/index.js +1 -5
- package/core/server/services/members/import-export/index.ts +2 -6
- package/core/server/services/members/members-api/repositories/member-repository.js +51 -0
- package/core/server/services/members-custom-fields/queries.js +4 -13
- package/core/server/services/members-custom-fields/queries.ts +4 -13
- package/core/server/services/members-custom-fields/schema.js +18 -27
- package/core/server/services/members-custom-fields/schema.ts +17 -27
- package/core/server/services/members-custom-fields/storage.js +94 -27
- package/core/server/services/members-custom-fields/storage.ts +114 -39
- package/core/server/services/members-custom-fields/values-service.js +98 -219
- package/core/server/services/members-custom-fields/values-service.ts +110 -238
- package/core/server/services/mentions/resource-service.js +1 -1
- package/core/server/services/mentions/service.js +2 -2
- package/core/server/services/route-settings/dynamic-routing-service.js +9 -59
- package/core/server/services/slack-notifications/slack-notifications.js +2 -2
- package/core/server/services/slack-ping/index.js +1 -1
- package/core/server/services/slack-ping/index.ts +1 -1
- package/core/server/services/slack-ping/slack-ping-service.js +3 -2
- package/core/server/services/slack-ping/slack-ping-service.ts +4 -5
- package/core/server/services/stats/content-stats-service.js +3 -3
- package/core/server/services/stats/members-stats-service.js +0 -7
- package/core/server/services/stats/posts-stats-service.js +2 -2
- package/core/server/services/themes/storage.js +19 -2
- package/core/server/services/url/config.js +90 -135
- package/core/server/services/url/index.js +6 -49
- package/core/server/services/url/lazy-find-resource.js +14 -11
- package/core/server/services/url/lazy-find-resource.ts +14 -11
- package/core/server/services/url/lazy-url-service.js +174 -94
- package/core/server/services/url/lazy-url-service.ts +233 -97
- package/core/server/services/url/routable-resources.js +62 -71
- package/core/server/services/url/router-filter.js +12 -4
- package/core/server/services/url/router-filter.ts +12 -4
- package/core/server/services/webhooks/index.js +1 -1
- package/core/server/services/webhooks/serialize.js +12 -2
- package/core/server/web/api/endpoints/admin/routes.js +2 -2
- package/core/shared/config/env/config.testing-mysql.json +1 -2
- package/core/shared/config/env/config.testing.json +1 -2
- package/core/shared/custom-theme-settings-cache/custom-theme-settings-bread-service.js +4 -0
- package/core/shared/custom-theme-settings-cache/custom-theme-settings-service.js +39 -0
- package/core/shared/events/index.js +1 -2
- package/core/shared/labs.js +4 -4
- package/package.json +10 -11
- package/pnpm-lock.yaml +44 -47
- package/pnpm-workspace.yaml +19 -19
- package/tsconfig.json +1 -0
- package/components/tryghost-adapter-base-scheduling-0.2.0.tgz +0 -0
- package/components/tryghost-kg-converters-1.2.3.tgz +0 -0
- package/components/tryghost-kg-default-cards-10.3.3.tgz +0 -0
- package/components/tryghost-kg-default-nodes-2.1.4.tgz +0 -0
- package/core/built/admin/assets/Combination-BCm9FL4o.js +0 -41
- package/core/built/admin/assets/activitypub/layout-CTgrezN7.js +0 -1
- package/core/built/admin/assets/automated-emails-6t2bIRWf.js +0 -7
- package/core/built/admin/assets/checkbox-BIl077a0.js +0 -1
- package/core/built/admin/assets/chunk.524.87b52f4fada529df2c4c.js +0 -25
- package/core/built/admin/assets/chunk.582.340bcca873e806cbd4bb.js +0 -27
- package/core/built/admin/assets/code-editor-view-C0aWNwdl.js +0 -1
- package/core/built/admin/assets/comments-qwhIjH3c.js +0 -1
- package/core/built/admin/assets/disabled-sources-indicator-DYAXW-6V.js +0 -1
- package/core/built/admin/assets/dist-BUKmD51u.js +0 -1
- package/core/built/admin/assets/dist-CNlMj7ML.js +0 -1
- package/core/built/admin/assets/dist-DDY6GRVz.js +0 -1
- package/core/built/admin/assets/dist-DG78yroX.js +0 -23
- package/core/built/admin/assets/editor-DDYSOXGN.js +0 -8
- package/core/built/admin/assets/esm-CFX93H5M.js +0 -2
- package/core/built/admin/assets/filters-CLehPo_D.js +0 -1
- package/core/built/admin/assets/index-08n05-rc.js +0 -67
- package/core/built/admin/assets/index-DgUzgFvS.css +0 -1
- package/core/built/admin/assets/label-picker-DVnpu_IF.js +0 -1
- package/core/built/admin/assets/layout-B0YLh7R9.js +0 -1
- package/core/built/admin/assets/member-custom-fields-C8NpZYza.js +0 -1
- package/core/built/admin/assets/member-detail-CIVAdKXf.js +0 -1
- package/core/built/admin/assets/members-oLPiSkXD.js +0 -10
- package/core/built/admin/assets/modals-CB7v-k3T.js +0 -31
- package/core/built/admin/assets/newsletter-rbeDX9Wk.js +0 -1
- package/core/built/admin/assets/overview--4V-kx9c.js +0 -1
- package/core/built/admin/assets/overview-DSLv30oz.js +0 -1
- package/core/built/admin/assets/post-analytics-header-pU2m9ZuV.js +0 -1
- package/core/built/admin/assets/preferences-Ru4CRPHC.js +0 -5
- package/core/built/admin/assets/profile-BNb1oj7D.js +0 -1
- package/core/built/admin/assets/select-B0HteHrp.js +0 -1
- package/core/built/admin/assets/settings-B1C9Q3wo.js +0 -4
- package/core/built/admin/assets/social-urls-DA2lXrhW.js +0 -8
- package/core/built/admin/assets/switch-CyQcwMAv.js +0 -1
- package/core/built/admin/assets/tabs-D4y1gqUd.js +0 -1
- package/core/built/admin/assets/tags-Dmft-Y4O.js +0 -1
- package/core/built/admin/assets/toggle-group-R2QMFvXW.js +0 -1
- package/core/built/admin/assets/use-filter-params-WrdhAISv.js +0 -1
- package/core/built/admin/assets/web-BqW0b0_C.js +0 -1
- package/core/built/admin/assets/web-Cy5GKMWM.js +0 -2
- package/core/server/services/email-analytics/jobs/update-member-email-analytics/index.js +0 -14
- package/core/server/services/url/local-file-cache.js +0 -75
- package/core/server/services/url/queue.js +0 -260
- package/core/server/services/url/resource.js +0 -102
- package/core/server/services/url/resources.js +0 -480
- package/core/server/services/url/url-generator.js +0 -276
- package/core/server/services/url/url-service-facade.js +0 -366
- package/core/server/services/url/url-service-facade.ts +0 -519
- package/core/server/services/url/url-service.js +0 -387
- package/core/server/services/url/urls.js +0 -140
- package/core/shared/events/url-resource-updated-event.js +0 -33
- /package/core/built/admin/assets/{chunk.211.6f7328d63c41536451b3.js.LICENSE.txt → chunk.571.40f093ed6d883993714e.js.LICENSE.txt} +0 -0
- /package/core/built/admin/assets/{dist-CqO2lWS0.js → dist-CqO2lWS02.js} +0 -0
- /package/core/server/api/endpoints/{gift-reminders.js → gifts.js} +0 -0
|
@@ -96,11 +96,13 @@ module.exports = function (Bookshelf) {
|
|
|
96
96
|
(value, key) => key.startsWith(PIVOT_PREFIX)
|
|
97
97
|
);
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
// Iterate `_previousRelations` rather than `relationships` — a relation
|
|
100
|
+
// can carry previous state without being managed by bookshelf-relations
|
|
101
|
+
// (e.g. a member's stripeSubscriptions). Behaviour is unchanged for
|
|
102
|
+
// relations that are in both.
|
|
103
|
+
if (this._previousRelations) {
|
|
104
|
+
Object.keys(this._previousRelations).forEach((relation) => {
|
|
105
|
+
clonedModel.related(relation).models = this._previousRelations[relation].models;
|
|
104
106
|
});
|
|
105
107
|
}
|
|
106
108
|
|
|
@@ -1006,8 +1006,8 @@ Post = ghostBookshelf.Model.extend({
|
|
|
1006
1006
|
* - `slug`: /:slug/
|
|
1007
1007
|
* - `published_at`: /:year/:slug
|
|
1008
1008
|
* - `author_id`: /:author/:slug, /:primary_author/:slug
|
|
1009
|
-
* - now, the UrlService
|
|
1010
|
-
* - you can ask `urlService.
|
|
1009
|
+
* - now, the UrlService computes urls from the routing config
|
|
1010
|
+
* - you can ask `urlService.getUrlForResource(post)`
|
|
1011
1011
|
*
|
|
1012
1012
|
* ### events
|
|
1013
1013
|
* - you call `findAll` with `columns: id`
|
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.AdapterManager = void 0;
|
|
7
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
8
7
|
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
9
8
|
const utils_1 = require("./utils");
|
|
10
9
|
/**
|
|
@@ -121,50 +120,7 @@ class AdapterManager {
|
|
|
121
120
|
message: `Unable to find ${adapterType} adapter in ${this.pathsToAdapters}.`
|
|
122
121
|
});
|
|
123
122
|
}
|
|
124
|
-
|
|
125
|
-
for (const pathToAdapters of this.pathsToAdapters) {
|
|
126
|
-
let pathToAdapter = node_path_1.default.join(pathToAdapters, adapterType, adapterClassName);
|
|
127
|
-
if (pathToAdapters === '') {
|
|
128
|
-
// We are loading from node_modules, we can remove the `adapterType` prefix
|
|
129
|
-
pathToAdapter = node_path_1.default.join(pathToAdapters, adapterClassName);
|
|
130
|
-
}
|
|
131
|
-
// An adapter directory may be a full module with its own
|
|
132
|
-
// package.json, in which case this resolves the `exports` entry
|
|
133
|
-
// point; otherwise the path passes through unchanged.
|
|
134
|
-
const moduleToLoad = (0, utils_1.resolveAdapterEntryPoint)(pathToAdapter);
|
|
135
|
-
try {
|
|
136
|
-
const adapterModule = this.loadAdapterFromPath(moduleToLoad);
|
|
137
|
-
Adapter = (0, utils_1.resolveAdapterExport)(adapterModule);
|
|
138
|
-
if (Adapter) {
|
|
139
|
-
break;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
catch (err) {
|
|
143
|
-
// Catch runtime errors
|
|
144
|
-
if (!(err instanceof Error) || err.code !== 'MODULE_NOT_FOUND') {
|
|
145
|
-
throw new errors_1.default.IncorrectUsageError({ err: err });
|
|
146
|
-
}
|
|
147
|
-
// Catch missing dependencies BUT NOT missing adapter.
|
|
148
|
-
// Only check the first line — Node appends a "Require stack"
|
|
149
|
-
// that includes the adapter's own path, which would false-positive.
|
|
150
|
-
const firstLine = err.message.split('\n')[0];
|
|
151
|
-
if (!firstLine.includes(pathToAdapter)) {
|
|
152
|
-
// Name the unresolved module so the error is actionable, e.g.
|
|
153
|
-
// "Cannot find module 'superagent'" -> 'superagent'.
|
|
154
|
-
const missingMatch = /Cannot find module '([^']+)'/.exec(firstLine);
|
|
155
|
-
const missingModule = missingMatch ? ` '${missingMatch[1]}'` : '';
|
|
156
|
-
throw new errors_1.default.IncorrectUsageError({
|
|
157
|
-
message: `You are missing a dependency${missingModule} in your adapter ${pathToAdapter}`,
|
|
158
|
-
err: err
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
if (!Adapter) {
|
|
164
|
-
throw new errors_1.default.IncorrectUsageError({
|
|
165
|
-
message: `Unable to find ${adapterType} adapter ${adapterClassName} in ${this.pathsToAdapters}.`
|
|
166
|
-
});
|
|
167
|
-
}
|
|
123
|
+
const Adapter = (0, utils_1.loadAdapterClass)(adapterType, adapterClassName, this.pathsToAdapters, this.loadAdapterFromPath);
|
|
168
124
|
return { Adapter, adapterConfig: adapterConfig ?? {}, adapterType, adapterClassName };
|
|
169
125
|
}
|
|
170
126
|
/**
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import errors from '@tryghost/errors';
|
|
3
|
-
import {
|
|
2
|
+
import {loadAdapterClass, resolveAdapterOptions, normalizeAdapterConfig, getConfiguredFeatures} from './utils';
|
|
4
3
|
import type {ConfigInstance} from '../../../shared/config/loader';
|
|
5
4
|
import type {
|
|
6
5
|
Adapter,
|
|
@@ -186,52 +185,7 @@ export class AdapterManager<BaseClasses extends BaseClassMap = BaseClassMap> {
|
|
|
186
185
|
});
|
|
187
186
|
}
|
|
188
187
|
|
|
189
|
-
|
|
190
|
-
for (const pathToAdapters of this.pathsToAdapters) {
|
|
191
|
-
let pathToAdapter = path.join(pathToAdapters, adapterType, adapterClassName);
|
|
192
|
-
if (pathToAdapters === '') {
|
|
193
|
-
// We are loading from node_modules, we can remove the `adapterType` prefix
|
|
194
|
-
pathToAdapter = path.join(pathToAdapters, adapterClassName);
|
|
195
|
-
}
|
|
196
|
-
// An adapter directory may be a full module with its own
|
|
197
|
-
// package.json, in which case this resolves the `exports` entry
|
|
198
|
-
// point; otherwise the path passes through unchanged.
|
|
199
|
-
const moduleToLoad = resolveAdapterEntryPoint(pathToAdapter);
|
|
200
|
-
|
|
201
|
-
try {
|
|
202
|
-
const adapterModule = this.loadAdapterFromPath(moduleToLoad);
|
|
203
|
-
Adapter = resolveAdapterExport(adapterModule);
|
|
204
|
-
if (Adapter) {
|
|
205
|
-
break;
|
|
206
|
-
}
|
|
207
|
-
} catch (err) {
|
|
208
|
-
// Catch runtime errors
|
|
209
|
-
if (!(err instanceof Error) || (err as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND') {
|
|
210
|
-
throw new errors.IncorrectUsageError({err: err as Error});
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Catch missing dependencies BUT NOT missing adapter.
|
|
214
|
-
// Only check the first line — Node appends a "Require stack"
|
|
215
|
-
// that includes the adapter's own path, which would false-positive.
|
|
216
|
-
const firstLine = err.message.split('\n')[0];
|
|
217
|
-
if (!firstLine.includes(pathToAdapter)) {
|
|
218
|
-
// Name the unresolved module so the error is actionable, e.g.
|
|
219
|
-
// "Cannot find module 'superagent'" -> 'superagent'.
|
|
220
|
-
const missingMatch = /Cannot find module '([^']+)'/.exec(firstLine);
|
|
221
|
-
const missingModule = missingMatch ? ` '${missingMatch[1]}'` : '';
|
|
222
|
-
throw new errors.IncorrectUsageError({
|
|
223
|
-
message: `You are missing a dependency${missingModule} in your adapter ${pathToAdapter}`,
|
|
224
|
-
err: err as Error
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
if (!Adapter) {
|
|
231
|
-
throw new errors.IncorrectUsageError({
|
|
232
|
-
message: `Unable to find ${adapterType} adapter ${adapterClassName} in ${this.pathsToAdapters}.`
|
|
233
|
-
});
|
|
234
|
-
}
|
|
188
|
+
const Adapter = loadAdapterClass(adapterType, adapterClassName, this.pathsToAdapters, this.loadAdapterFromPath);
|
|
235
189
|
|
|
236
190
|
return {Adapter, adapterConfig: adapterConfig ?? {}, adapterType, adapterClassName};
|
|
237
191
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
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.adapterPaths = void 0;
|
|
7
|
+
exports.buildAdapterPaths = buildAdapterPaths;
|
|
8
|
+
const config_1 = __importDefault(require("../../../shared/config"));
|
|
9
|
+
/**
|
|
10
|
+
* Where adapters are looked up, in order. Also read by bin/validate-adapters.ts,
|
|
11
|
+
* which checks adapter implementations at build time - keep this the only place
|
|
12
|
+
* the lookup order is declared, so a name resolves there exactly as it does here.
|
|
13
|
+
*/
|
|
14
|
+
function buildAdapterPaths(configInstance) {
|
|
15
|
+
return Array.from(new Set([
|
|
16
|
+
'', // A blank path will cause us to check node_modules for the adapter
|
|
17
|
+
configInstance.get('paths').internalAdaptersPath,
|
|
18
|
+
// custom docker builds may install adapters in a separate path from content,
|
|
19
|
+
// since the content dir is often bind-mounted into the container. Offering
|
|
20
|
+
// an escape hatch here to allow for this
|
|
21
|
+
configInstance.get('paths').installedAdaptersPath ?? '',
|
|
22
|
+
// load adapters from content last, so that they don't override any other
|
|
23
|
+
// internal or platform-installed adapters
|
|
24
|
+
// TODO: potentially deprecate/remove as part of Ghost 7.0
|
|
25
|
+
configInstance.getContentPath('adapters')
|
|
26
|
+
]));
|
|
27
|
+
}
|
|
28
|
+
exports.adapterPaths = buildAdapterPaths(config_1.default);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import config from '../../../shared/config';
|
|
2
|
+
import type {ConfigInstance} from '../../../shared/config/loader';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Where adapters are looked up, in order. Also read by bin/validate-adapters.ts,
|
|
6
|
+
* which checks adapter implementations at build time - keep this the only place
|
|
7
|
+
* the lookup order is declared, so a name resolves there exactly as it does here.
|
|
8
|
+
*/
|
|
9
|
+
export function buildAdapterPaths(configInstance: ConfigInstance): string[] {
|
|
10
|
+
return Array.from(new Set<string>([
|
|
11
|
+
'', // A blank path will cause us to check node_modules for the adapter
|
|
12
|
+
configInstance.get('paths').internalAdaptersPath,
|
|
13
|
+
|
|
14
|
+
// custom docker builds may install adapters in a separate path from content,
|
|
15
|
+
// since the content dir is often bind-mounted into the container. Offering
|
|
16
|
+
// an escape hatch here to allow for this
|
|
17
|
+
configInstance.get('paths').installedAdaptersPath ?? '',
|
|
18
|
+
|
|
19
|
+
// load adapters from content last, so that they don't override any other
|
|
20
|
+
// internal or platform-installed adapters
|
|
21
|
+
// TODO: potentially deprecate/remove as part of Ghost 7.0
|
|
22
|
+
configInstance.getContentPath('adapters')
|
|
23
|
+
]));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const adapterPaths: string[] = buildAdapterPaths(config);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.baseClasses = void 0;
|
|
4
|
+
const ghost_storage_base_1 = require("ghost-storage-base");
|
|
5
|
+
const adapter_base_scheduling_1 = require("@tryghost/adapter-base-scheduling");
|
|
6
|
+
const adapter_base_sso_1 = require("@tryghost/adapter-base-sso");
|
|
7
|
+
const adapter_base_cache_1 = require("@tryghost/adapter-base-cache");
|
|
8
|
+
const adapter_base_redirects_1 = require("@tryghost/adapter-base-redirects");
|
|
9
|
+
const adapter_base_route_settings_1 = require("@tryghost/adapter-base-route-settings");
|
|
10
|
+
/**
|
|
11
|
+
* The base class every adapter of a given type must extend. Also read by
|
|
12
|
+
* bin/validate-adapters.js, which checks adapter implementations at build time -
|
|
13
|
+
* keep this the only place the mapping is declared.
|
|
14
|
+
*/
|
|
15
|
+
exports.baseClasses = {
|
|
16
|
+
storage: ghost_storage_base_1.StorageBase,
|
|
17
|
+
scheduling: adapter_base_scheduling_1.SchedulingBase,
|
|
18
|
+
sso: adapter_base_sso_1.SSOBase,
|
|
19
|
+
cache: adapter_base_cache_1.CacheBase,
|
|
20
|
+
redirects: adapter_base_redirects_1.RedirectsStoreBase,
|
|
21
|
+
'route-settings': adapter_base_route_settings_1.RouteSettingsStoreBase
|
|
22
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {StorageBase} from 'ghost-storage-base';
|
|
2
|
+
import {SchedulingBase} from '@tryghost/adapter-base-scheduling';
|
|
3
|
+
import {SSOBase} from '@tryghost/adapter-base-sso';
|
|
4
|
+
import {CacheBase} from '@tryghost/adapter-base-cache';
|
|
5
|
+
import {RedirectsStoreBase} from '@tryghost/adapter-base-redirects';
|
|
6
|
+
import {RouteSettingsStoreBase} from '@tryghost/adapter-base-route-settings';
|
|
7
|
+
|
|
8
|
+
import type {BaseClassMap} from './adapter-manager';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The base class every adapter of a given type must extend. Also read by
|
|
12
|
+
* bin/validate-adapters.js, which checks adapter implementations at build time -
|
|
13
|
+
* keep this the only place the mapping is declared.
|
|
14
|
+
*/
|
|
15
|
+
export const baseClasses = {
|
|
16
|
+
storage: StorageBase,
|
|
17
|
+
scheduling: SchedulingBase,
|
|
18
|
+
sso: SSOBase,
|
|
19
|
+
cache: CacheBase,
|
|
20
|
+
redirects: RedirectsStoreBase,
|
|
21
|
+
'route-settings': RouteSettingsStoreBase
|
|
22
|
+
} satisfies BaseClassMap;
|
|
@@ -3,40 +3,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const ghost_storage_base_1 = require("ghost-storage-base");
|
|
7
|
-
const adapter_base_scheduling_1 = require("@tryghost/adapter-base-scheduling");
|
|
8
|
-
const adapter_base_sso_1 = require("@tryghost/adapter-base-sso");
|
|
9
|
-
const adapter_base_cache_1 = require("@tryghost/adapter-base-cache");
|
|
10
|
-
const adapter_base_redirects_1 = require("@tryghost/adapter-base-redirects");
|
|
11
|
-
const adapter_base_route_settings_1 = require("@tryghost/adapter-base-route-settings");
|
|
12
6
|
const adapter_manager_1 = require("./adapter-manager");
|
|
7
|
+
const adapter_paths_1 = require("./adapter-paths");
|
|
8
|
+
const base_classes_1 = require("./base-classes");
|
|
13
9
|
const config_1 = __importDefault(require("../../../shared/config"));
|
|
14
|
-
const adapterPaths = new Set([
|
|
15
|
-
'', // A blank path will cause us to check node_modules for the adapter
|
|
16
|
-
config_1.default.get('paths').internalAdaptersPath,
|
|
17
|
-
// custom docker builds may install adapters in a separate path from content,
|
|
18
|
-
// since the content dir is often bind-mounted into the container. Offering
|
|
19
|
-
// an escape hatch here to allow for this
|
|
20
|
-
config_1.default.get('paths').installedAdaptersPath ?? '',
|
|
21
|
-
// load adapters from content last, so that they don't override any other
|
|
22
|
-
// internal or platform-installed adapters
|
|
23
|
-
// TODO: potentially deprecate/remove as part of Ghost 7.0
|
|
24
|
-
config_1.default.getContentPath('adapters'),
|
|
25
|
-
]);
|
|
26
10
|
// A singleton adapter manager, preconfigured with the base classes for every
|
|
27
11
|
// known adapter type. `getAdapter` resolves the active adapter and its options
|
|
28
12
|
// from config on each call, so runtime config changes are always reflected.
|
|
29
13
|
const adapterManager = new adapter_manager_1.AdapterManager({
|
|
30
14
|
loadAdapterFromPath: require,
|
|
31
15
|
config: config_1.default,
|
|
32
|
-
pathsToAdapters:
|
|
33
|
-
baseClasses:
|
|
34
|
-
storage: ghost_storage_base_1.StorageBase,
|
|
35
|
-
scheduling: adapter_base_scheduling_1.SchedulingBase,
|
|
36
|
-
sso: adapter_base_sso_1.SSOBase,
|
|
37
|
-
cache: adapter_base_cache_1.CacheBase,
|
|
38
|
-
redirects: adapter_base_redirects_1.RedirectsStoreBase,
|
|
39
|
-
'route-settings': adapter_base_route_settings_1.RouteSettingsStoreBase
|
|
40
|
-
}
|
|
16
|
+
pathsToAdapters: adapter_paths_1.adapterPaths,
|
|
17
|
+
baseClasses: base_classes_1.baseClasses
|
|
41
18
|
});
|
|
42
19
|
exports.default = adapterManager;
|
|
@@ -1,43 +1,16 @@
|
|
|
1
|
-
import {StorageBase} from 'ghost-storage-base';
|
|
2
|
-
import {SchedulingBase} from '@tryghost/adapter-base-scheduling';
|
|
3
|
-
import {SSOBase} from '@tryghost/adapter-base-sso';
|
|
4
|
-
import {CacheBase} from '@tryghost/adapter-base-cache';
|
|
5
|
-
import {RedirectsStoreBase} from '@tryghost/adapter-base-redirects';
|
|
6
|
-
import {RouteSettingsStoreBase} from '@tryghost/adapter-base-route-settings';
|
|
7
|
-
|
|
8
1
|
import {AdapterManager} from './adapter-manager';
|
|
2
|
+
import {adapterPaths} from './adapter-paths';
|
|
3
|
+
import {baseClasses} from './base-classes';
|
|
9
4
|
import config from '../../../shared/config';
|
|
10
5
|
|
|
11
|
-
const adapterPaths = new Set<string>([
|
|
12
|
-
'', // A blank path will cause us to check node_modules for the adapter
|
|
13
|
-
config.get('paths').internalAdaptersPath,
|
|
14
|
-
|
|
15
|
-
// custom docker builds may install adapters in a separate path from content,
|
|
16
|
-
// since the content dir is often bind-mounted into the container. Offering
|
|
17
|
-
// an escape hatch here to allow for this
|
|
18
|
-
config.get('paths').installedAdaptersPath ?? '',
|
|
19
|
-
|
|
20
|
-
// load adapters from content last, so that they don't override any other
|
|
21
|
-
// internal or platform-installed adapters
|
|
22
|
-
// TODO: potentially deprecate/remove as part of Ghost 7.0
|
|
23
|
-
config.getContentPath('adapters'),
|
|
24
|
-
]);
|
|
25
|
-
|
|
26
6
|
// A singleton adapter manager, preconfigured with the base classes for every
|
|
27
7
|
// known adapter type. `getAdapter` resolves the active adapter and its options
|
|
28
8
|
// from config on each call, so runtime config changes are always reflected.
|
|
29
9
|
const adapterManager = new AdapterManager({
|
|
30
10
|
loadAdapterFromPath: require,
|
|
31
11
|
config,
|
|
32
|
-
pathsToAdapters:
|
|
33
|
-
baseClasses
|
|
34
|
-
storage: StorageBase,
|
|
35
|
-
scheduling: SchedulingBase,
|
|
36
|
-
sso: SSOBase,
|
|
37
|
-
cache: CacheBase,
|
|
38
|
-
redirects: RedirectsStoreBase,
|
|
39
|
-
'route-settings': RouteSettingsStoreBase
|
|
40
|
-
}
|
|
12
|
+
pathsToAdapters: adapterPaths,
|
|
13
|
+
baseClasses
|
|
41
14
|
});
|
|
42
15
|
|
|
43
16
|
export default adapterManager;
|
|
@@ -5,12 +5,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.resolveAdapterEntryPoint = resolveAdapterEntryPoint;
|
|
7
7
|
exports.resolveAdapterExport = resolveAdapterExport;
|
|
8
|
+
exports.loadAdapterClass = loadAdapterClass;
|
|
8
9
|
exports.normalizeAdapterConfig = normalizeAdapterConfig;
|
|
9
10
|
exports.getConfiguredFeatures = getConfiguredFeatures;
|
|
10
11
|
exports.resolveAdapterOptions = resolveAdapterOptions;
|
|
11
12
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
12
13
|
const node_path_1 = __importDefault(require("node:path"));
|
|
13
14
|
const node_module_1 = require("node:module");
|
|
15
|
+
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
14
16
|
/**
|
|
15
17
|
* Whether `filePath` resolves to a location inside `directory`.
|
|
16
18
|
*
|
|
@@ -116,6 +118,54 @@ function resolveAdapterExport(moduleExport) {
|
|
|
116
118
|
}
|
|
117
119
|
return null;
|
|
118
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Locate and load an adapter constructor by type and class name, trying each of
|
|
123
|
+
* `pathsToAdapters` in order. Shared by the adapter manager and by
|
|
124
|
+
* bin/validate-adapters.ts, so a name resolves — and fails — identically at build
|
|
125
|
+
* time and at runtime.
|
|
126
|
+
*/
|
|
127
|
+
function loadAdapterClass(adapterType, adapterClassName, pathsToAdapters, loadAdapterFromPath) {
|
|
128
|
+
for (const pathToAdapters of pathsToAdapters) {
|
|
129
|
+
let pathToAdapter = node_path_1.default.join(pathToAdapters, adapterType, adapterClassName);
|
|
130
|
+
if (pathToAdapters === '') {
|
|
131
|
+
// We are loading from node_modules, we can remove the `adapterType` prefix
|
|
132
|
+
pathToAdapter = node_path_1.default.join(pathToAdapters, adapterClassName);
|
|
133
|
+
}
|
|
134
|
+
// An adapter directory may be a full module with its own
|
|
135
|
+
// package.json, in which case this resolves the `exports` entry
|
|
136
|
+
// point; otherwise the path passes through unchanged.
|
|
137
|
+
const moduleToLoad = resolveAdapterEntryPoint(pathToAdapter);
|
|
138
|
+
try {
|
|
139
|
+
const Adapter = resolveAdapterExport(loadAdapterFromPath(moduleToLoad));
|
|
140
|
+
if (Adapter) {
|
|
141
|
+
return Adapter;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
// Catch runtime errors
|
|
146
|
+
if (!(err instanceof Error) || err.code !== 'MODULE_NOT_FOUND') {
|
|
147
|
+
throw new errors_1.default.IncorrectUsageError({ err: err });
|
|
148
|
+
}
|
|
149
|
+
// Catch missing dependencies BUT NOT missing adapter.
|
|
150
|
+
// Only check the first line — Node appends a "Require stack"
|
|
151
|
+
// that includes the adapter's own path, which would false-positive.
|
|
152
|
+
const firstLine = err.message.split('\n')[0];
|
|
153
|
+
if (!firstLine.includes(pathToAdapter)) {
|
|
154
|
+
// Name the unresolved module so the error is actionable, e.g.
|
|
155
|
+
// "Cannot find module 'superagent'" -> 'superagent'.
|
|
156
|
+
const missingMatch = /Cannot find module '([^']+)'/.exec(firstLine);
|
|
157
|
+
const missingModule = missingMatch ? ` '${missingMatch[1]}'` : '';
|
|
158
|
+
throw new errors_1.default.IncorrectUsageError({
|
|
159
|
+
message: `You are missing a dependency${missingModule} in your adapter ${pathToAdapter}`,
|
|
160
|
+
err: err
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
throw new errors_1.default.IncorrectUsageError({
|
|
166
|
+
message: `Unable to find ${adapterType} adapter ${adapterClassName} in ${pathsToAdapters}.`
|
|
167
|
+
});
|
|
168
|
+
}
|
|
119
169
|
function getSchedulingConfig(config) {
|
|
120
170
|
const adapterConfig = config.get('adapters:scheduling');
|
|
121
171
|
if (!adapterConfig) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import {createRequire} from 'node:module';
|
|
4
|
+
import errors from '@tryghost/errors';
|
|
4
5
|
import type {AdapterConstructor} from "./types";
|
|
5
6
|
import type {ConfigInstance} from '../../../shared/config/loader';
|
|
6
7
|
|
|
@@ -122,6 +123,62 @@ export function resolveAdapterExport(moduleExport: unknown): AdapterConstructor
|
|
|
122
123
|
return null;
|
|
123
124
|
}
|
|
124
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Locate and load an adapter constructor by type and class name, trying each of
|
|
128
|
+
* `pathsToAdapters` in order. Shared by the adapter manager and by
|
|
129
|
+
* bin/validate-adapters.ts, so a name resolves — and fails — identically at build
|
|
130
|
+
* time and at runtime.
|
|
131
|
+
*/
|
|
132
|
+
export function loadAdapterClass(
|
|
133
|
+
adapterType: string,
|
|
134
|
+
adapterClassName: string,
|
|
135
|
+
pathsToAdapters: string[],
|
|
136
|
+
loadAdapterFromPath: (path: string) => unknown
|
|
137
|
+
): AdapterConstructor {
|
|
138
|
+
for (const pathToAdapters of pathsToAdapters) {
|
|
139
|
+
let pathToAdapter = path.join(pathToAdapters, adapterType, adapterClassName);
|
|
140
|
+
if (pathToAdapters === '') {
|
|
141
|
+
// We are loading from node_modules, we can remove the `adapterType` prefix
|
|
142
|
+
pathToAdapter = path.join(pathToAdapters, adapterClassName);
|
|
143
|
+
}
|
|
144
|
+
// An adapter directory may be a full module with its own
|
|
145
|
+
// package.json, in which case this resolves the `exports` entry
|
|
146
|
+
// point; otherwise the path passes through unchanged.
|
|
147
|
+
const moduleToLoad = resolveAdapterEntryPoint(pathToAdapter);
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
const Adapter = resolveAdapterExport(loadAdapterFromPath(moduleToLoad));
|
|
151
|
+
if (Adapter) {
|
|
152
|
+
return Adapter;
|
|
153
|
+
}
|
|
154
|
+
} catch (err) {
|
|
155
|
+
// Catch runtime errors
|
|
156
|
+
if (!(err instanceof Error) || (err as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND') {
|
|
157
|
+
throw new errors.IncorrectUsageError({err: err as Error});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Catch missing dependencies BUT NOT missing adapter.
|
|
161
|
+
// Only check the first line — Node appends a "Require stack"
|
|
162
|
+
// that includes the adapter's own path, which would false-positive.
|
|
163
|
+
const firstLine = err.message.split('\n')[0];
|
|
164
|
+
if (!firstLine.includes(pathToAdapter)) {
|
|
165
|
+
// Name the unresolved module so the error is actionable, e.g.
|
|
166
|
+
// "Cannot find module 'superagent'" -> 'superagent'.
|
|
167
|
+
const missingMatch = /Cannot find module '([^']+)'/.exec(firstLine);
|
|
168
|
+
const missingModule = missingMatch ? ` '${missingMatch[1]}'` : '';
|
|
169
|
+
throw new errors.IncorrectUsageError({
|
|
170
|
+
message: `You are missing a dependency${missingModule} in your adapter ${pathToAdapter}`,
|
|
171
|
+
err: err as Error
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
throw new errors.IncorrectUsageError({
|
|
178
|
+
message: `Unable to find ${adapterType} adapter ${adapterClassName} in ${pathsToAdapters}.`
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
125
182
|
function getSchedulingConfig(config: ConfigInstance) {
|
|
126
183
|
const adapterConfig = config.get('adapters:scheduling');
|
|
127
184
|
if (!adapterConfig) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const Feedback = require('./feedback');
|
|
2
2
|
const errors = require('@tryghost/errors');
|
|
3
|
+
const permissions = require('../../services/permissions');
|
|
3
4
|
const tpl = require('@tryghost/tpl');
|
|
4
5
|
|
|
5
6
|
const messages = {
|
|
@@ -50,7 +51,7 @@ class AudienceFeedbackController {
|
|
|
50
51
|
// Load the full post (with tags/authors) rather than passing an
|
|
51
52
|
// id-only resource: the URL service needs status to apply the
|
|
52
53
|
// published base filter and tags/authors to evaluate filtered
|
|
53
|
-
// routes — the
|
|
54
|
+
// routes — the URL service reports a bare {id} as thin.
|
|
54
55
|
const post = await this.#repository.getPostById(postId, {withRelated: ['tags', 'authors']});
|
|
55
56
|
const target = post
|
|
56
57
|
? this.#audienceFeedbackService.buildLink(uuid, post, score, key)
|
|
@@ -118,7 +119,8 @@ class AudienceFeedbackController {
|
|
|
118
119
|
const postId = frame.data.id;
|
|
119
120
|
const options = {
|
|
120
121
|
limit: frame.options.limit || 10,
|
|
121
|
-
page: frame.options.page || 1
|
|
122
|
+
page: frame.options.page || 1,
|
|
123
|
+
withMember: false
|
|
122
124
|
};
|
|
123
125
|
|
|
124
126
|
// Add score filter if specified
|
|
@@ -126,6 +128,13 @@ class AudienceFeedbackController {
|
|
|
126
128
|
options.score = parseInt(frame.options.score);
|
|
127
129
|
}
|
|
128
130
|
|
|
131
|
+
try {
|
|
132
|
+
await permissions.canThis(frame.options.context).browse.member();
|
|
133
|
+
options.withMember = true;
|
|
134
|
+
} catch {
|
|
135
|
+
// permissions throws; we want to return data but without member info
|
|
136
|
+
}
|
|
137
|
+
|
|
129
138
|
const result = await this.#repository.getForPost(postId, options);
|
|
130
139
|
return result;
|
|
131
140
|
}
|
|
@@ -24,7 +24,7 @@ class AudienceFeedbackService {
|
|
|
24
24
|
*/
|
|
25
25
|
buildLink(uuid, post, score, key) {
|
|
26
26
|
const postData = toPlain(post);
|
|
27
|
-
let postUrl = this.#urlService.
|
|
27
|
+
let postUrl = this.#urlService.getUrlForResource({...postData, type: 'posts'}, {absolute: true});
|
|
28
28
|
|
|
29
29
|
if (postUrl.match(/\/404\//)) {
|
|
30
30
|
postUrl = this.#baseURL;
|
|
@@ -36,7 +36,7 @@ class AudienceFeedbackService {
|
|
|
36
36
|
* Feedback link for a post that no longer exists. Goes straight to the
|
|
37
37
|
* home page — the same destination buildLink picks when the URL service
|
|
38
38
|
* has no URL for the post — without asking the URL service: an id-only
|
|
39
|
-
* resource can't be routed (the
|
|
39
|
+
* resource can't be routed (the URL service reports it as thin).
|
|
40
40
|
*
|
|
41
41
|
* @param {string} uuid
|
|
42
42
|
* @param {string} postId
|
|
@@ -76,10 +76,13 @@ module.exports = class FeedbackRepository {
|
|
|
76
76
|
limit: options.limit || 10,
|
|
77
77
|
page: options.page || 1,
|
|
78
78
|
order: 'created_at DESC',
|
|
79
|
-
withRelated: ['member'],
|
|
80
79
|
filter: filter
|
|
81
80
|
};
|
|
82
81
|
|
|
82
|
+
if (options.withMember) {
|
|
83
|
+
findOptions.withRelated = ['member'];
|
|
84
|
+
}
|
|
85
|
+
|
|
83
86
|
// Use findPage with filter
|
|
84
87
|
const results = await this.#MemberFeedback.findPage(findOptions);
|
|
85
88
|
|
|
@@ -26,6 +26,7 @@ const AUTH_CODE_CHALLENGE_BYTES = 16;
|
|
|
26
26
|
* @prop {string} user_agent
|
|
27
27
|
* @prop {string} ip
|
|
28
28
|
* @prop {boolean} verified
|
|
29
|
+
* @prop {string} [verified_user_id]
|
|
29
30
|
* @prop {string} [auth_code_challenge]
|
|
30
31
|
* @prop {number} [auth_code_generated_at]
|
|
31
32
|
*/
|
|
@@ -190,12 +191,14 @@ module.exports = function createSessionService({
|
|
|
190
191
|
|
|
191
192
|
if (isAuthCodeVerified) {
|
|
192
193
|
session.verified = true;
|
|
194
|
+
session.verified_user_id = user.id;
|
|
193
195
|
invalidateAuthCodeChallenge(session);
|
|
194
196
|
}
|
|
195
197
|
}
|
|
196
198
|
|
|
197
199
|
if (isStaffDeviceVerificationDisabled()) {
|
|
198
200
|
session.verified = true;
|
|
201
|
+
session.verified_user_id = user.id;
|
|
199
202
|
}
|
|
200
203
|
}
|
|
201
204
|
|
|
@@ -214,6 +217,7 @@ module.exports = function createSessionService({
|
|
|
214
217
|
const {
|
|
215
218
|
user_id: previousUserId,
|
|
216
219
|
verified: previousVerified,
|
|
220
|
+
verified_user_id: previousVerifiedUserId,
|
|
217
221
|
auth_code_challenge: previousAuthCodeChallenge,
|
|
218
222
|
auth_code_generated_at: previousAuthCodeGeneratedAt
|
|
219
223
|
} = previousSession;
|
|
@@ -231,8 +235,11 @@ module.exports = function createSessionService({
|
|
|
231
235
|
|
|
232
236
|
const session = req.session;
|
|
233
237
|
session.user_id = previousUserId;
|
|
234
|
-
//
|
|
235
|
-
|
|
238
|
+
// Verification is bound to the user who completed it — any other user
|
|
239
|
+
// (including sessions with no verified_user_id) must verify again
|
|
240
|
+
const carryVerification = previousVerified === true && previousVerifiedUserId === user.id;
|
|
241
|
+
session.verified = carryVerification ? true : undefined;
|
|
242
|
+
session.verified_user_id = carryVerification ? previousVerifiedUserId : undefined;
|
|
236
243
|
session.auth_code_challenge = previousAuthCodeChallenge;
|
|
237
244
|
session.auth_code_generated_at = previousAuthCodeGeneratedAt;
|
|
238
245
|
|
|
@@ -282,6 +289,7 @@ module.exports = function createSessionService({
|
|
|
282
289
|
});
|
|
283
290
|
|
|
284
291
|
session.verified = true;
|
|
292
|
+
session.verified_user_id = user.id;
|
|
285
293
|
invalidateAuthCodeChallenge(session);
|
|
286
294
|
}
|
|
287
295
|
|
|
@@ -480,6 +488,7 @@ module.exports = function createSessionService({
|
|
|
480
488
|
async function verifySession(req, res) {
|
|
481
489
|
const session = await getSession(req, res);
|
|
482
490
|
session.verified = true;
|
|
491
|
+
session.verified_user_id = session.user_id;
|
|
483
492
|
invalidateAuthCodeChallenge(session);
|
|
484
493
|
}
|
|
485
494
|
|
|
@@ -491,7 +500,12 @@ module.exports = function createSessionService({
|
|
|
491
500
|
*/
|
|
492
501
|
async function isVerifiedSession(req, res) {
|
|
493
502
|
const session = await getSession(req, res);
|
|
494
|
-
|
|
503
|
+
// Verification is bound to a user; a session with no verified_user_id
|
|
504
|
+
// (e.g. logged out, or predating this field) fails closed rather than
|
|
505
|
+
// matching an absent user_id via undefined === undefined
|
|
506
|
+
return session.verified === true &&
|
|
507
|
+
!!session.verified_user_id &&
|
|
508
|
+
session.verified_user_id === session.user_id;
|
|
495
509
|
}
|
|
496
510
|
|
|
497
511
|
/**
|
|
@@ -506,6 +520,7 @@ module.exports = function createSessionService({
|
|
|
506
520
|
|
|
507
521
|
if (isVerificationRequired()) {
|
|
508
522
|
session.verified = undefined;
|
|
523
|
+
session.verified_user_id = undefined;
|
|
509
524
|
}
|
|
510
525
|
|
|
511
526
|
invalidateAuthCodeChallenge(session);
|