ghost 6.47.0 → 6.48.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/MigratorConfig.js +0 -1
- package/bin/create-migration.js +1 -1
- package/bin/generate-golden-email.js +0 -1
- package/components/tryghost-i18n-0.0.0.tgz +0 -0
- package/core/boot.js +13 -7
- package/core/built/admin/assets/{PolarAngleAxis-CLluELUg.js → PolarAngleAxis-DufzOBEz.js} +1 -1
- package/core/built/admin/assets/{_baseAssignValue-Dz1iqdwD.js → _baseAssignValue-BjUm4QeA.js} +1 -1
- package/core/built/admin/assets/{a-large-small-BA74vHPp.js → a-large-small-D0RF_WS9.js} +1 -1
- package/core/built/admin/assets/{account-migration-B-NqdKuN.js → account-migration-B7n6ezrZ.js} +1 -1
- package/core/built/admin/assets/activitypub/{account-migration-ClmVrAXr.js → account-migration-BJeRnMCl.js} +3 -3
- package/core/built/admin/assets/activitypub/activitypub.js +1 -1
- package/core/built/admin/assets/activitypub/{at-sign-9F3qd4Nn.js → at-sign-BygVOKdj.js} +2 -2
- package/core/built/admin/assets/activitypub/{avatar-flipboard-jBHA13Ej.js → avatar-flipboard-CNcjI8lK.js} +2 -2
- package/core/built/admin/assets/activitypub/{bluesky-sharing-1irhvVtF.js → bluesky-sharing-mgBNeRfA.js} +4 -4
- package/core/built/admin/assets/activitypub/{copy-DXRvsGiK.js → copy-BMChXIQc.js} +2 -2
- package/core/built/admin/assets/activitypub/{deleted-feed-item-67VQJde4.js → deleted-feed-item-D-spb6V1.js} +2 -2
- package/core/built/admin/assets/activitypub/{edit-profile-BfpbEj98.js → edit-profile-CDQ3V8-c.js} +4 -4
- package/core/built/admin/assets/activitypub/{feed-DUrI7SPC.js → feed-Vqr3WU-V.js} +4 -4
- package/core/built/admin/assets/activitypub/{hash-CMtB10PN.js → hash-D7SSXVOg.js} +2 -2
- package/core/built/admin/assets/activitypub/{inbox-2xq8SJ7A.js → inbox-BHk5Dw27.js} +2 -2
- package/core/built/admin/assets/activitypub/{index-BT97xLpd.js → index-BejkeH-m.js} +2 -2
- package/core/built/admin/assets/activitypub/{index-DssHQAjK.js → index-BqL23J-m.js} +32 -32
- package/core/built/admin/assets/activitypub/{index-Ba6FXt8y.js → index-CHhvjNuG.js} +6 -6
- package/core/built/admin/assets/activitypub/{index-ERtz4Bvy.js → index-CZsNO9hA.js} +5 -5
- package/core/built/admin/assets/activitypub/{index-sgY7lLrg.js → index-CaIhRYzz.js} +3 -3
- package/core/built/admin/assets/activitypub/{index-D1EWoXrK.js → index-DA2MkQVu.js} +2 -2
- package/core/built/admin/assets/activitypub/{index-sudOvKcY.js → index-DHhFcmfu.js} +21 -21
- package/core/built/admin/assets/activitypub/{index-Ccighz1t.js → index-sh2bDSls.js} +4 -4
- package/core/built/admin/assets/activitypub/{label-KQSsSjmN.js → label-D80yhOIm.js} +2 -2
- package/core/built/admin/assets/activitypub/{moderation-B78if-r0.js → moderation-LJNmKBCi.js} +3 -3
- package/core/built/admin/assets/activitypub/{note-Bfr7ovn7.js → note-CyjKLcQ-.js} +4 -4
- package/core/built/admin/assets/activitypub/{reply-CehesW8Z.js → reply-BiiCFx7G.js} +2 -2
- package/core/built/admin/assets/activitypub/{separator-B_Ly_Qq8.js → separator-CY3PMmtI.js} +2 -2
- package/core/built/admin/assets/activitypub/{settings-D6R97p7v.js → settings-BQy6Gr7R.js} +3 -3
- package/core/built/admin/assets/activitypub/{step-1-Cl1YxgZ1.js → step-1-DCqRwgf3.js} +3 -3
- package/core/built/admin/assets/activitypub/{step-2-DDyR--Qe.js → step-2-DQlhehTO.js} +5 -5
- package/core/built/admin/assets/activitypub/{step-3-Don8gv0n.js → step-3-DAUCAcxW.js} +7 -7
- package/core/built/admin/assets/activitypub/{tabs-DTpfm-wu.js → tabs-B_6UuI7r.js} +3 -3
- package/core/built/admin/assets/activitypub/{topic-filter-Oee10885.js → topic-filter--FT1A_dc.js} +2 -2
- package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +1 -1
- package/core/built/admin/assets/admin-x-settings/{code-editor-view-CGZuiDGx.js → code-editor-view-Bp_sCJR0.js} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-CwEblQZC.js → index-BPXA3pTW.js} +5 -5
- package/core/built/admin/assets/admin-x-settings/{index-rr_UntGE.js → index-BS375mg1.js} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-BpM6W2br.js → index-B_PlQoEG.js} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-BGdS5xw4.js → index-BflhAbu2.js} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-DtWUeJhp.js → index-CftMe8fe.js} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-B65inCwj.js → index-DRB7FH6y.js} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-DSX261S9.js → index-DijZ3oAM.js} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-DF6YEs01.js → index-cV0Lof9H.js} +1526 -1500
- package/core/built/admin/assets/admin-x-settings/{index-CluZYkUC.js → index-qc4x3vZj.js} +3 -3
- package/core/built/admin/assets/admin-x-settings/{modals-Bf4KOU31.js → modals-CkjuEByw.js} +55 -67
- package/core/built/admin/assets/{arrow-right-BxP3aeA5.js → arrow-right-BF77Yx73.js} +1 -1
- package/core/built/admin/assets/{at-sign-Bf0y-jim.js → at-sign-DhJF3n_V.js} +1 -1
- package/core/built/admin/assets/{audience-DHR1WgFK.js → audience-DHPKKayV.js} +1 -1
- package/core/built/admin/assets/{automated-emails-DbJbDLib.js → automated-emails-DInKYTEC.js} +1 -1
- package/core/built/admin/assets/{automations-aLgTzSsZ.js → automations-DJpeZw9T.js} +1 -1
- package/core/built/admin/assets/automations-DpQKN9j0.js +1 -0
- package/core/built/admin/assets/{avatar-flipboard-B0F2LMW5.js → avatar-flipboard-yRdmFC6R.js} +1 -1
- package/core/built/admin/assets/{bluesky-sharing-DjhtIuyr.js → bluesky-sharing-qSiCERoR.js} +1 -1
- package/core/built/admin/assets/{chart-BGwxlD0z.js → chart-CP2N9ZC-.js} +1 -1
- package/core/built/admin/assets/{chevron-up-C2FeVzre.js → chevron-up-BQ6fOpFR.js} +1 -1
- package/core/built/admin/assets/{chunk.524.31b31f7958dfae110016.js → chunk.524.ad4560630d4d62fbceb5.js} +4 -4
- package/core/built/admin/assets/{chunk.582.a855020953886af6e83b.js → chunk.582.fd4878e4e0af31ef86c0.js} +6 -6
- package/core/built/admin/assets/{chunk.972.258e6b1dab79b2189f1c.js → chunk.98.69968e0f393d82c2949c.js} +4 -4
- package/core/built/admin/assets/{code-editor-view-DzPkm_nJ.js → code-editor-view-CVODiRVJ.js} +1 -1
- package/core/built/admin/assets/{comments-DgItXUWN.js → comments-CP-NxopD.js} +1 -1
- package/core/built/admin/assets/{content-helpers-BNefU_PE.js → content-helpers-Crzkusiq.js} +1 -1
- package/core/built/admin/assets/{copy-DoNNUZlb.js → copy-r1LFsU75.js} +1 -1
- package/core/built/admin/assets/{data-list-CO1cZQRU.js → data-list-CzSc7z-2.js} +1 -1
- package/core/built/admin/assets/{deleted-feed-item-DC2wSAhv.js → deleted-feed-item-PyEM8FiX.js} +1 -1
- package/core/built/admin/assets/{dropzone-BTODLafn.js → dropzone-DI8A9qO6.js} +1 -1
- package/core/built/admin/assets/{edit-profile-BMMpmWIZ.js → edit-profile-DlJ64lV7.js} +1 -1
- package/core/built/admin/assets/editor-CevNZicQ.js +8 -0
- package/core/built/admin/assets/{empty-indicator-Dza0FQlj.js → empty-indicator-Dxg05yWg.js} +1 -1
- package/core/built/admin/assets/{en-yf9qAqTu.js → en-D93GVp3o.js} +1 -1
- package/core/built/admin/assets/{eye-CAqnnfQF.js → eye-6POPPpTw.js} +1 -1
- package/core/built/admin/assets/{feed-BkNsbWiF.js → feed-P_RMYb5x.js} +1 -1
- package/core/built/admin/assets/{field-Ddb1ZOqM.js → field-DeNjwWrL.js} +1 -1
- package/core/built/admin/assets/{filter-query-core-5Mac92kh.js → filter-query-core-DFs5WSmA.js} +1 -1
- package/core/built/admin/assets/{filters-BCb4bgtg.js → filters-C_BSQgb7.js} +1 -1
- package/core/built/admin/assets/{gh-chart-C6zkIg8k.js → gh-chart-pNHAbeQn.js} +1 -1
- package/core/built/admin/assets/{ghost-5313258fd425ced5db6516acde01ba36.js → ghost-3f5b3569e0beec61266cb74077677fbc.js} +3 -3
- package/core/built/admin/assets/{growth-ezUlN8OE.js → growth-B83tVOYO.js} +1 -1
- package/core/built/admin/assets/{hash-DE2OmChI.js → hash-BCTATV5W.js} +1 -1
- package/core/built/admin/assets/{inbox-OthiHvlV.js → inbox-rE3c5suT.js} +1 -1
- package/core/built/admin/assets/{index-BLyzLfyx.js → index-7EiRc5Ay.js} +1 -1
- package/core/built/admin/assets/{index-CV5v0eFE.js → index-B5bpZGTI.js} +1 -1
- package/core/built/admin/assets/index-BNtzAd7H.css +1 -0
- package/core/built/admin/assets/{index-BC1yWeaJ.js → index-BT33w2Io.js} +1 -1
- package/core/built/admin/assets/{index-DjffQ3VJ.js → index-BbkXWdhb.js} +1 -1
- package/core/built/admin/assets/{index-DH6PA3W6.js → index-BfhSrnrJ.js} +1 -1
- package/core/built/admin/assets/{index-CRvK0Iac.js → index-BmR_OUpb.js} +1 -1
- package/core/built/admin/assets/{index-CNV7fxKZ.js → index-BuhMgn5c.js} +1 -1
- package/core/built/admin/assets/{index-pkixJbdq.js → index-C-075SzJ.js} +34 -34
- package/core/built/admin/assets/{index-DJoByVS8.js → index-CB3hJd9E.js} +1 -1
- package/core/built/admin/assets/{index-D3bb-MEJ.js → index-CCISLIQd.js} +1 -1
- package/core/built/admin/assets/{index-BIEhcKiV.js → index-Cnptpx11.js} +1 -1
- package/core/built/admin/assets/{index-DK1cu59e.js → index-CrBRU81r.js} +1 -1
- package/core/built/admin/assets/{index-B0_p1-R0.js → index-CscUHFJp.js} +1 -1
- package/core/built/admin/assets/{index-Bi5qzf86.js → index-D3ZzfuJt.js} +1 -1
- package/core/built/admin/assets/{index-CKPny_6u.js → index-D4wn-U0V.js} +1 -1
- package/core/built/admin/assets/{index-YzcsD17L.js → index-DNRlkUeu.js} +1 -1
- package/core/built/admin/assets/{index-BoMsDCxD.js → index-D_G6negZ.js} +1 -1
- package/core/built/admin/assets/{index-CwsmINtV.js → index-DfxHSK1s.js} +1 -1
- package/core/built/admin/assets/{index-X91I8PcS.js → index-Dpc3COTl.js} +1 -1
- package/core/built/admin/assets/{index-c1h-EQpd.js → index-UsbnU2jy.js} +1 -1
- package/core/built/admin/assets/{index-oKgNVmwC.js → index-VfrJzh5m.js} +1 -1
- package/core/built/admin/assets/{index-D5MrQBSe.js → index-fbxc8Dpt.js} +1 -1
- package/core/built/admin/assets/{input-group-BOLMrDfJ.js → input-group-BLygwiDK.js} +1 -1
- package/core/built/admin/assets/{koenig-lexical-DlzcWUPw.js → koenig-lexical-B9U3sBS5.js} +1 -1
- package/core/built/admin/assets/{kpi-card-BlF7JKRC.js → kpi-card-Bmnvvp4X.js} +1 -1
- package/core/built/admin/assets/{kpi-card-HDshm3lO.js → kpi-card-CGVtzdgJ.js} +1 -1
- package/core/built/admin/assets/{kpi-tabs-Dty6zMSP.js → kpi-tabs-DxbvMkIU.js} +1 -1
- package/core/built/admin/assets/{kpis-CFz4r5wW.js → kpis-CQBAGVjP.js} +1 -1
- package/core/built/admin/assets/{label-CVzNcbjb.js → label-DpTwHQi_.js} +1 -1
- package/core/built/admin/assets/{links-D9dHwDlP.js → links-Bdw25FJF.js} +1 -1
- package/core/built/admin/assets/{list-page-shoQED7N.js → list-page-BvTQwP5F.js} +1 -1
- package/core/built/admin/assets/{loader-circle-cad701gH.js → loader-circle-3HJkQKWf.js} +1 -1
- package/core/built/admin/assets/{mail-DG4PKpZy.js → mail-DvrqP73n.js} +1 -1
- package/core/built/admin/assets/{main-layout-BmFla3Se.js → main-layout-BAPpm0bz.js} +1 -1
- package/core/built/admin/assets/{members-d19Z6k1C.js → members-CF4CzJSf.js} +1 -1
- package/core/built/admin/assets/minus-DJIePlnU.js +1 -0
- package/core/built/admin/assets/modals-CVsVi0zu.js +35 -0
- package/core/built/admin/assets/{moderation-BWBLnh4h.js → moderation-BX1KH5QL.js} +1 -1
- package/core/built/admin/assets/{newsletter-DNY4MroI.js → newsletter-BlKeb58e.js} +1 -1
- package/core/built/admin/assets/{newsletters-B10iBPP-.js → newsletters-3In8H0Z5.js} +1 -1
- package/core/built/admin/assets/{note-S0b6wjRR.js → note-ybwJCAxm.js} +1 -1
- package/core/built/admin/assets/{offers-B-9mZqKd.js → offers-Cl0ZNEMr.js} +1 -1
- package/core/built/admin/assets/{onboarding-route-AMFn0X5G.js → onboarding-route-A3ECeMAi.js} +1 -1
- package/core/built/admin/assets/{overview-WKadyZRW.js → overview-DrMrfsk-.js} +1 -1
- package/core/built/admin/assets/{pagemenu-BofQcFaF.js → pagemenu-O7HbsehH.js} +1 -1
- package/core/built/admin/assets/{pencil-LfMcD0vS.js → pencil-CknTbJeE.js} +1 -1
- package/core/built/admin/assets/{pin-CayUjL8e.js → pin-BNs-JdQ3.js} +1 -1
- package/core/built/admin/assets/{post-analytics-DMHvt3Jl.js → post-analytics-Dk1VloZp.js} +1 -1
- package/core/built/admin/assets/{post-analytics-context-10cqioP1.js → post-analytics-context-kPL94Ivz.js} +1 -1
- package/core/built/admin/assets/{post-analytics-header-DlICE18K.js → post-analytics-header-CpMOozq-.js} +1 -1
- package/core/built/admin/assets/{post-share-modal-Cfwy2UwD.js → post-share-modal-F0dobdhF.js} +1 -1
- package/core/built/admin/assets/posts/{alert-dialog-cQK32v9G.js → alert-dialog-NoPLULhG.js} +5 -5
- package/core/built/admin/assets/posts/{app-utils-DQ2hixop.js → app-utils-BiM9QO4L.js} +3 -3
- package/core/built/admin/assets/posts/{automations-BqkU9-zY.js → automations-BgIAmq9f.js} +3 -3
- package/core/built/admin/assets/posts/{automations-CoilKpVH.js → automations-D_XwO405.js} +30 -30
- package/core/built/admin/assets/posts/{avatar-BejAO6Rj.js → avatar-BYsYOpmq.js} +5 -5
- package/core/built/admin/assets/posts/{badge-BYGRyd2f.js → badge-B54vLono.js} +2 -2
- package/core/built/admin/assets/posts/{button-CG2Dpjqy.js → button-DMLfwOQt.js} +3 -3
- package/core/built/admin/assets/posts/{check-fsC5BvGC.js → check-D6qDi62T.js} +2 -2
- package/core/built/admin/assets/posts/{comments-CsyF5C1S.js → comments-CyYCbvUG.js} +26 -26
- package/core/built/admin/assets/posts/{data-list-JslRF2F5.js → data-list-B0DrMm-x.js} +4 -4
- package/core/built/admin/assets/posts/{dialog-3KY3A8t5.js → dialog-DtEZpY1q.js} +3 -3
- package/core/built/admin/assets/posts/{editor-3HPW_xW4.js → editor-LJHLmUoW.js} +1943 -1943
- package/core/built/admin/assets/posts/{ellipsis-BhK5S70U.js → ellipsis-JeIF0Biz.js} +2 -2
- package/core/built/admin/assets/posts/{empty-indicator-C9DbE9wZ.js → empty-indicator-dktzN32y.js} +2 -2
- package/core/built/admin/assets/posts/{filters-BCBDCnQF.js → filters-D1L-LU_m.js} +10 -10
- package/core/built/admin/assets/posts/{get-site-timezone-83C41MGz.js → get-site-timezone-dsyl8nlB.js} +3 -3
- package/core/built/admin/assets/posts/{growth-COoL1kMe.js → growth-yX8UB_ce.js} +12 -12
- package/core/built/admin/assets/posts/{heading-D3VqNO3z.js → heading-CNte43wH.js} +2 -2
- package/core/built/admin/assets/posts/{hooks-5YpJYWOw.js → hooks-BIgv7QBp.js} +2 -2
- package/core/built/admin/assets/posts/{index-Dqn5WIFh.js → index-2FO6Vy0r.js} +11 -11
- package/core/built/admin/assets/posts/{input-C1qcZBGw.js → input-BycmlCp8.js} +3 -3
- package/core/built/admin/assets/posts/{input-surface-C4vUAdbV.js → input-surface-vY3ACaso.js} +2 -2
- package/core/built/admin/assets/posts/{koenig-lexical-NZjxFY0X.js → koenig-lexical-Cq8SUcZC.js} +2 -2
- package/core/built/admin/assets/posts/{kpis-C2FEXoUT.js → kpis-CAJcU1w0.js} +27 -27
- package/core/built/admin/assets/posts/{label-CmJzmJY7.js → label-BmLTflMF.js} +3 -3
- package/core/built/admin/assets/posts/{links-nzud7t_t.js → links-BVcmMZmF.js} +4 -4
- package/core/built/admin/assets/posts/{list-page-D_rv4TgN.js → list-page-DX2WRn5T.js} +4 -4
- package/core/built/admin/assets/posts/{loading-indicator-DAOD6O2b.js → loading-indicator-C6FD4nS6.js} +3 -3
- package/core/built/admin/assets/posts/{mail-CtH0gTpq.js → mail-BMyoNUVM.js} +2 -2
- package/core/built/admin/assets/posts/{main-layout-VqvCxOXQ.js → main-layout-ClnxdW1Y.js} +2 -2
- package/core/built/admin/assets/posts/{message-circle-D4bCjxKS.js → message-circle-DwfHX-p1.js} +2 -2
- package/core/built/admin/assets/posts/{newsletter-BfwFyv6d.js → newsletter-Bid5_Bim.js} +19 -19
- package/core/built/admin/assets/posts/{overview-DKGum6ro.js → overview-BXti6Wg_.js} +18 -18
- package/core/built/admin/assets/posts/{pencil-Cffx-vm3.js → pencil-ChTk8IpW.js} +2 -2
- package/core/built/admin/assets/posts/{plus-D2ekwsq0.js → plus-DIKls8C6.js} +2 -2
- package/core/built/admin/assets/posts/{popover-DdbdKflP.js → popover-DVZsAT5u.js} +4 -4
- package/core/built/admin/assets/posts/{post-analytics-BleJYoNZ.js → post-analytics-DBL_kS0g.js} +6 -6
- package/core/built/admin/assets/posts/{post-analytics-context-DT3Avn9Q.js → post-analytics-context-Dr5y5nxd.js} +6 -6
- package/core/built/admin/assets/posts/{post-analytics-header-BktlrM_v.js → post-analytics-header-LH2-Jzgp.js} +13 -13
- package/core/built/admin/assets/posts/{post-share-modal-G8v3ZuSg.js → post-share-modal-D4DrfNfJ.js} +6 -6
- package/core/built/admin/assets/posts/{posts-CdWV_nlm.js → posts-ByxhcCrn.js} +2 -2
- package/core/built/admin/assets/posts/posts.js +1 -1
- package/core/built/admin/assets/posts/{search-CXP00fG8.js → search-DZR23LP-.js} +2 -2
- package/core/built/admin/assets/posts/{settings-DEXxDYc2.js → settings-CWyOKKnK.js} +2 -2
- package/core/built/admin/assets/posts/{sheet-CXHmD_eT.js → sheet-CNe7II5c.js} +3 -3
- package/core/built/admin/assets/posts/{site-C6DajagV.js → site-H9RAiQVv.js} +2 -2
- package/core/built/admin/assets/posts/{skeleton-Bihnkn8q.js → skeleton-Cn6x1x_C.js} +3 -3
- package/core/built/admin/assets/posts/{source-icon-C3oQy3UI.js → source-icon-BZOYujd1.js} +4 -4
- package/core/built/admin/assets/posts/{stats-DFicPtCX.js → stats-ugHCg8Oe.js} +4 -4
- package/core/built/admin/assets/posts/{table-DSJmeU5t.js → table-dG3Q5X95.js} +2 -2
- package/core/built/admin/assets/posts/{tabs-oRdVpN8P.js → tabs--EW8uL5B.js} +4 -4
- package/core/built/admin/assets/posts/{tags-6v5Qt_05.js → tags-DVdOfiSf.js} +2 -2
- package/core/built/admin/assets/posts/{tags-Upnkm0CF.js → tags-i0HJqNYU.js} +16 -16
- package/core/built/admin/assets/posts/{tooltip-Ci7pesWi.js → tooltip-ZvsT1Fs9.js} +4 -4
- package/core/built/admin/assets/posts/{trash-2-NCYWjRlg.js → trash-2-BT9fEHUL.js} +2 -2
- package/core/built/admin/assets/posts/{value-CcwzOh2_.js → value-DoFcsWDk.js} +2 -2
- package/core/built/admin/assets/posts/{virtual-list-window-CNahQBXY.js → virtual-list-window-Bt47XODn.js} +3 -3
- package/core/built/admin/assets/posts/{web-C3KrPq0T.js → web-BMTRLT-h.js} +20 -20
- package/core/built/admin/assets/posts/{zap-k30mZEuO.js → zap-DcIfEzKX.js} +2 -2
- package/core/built/admin/assets/{posts-DAfLuxAA.js → posts-DODOCB1E.js} +1 -1
- package/core/built/admin/assets/{power-Drkzg1xX.js → power-BZ7BM82m.js} +1 -1
- package/core/built/admin/assets/{referrers-TYxTJ2On.js → referrers-xwNb6L-8.js} +1 -1
- package/core/built/admin/assets/{repeat-CTM1qAzl.js → repeat-DHMCQMCA.js} +1 -1
- package/core/built/admin/assets/{reply-DXN16g7W.js → reply-DoLURZi2.js} +1 -1
- package/core/built/admin/assets/{rocket-DLixlWs0.js → rocket-BDH89dZr.js} +1 -1
- package/core/built/admin/assets/{select-DbiLEqYb.js → select-oE39QRll.js} +1 -1
- package/core/built/admin/assets/{send-B71C_46D.js → send-QgRN_yRy.js} +1 -1
- package/core/built/admin/assets/{settings-BBMPA3MP.js → settings-CF4NLxuS.js} +4 -4
- package/core/built/admin/assets/{settings-lSFHFrsJ.js → settings-D7e6KLAi.js} +1 -1
- package/core/built/admin/assets/{share-modal-CXrYja6o.js → share-modal-BxIh7i7o.js} +1 -1
- package/core/built/admin/assets/{sort-button-WYo-9Kge.js → sort-button-CEe_40Pi.js} +1 -1
- package/core/built/admin/assets/{source-icon-D6BzjYPP.js → source-icon-CzTNLO6j.js} +1 -1
- package/core/built/admin/assets/{sprout-DVfG_qhy.js → sprout-B2fN41p-.js} +1 -1
- package/core/built/admin/assets/{square-BbUJwQJi.js → square-CJZsjE-3.js} +1 -1
- package/core/built/admin/assets/{stats-CnXALQ4j.js → stats-jTxCK1CB.js} +1 -1
- package/core/built/admin/assets/{stats-view-B-yeMUkl.js → stats-view-B4jz69N8.js} +1 -1
- package/core/built/admin/assets/{step-1-DUl_hlpV.js → step-1-BovjhDNc.js} +1 -1
- package/core/built/admin/assets/{step-2-DjX_A4Ke.js → step-2-ClG40BfX.js} +1 -1
- package/core/built/admin/assets/{step-3-CnDCCA8T.js → step-3-ZMSyEHZI.js} +1 -1
- package/core/built/admin/assets/{table-AagTvMa9.js → table-B8Pj96or.js} +1 -1
- package/core/built/admin/assets/{tabs-IDJWnQD-.js → tabs-BZosOk0o.js} +1 -1
- package/core/built/admin/assets/{tags-CXAcIDw-.js → tags-BpWoYBfB.js} +1 -1
- package/core/built/admin/assets/{tags-C3lykbgu.js → tags-DZukMyuU.js} +1 -1
- package/core/built/admin/assets/{textarea-Cc3nUXep.js → textarea-BtnzsOk7.js} +1 -1
- package/core/built/admin/assets/{thumbs-down-SsjC2lMD.js → thumbs-down-CZTzyz7D.js} +1 -1
- package/core/built/admin/assets/{tiers-J8AeZmRd.js → tiers-Do7zBqAk.js} +1 -1
- package/core/built/admin/assets/{toggle-group-BzD8yimX.js → toggle-group-abk9FYXi.js} +1 -1
- package/core/built/admin/assets/{topic-filter-CA_L6ehz.js → topic-filter-CdMvjkmc.js} +1 -1
- package/core/built/admin/assets/{trash-BKhRqxsX.js → trash-DNXRsBf0.js} +1 -1
- package/core/built/admin/assets/{underline-_HIgX6e1.js → underline-HXWuVCAi.js} +1 -1
- package/core/built/admin/assets/{undo-2-ClkkOS0O.js → undo-2-C2ntNJKC.js} +1 -1
- package/core/built/admin/assets/{upload-DEPHbyvo.js → upload-D52l7HIb.js} +1 -1
- package/core/built/admin/assets/{use-growth-stats-BM2qWt0C.js → use-growth-stats-Dgs0UxDT.js} +1 -1
- package/core/built/admin/assets/{use-simple-pagination-zyklfekn.js → use-simple-pagination-Cj2rVggA.js} +1 -1
- package/core/built/admin/assets/{user-round-check-DoaGU2hC.js → user-round-check-C0GdT99c.js} +1 -1
- package/core/built/admin/assets/{user-round-x-CwEKNuU6.js → user-round-x-CVCvxuUG.js} +1 -1
- package/core/built/admin/assets/{virtual-list-window-C0Cv0gUC.js → virtual-list-window-mdQS2bt_.js} +1 -1
- package/core/built/admin/assets/{wallet-cards-BjdG5glh.js → wallet-cards-CtLF01jQ.js} +1 -1
- package/core/built/admin/assets/{web-BZNnanCT.js → web-DTib8_n8.js} +1 -1
- package/core/built/admin/index.html +6 -6
- package/core/frontend/helpers/ghost_foot.js +12 -2
- package/core/frontend/helpers/prev_post.js +1 -1
- package/core/frontend/helpers/tpl/gift-toast.hbs +130 -0
- package/core/frontend/services/proxy.js +9 -0
- package/core/frontend/services/routing/controllers/entry/canonical-url.js +15 -0
- package/core/frontend/services/routing/controllers/entry/canonical-url.ts +14 -0
- package/core/frontend/services/routing/controllers/entry/gift-links.js +82 -0
- package/core/frontend/services/routing/controllers/entry/gift-links.ts +92 -0
- package/core/frontend/services/routing/controllers/entry/markdown.js +62 -0
- package/core/frontend/services/routing/controllers/entry/markdown.ts +66 -0
- package/core/frontend/services/routing/controllers/entry.js +96 -105
- package/core/frontend/services/routing/controllers/entry.ts +97 -0
- package/core/frontend/services/routing/controllers/index.js +1 -1
- package/core/frontend/web/middleware/frontend-caching.js +9 -0
- package/core/server/adapters/cache/Redis.js +0 -1
- package/core/server/adapters/redirects/RedirectsStoreBase.d.ts +0 -4
- package/core/server/adapters/scheduling/scheduling-default.js +8 -1
- package/core/server/api/endpoints/gift-links.js +23 -16
- package/core/server/api/endpoints/gift-links.ts +25 -17
- package/core/server/api/endpoints/index.js +0 -1
- package/core/server/api/endpoints/previews.js +3 -24
- package/core/server/api/endpoints/utils/serializers/output/gift-links.js +4 -4
- package/core/server/api/endpoints/utils/serializers/output/gift-links.ts +4 -4
- package/core/server/api/endpoints/utils/serializers/output/index.js +0 -1
- package/core/server/api/endpoints/utils/validators/input/automation_email_previews.js +8 -9
- package/core/server/api/endpoints/utils/validators/input/index.js +0 -1
- package/core/server/data/migrations/versions/6.48/2026-06-23-00-00-00-drop-gift-links-revoked-at.js +6 -0
- package/core/server/data/migrations/versions/6.48/2026-06-23-00-00-01-rename-gift-links-revoke-all-permission-to-remove-all.js +37 -0
- package/core/server/data/migrations/versions/6.48/2026-06-24-00-00-00-drop-gift-links-redemption-columns.js +10 -0
- package/core/server/data/schema/fixtures/fixtures.json +2 -2
- package/core/server/data/schema/schema.js +1 -4
- package/core/server/data/seeders/data-generator.js +4 -1
- package/core/server/data/seeders/importers/members-login-events-importer.js +0 -1
- package/core/server/data/seeders/importers/members-newsletters-importer.js +0 -1
- package/core/server/data/seeders/importers/members-paid-subscription-events-importer.js +0 -1
- package/core/server/data/seeders/importers/members-status-events-importer.js +0 -1
- package/core/server/data/seeders/importers/members-stripe-customers-importer.js +0 -1
- package/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js +0 -1
- package/core/server/data/seeders/importers/members-subscribe-events-importer.js +0 -1
- package/core/server/data/seeders/importers/members-subscription-created-events-importer.js +0 -1
- package/core/server/lib/lexical.js +62 -36
- package/core/server/lib/post-revisions.js +0 -2
- package/core/server/lib/post-revisions.ts +0 -3
- package/core/server/models/index.js +0 -3
- package/core/server/services/auth/reset-authentication.js +0 -2
- package/core/server/services/auth/reset-authentication.ts +0 -3
- package/core/server/services/auth/session/index.js +0 -1
- package/core/server/services/automations/automations-api.js +59 -17
- package/core/server/services/automations/automations-api.ts +69 -16
- package/core/server/services/automations/database-automations-repository.js +58 -3
- package/core/server/services/automations/database-automations-repository.ts +70 -3
- package/core/server/services/automations/stale-lock-cutoff.js +7 -0
- package/core/server/services/automations/stale-lock-cutoff.ts +5 -0
- package/core/server/services/email-address/email-address-parser.js.d.ts +0 -1
- package/core/server/services/email-service/batch-sending-service.js +99 -26
- package/core/server/services/email-service/email-service-wrapper.js +7 -2
- package/core/server/services/email-service/email-service.js +146 -4
- package/core/server/services/gift-links/database.js +0 -3
- package/core/server/services/gift-links/database.ts +1 -4
- package/core/server/services/gift-links/index.js +2 -2
- package/core/server/services/gift-links/index.ts +4 -2
- package/core/server/services/gift-links/models.js +0 -2
- package/core/server/services/gift-links/models.ts +0 -2
- package/core/server/services/gift-links/queries.js +2 -2
- package/core/server/services/gift-links/queries.ts +2 -2
- package/core/server/services/gift-links/serializers.js +0 -2
- package/core/server/services/gift-links/serializers.ts +0 -2
- package/core/server/services/gift-links/service.js +54 -35
- package/core/server/services/gift-links/service.ts +70 -35
- package/core/server/services/gifts/gift-reminder-scheduler.js +0 -2
- package/core/server/services/gifts/gift-reminder-scheduler.ts +0 -2
- package/core/server/services/indexnow.js +8 -1
- package/core/server/services/internal-keys/index.js +0 -1
- package/core/server/services/internal-keys/index.ts +0 -2
- package/core/server/services/lib/dynamic-redirect-manager.d.ts +0 -1
- package/core/server/services/lib/in-memory-repository.js +0 -1
- package/core/server/services/lib/in-memory-repository.ts +0 -2
- package/core/server/services/members/api.js +0 -3
- package/core/server/services/members/create-paid-member-shim.js +31 -0
- package/core/server/services/members/create-paid-member-shim.ts +31 -0
- package/core/server/services/members/emails/signin.js +0 -1
- package/core/server/services/members/members-api/members-api.js +0 -2
- package/core/server/services/members/members-api/repositories/member-repository.js +0 -3
- package/core/server/services/members/service.js +4 -0
- package/core/server/services/post-scheduling/index.js +0 -2
- package/core/server/services/post-scheduling/index.ts +0 -2
- package/core/server/services/post-scheduling/post-scheduling.js +0 -5
- package/core/server/services/post-scheduling/post-scheduling.ts +0 -5
- package/core/server/services/recommendations/service/bookshelf-repository.js +0 -1
- package/core/server/services/recommendations/service/bookshelf-repository.ts +0 -4
- package/core/server/services/recommendations/service/incoming-recommendation-service.js +0 -1
- package/core/server/services/recommendations/service/incoming-recommendation-service.ts +0 -1
- package/core/server/services/recommendations/service/recommendation-controller.js +0 -1
- package/core/server/services/recommendations/service/recommendation-controller.ts +0 -1
- package/core/server/services/recommendations/service/recommendation-metadata-service.js +0 -1
- package/core/server/services/recommendations/service/recommendation-metadata-service.ts +0 -1
- package/core/server/services/recommendations/service/recommendation.js +0 -1
- package/core/server/services/recommendations/service/recommendation.ts +0 -1
- package/core/server/services/remote-flags/index.js +0 -1
- package/core/server/services/remote-flags/index.ts +0 -1
- package/core/server/services/slack.js +5 -1
- package/core/server/services/update-check/index.js +0 -1
- package/core/server/services/url/lazy-find-resource.js +0 -1
- package/core/server/services/url/lazy-find-resource.ts +0 -2
- package/core/server/services/url/lazy-url-service.js +0 -1
- package/core/server/services/url/lazy-url-service.ts +0 -2
- package/core/server/services/url/permalink-matcher.js +0 -1
- package/core/server/services/url/permalink-matcher.ts +0 -2
- package/core/server/services/url/router-filter.js +0 -2
- package/core/server/services/url/router-filter.ts +0 -2
- package/core/server/services/url/url-service-facade.js +0 -1
- package/core/server/services/url/url-service-facade.ts +0 -2
- package/core/server/services/verification/verification-webhook-service.js +0 -1
- package/core/server/services/verification/verification-webhook-service.ts +0 -1
- package/core/server/web/api/endpoints/admin/routes.js +7 -7
- package/core/shared/events-ts/post-deleted-event.js +0 -2
- package/core/shared/events-ts/post-deleted-event.ts +0 -2
- package/core/shared/labs.js +0 -1
- package/package.json +8 -16
- package/pnpm-lock.yaml +162 -113
- package/core/built/admin/assets/automations-BthXBzzq.js +0 -1
- package/core/built/admin/assets/editor-91xrI2A3.js +0 -8
- package/core/built/admin/assets/index-BYb09f-7.css +0 -1
- package/core/built/admin/assets/minus-DmrVsJ-z.js +0 -1
- package/core/built/admin/assets/modals-dnqxCS3l.js +0 -35
- package/core/server/models/outbox.js +0 -24
- package/core/server/services/outbox/events/start-outbox-processing-event.js +0 -22
- package/core/server/services/outbox/handlers/member-created.js +0 -85
- package/core/server/services/outbox/index.js +0 -49
- package/core/server/services/outbox/jobs/index.js +0 -30
- package/core/server/services/outbox/jobs/lib/constants.js +0 -17
- package/core/server/services/outbox/jobs/lib/process-entries.js +0 -117
- package/core/server/services/outbox/jobs/lib/process-outbox.js +0 -96
- package/core/server/services/outbox/jobs/outbox-job.js +0 -36
- package/types/ghost-storage-base.d.ts +0 -22
|
@@ -40,16 +40,27 @@ exports.GiftLinksService = void 0;
|
|
|
40
40
|
exports.generateGiftLinkToken = generateGiftLinkToken;
|
|
41
41
|
const crypto_1 = __importDefault(require("crypto"));
|
|
42
42
|
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
43
|
+
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
43
44
|
const zod_1 = require("zod");
|
|
44
45
|
const models_1 = require("./models");
|
|
45
46
|
const queries = __importStar(require("./queries"));
|
|
46
47
|
function generateGiftLinkToken() {
|
|
47
48
|
return models_1.GiftLinkToken.parse(crypto_1.default.randomBytes(24).toString('base64url'));
|
|
48
49
|
}
|
|
50
|
+
// The history UI only surfaces a verb-specific label (action_name) for 'edited' events; 'added' and
|
|
51
|
+
// 'deleted' render as the bare event. So 'reset' maps to 'edited' to read as "reset", while
|
|
52
|
+
// 'add'/'remove' read as plain "added"/"deleted".
|
|
53
|
+
const COMMANDS = {
|
|
54
|
+
add: 'added',
|
|
55
|
+
reset: 'edited',
|
|
56
|
+
remove: 'deleted'
|
|
57
|
+
};
|
|
49
58
|
class GiftLinksService {
|
|
50
59
|
knex;
|
|
51
|
-
|
|
60
|
+
Action;
|
|
61
|
+
constructor({ knex, Action }) {
|
|
52
62
|
this.knex = knex;
|
|
63
|
+
this.Action = Action;
|
|
53
64
|
}
|
|
54
65
|
async getPost(postId) {
|
|
55
66
|
return this.requirePost(postId);
|
|
@@ -58,37 +69,32 @@ class GiftLinksService {
|
|
|
58
69
|
const row = await queries.liveLinkForToken(token)(this.knex);
|
|
59
70
|
return row ? { id: row.post_id, giftLinks: [zod_1.z.decode(queries.giftLinkCodec, row)] } : null;
|
|
60
71
|
}
|
|
61
|
-
async
|
|
62
|
-
|
|
63
|
-
return post.giftLinks.length ? post : this.mint(postId);
|
|
72
|
+
async isValidTokenForPost(token, postId) {
|
|
73
|
+
return (await this.getPostByToken(token))?.id === postId;
|
|
64
74
|
}
|
|
65
|
-
async
|
|
75
|
+
async ensure(context, postId) {
|
|
66
76
|
const post = await this.requirePost(postId);
|
|
67
|
-
|
|
77
|
+
if (post.giftLinks.length) {
|
|
78
|
+
return post;
|
|
79
|
+
}
|
|
80
|
+
const minted = await this.mint(postId);
|
|
81
|
+
await this.recordAction(context, 'add', postId);
|
|
82
|
+
return minted;
|
|
68
83
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
await this.knex.transaction(async (trx) => {
|
|
75
|
-
await trx('gift_links')
|
|
76
|
-
.whereIn('token', trx('post_gift_links').select('gift_link_token'))
|
|
77
|
-
.update({ revoked_at: now, updated_at: now });
|
|
78
|
-
revoked = await trx('post_gift_links').del();
|
|
79
|
-
});
|
|
80
|
-
return revoked;
|
|
84
|
+
async create(context, postId) {
|
|
85
|
+
await this.requirePost(postId);
|
|
86
|
+
const minted = await this.mint(postId);
|
|
87
|
+
await this.recordAction(context, 'reset', postId);
|
|
88
|
+
return minted;
|
|
81
89
|
}
|
|
82
|
-
//
|
|
83
|
-
async
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
.
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
// Remove every live association; the gift_links rows stay as history.
|
|
91
|
+
async removeAll(context) {
|
|
92
|
+
const removed = await this.knex('post_gift_links').del();
|
|
93
|
+
if (removed > 0) {
|
|
94
|
+
await this.recordAction(context, 'remove', null);
|
|
95
|
+
}
|
|
96
|
+
return removed;
|
|
89
97
|
}
|
|
90
|
-
// A missing post is a 404, not a post with no live links: no rows means no post, and the
|
|
91
|
-
// remaining rows carrying a token are the live links.
|
|
92
98
|
async requirePost(postId) {
|
|
93
99
|
const rows = await queries.liveLinksForPost(postId)(this.knex);
|
|
94
100
|
if (rows.length === 0) {
|
|
@@ -99,16 +105,10 @@ class GiftLinksService {
|
|
|
99
105
|
.map(row => zod_1.z.decode(queries.giftLinkCodec, row));
|
|
100
106
|
return { id: postId, giftLinks };
|
|
101
107
|
}
|
|
102
|
-
|
|
103
|
-
// it. On reissue the replaced link is stamped revoked_at as history. Concurrent issues are
|
|
104
|
-
// last-writer-wins, not an error.
|
|
105
|
-
async mint(postId, replacing) {
|
|
108
|
+
async mint(postId) {
|
|
106
109
|
const now = new Date();
|
|
107
|
-
const link = { token: generateGiftLinkToken(),
|
|
110
|
+
const link = { token: generateGiftLinkToken(), createdAt: now };
|
|
108
111
|
await this.knex.transaction(async (trx) => {
|
|
109
|
-
if (replacing) {
|
|
110
|
-
await trx('gift_links').where({ token: replacing }).update({ revoked_at: now, updated_at: now });
|
|
111
|
-
}
|
|
112
112
|
await trx('gift_links').insert({ ...zod_1.z.encode(queries.giftLinkCodec, link), post_id: postId });
|
|
113
113
|
await trx('post_gift_links')
|
|
114
114
|
.insert({ post_id: postId, gift_link_token: link.token, created_at: now })
|
|
@@ -117,5 +117,24 @@ class GiftLinksService {
|
|
|
117
117
|
});
|
|
118
118
|
return { id: postId, giftLinks: [link] };
|
|
119
119
|
}
|
|
120
|
+
async recordAction(context, verb, subject) {
|
|
121
|
+
if (!context.actor) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const event = COMMANDS[verb];
|
|
125
|
+
try {
|
|
126
|
+
await this.Action.add({
|
|
127
|
+
event,
|
|
128
|
+
resource_type: 'gift_link',
|
|
129
|
+
resource_id: subject,
|
|
130
|
+
actor_type: context.actor.type,
|
|
131
|
+
actor_id: context.actor.id,
|
|
132
|
+
...(event === 'edited' ? { context: { action_name: verb } } : {})
|
|
133
|
+
}, { autoRefresh: false });
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
logging_1.default.error(err);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
120
139
|
}
|
|
121
140
|
exports.GiftLinksService = GiftLinksService;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import crypto from 'crypto';
|
|
2
2
|
import errors from '@tryghost/errors';
|
|
3
|
+
import logging from '@tryghost/logging';
|
|
3
4
|
import {z} from 'zod';
|
|
4
5
|
import type {Knex} from 'knex';
|
|
5
6
|
import {GiftLinkToken, type GiftLink, type Post} from './models';
|
|
@@ -9,11 +10,37 @@ export function generateGiftLinkToken(): GiftLinkToken {
|
|
|
9
10
|
return GiftLinkToken.parse(crypto.randomBytes(24).toString('base64url'));
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
export interface Actor {
|
|
14
|
+
id: string;
|
|
15
|
+
type: 'user' | 'integration';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface ActionRecorder {
|
|
19
|
+
add(data: Record<string, unknown>, options: {autoRefresh: boolean}): Promise<unknown>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface RequestContext {
|
|
23
|
+
actor: Actor | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// The history UI only surfaces a verb-specific label (action_name) for 'edited' events; 'added' and
|
|
27
|
+
// 'deleted' render as the bare event. So 'reset' maps to 'edited' to read as "reset", while
|
|
28
|
+
// 'add'/'remove' read as plain "added"/"deleted".
|
|
29
|
+
const COMMANDS = {
|
|
30
|
+
add: 'added',
|
|
31
|
+
reset: 'edited',
|
|
32
|
+
remove: 'deleted'
|
|
33
|
+
} as const satisfies Record<string, 'added' | 'edited' | 'deleted'>;
|
|
34
|
+
|
|
35
|
+
type GiftLinkVerb = keyof typeof COMMANDS;
|
|
36
|
+
|
|
12
37
|
export class GiftLinksService {
|
|
13
38
|
private knex: Knex;
|
|
39
|
+
private Action: ActionRecorder;
|
|
14
40
|
|
|
15
|
-
constructor({knex}: {knex: Knex}) {
|
|
41
|
+
constructor({knex, Action}: {knex: Knex; Action: ActionRecorder}) {
|
|
16
42
|
this.knex = knex;
|
|
43
|
+
this.Action = Action;
|
|
17
44
|
}
|
|
18
45
|
|
|
19
46
|
async getPost(postId: string): Promise<Post> {
|
|
@@ -25,41 +52,36 @@ export class GiftLinksService {
|
|
|
25
52
|
return row ? {id: row.post_id, giftLinks: [z.decode(queries.giftLinkCodec, row)]} : null;
|
|
26
53
|
}
|
|
27
54
|
|
|
28
|
-
async
|
|
29
|
-
|
|
30
|
-
return post.giftLinks.length ? post : this.mint(postId);
|
|
55
|
+
async isValidTokenForPost(token: string, postId: string): Promise<boolean> {
|
|
56
|
+
return (await this.getPostByToken(token))?.id === postId;
|
|
31
57
|
}
|
|
32
58
|
|
|
33
|
-
async
|
|
59
|
+
async ensure(context: RequestContext, postId: string): Promise<Post> {
|
|
34
60
|
const post = await this.requirePost(postId);
|
|
35
|
-
|
|
61
|
+
if (post.giftLinks.length) {
|
|
62
|
+
return post;
|
|
63
|
+
}
|
|
64
|
+
const minted = await this.mint(postId);
|
|
65
|
+
await this.recordAction(context, 'add', postId);
|
|
66
|
+
return minted;
|
|
36
67
|
}
|
|
37
68
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
await this.knex.transaction(async (trx) => {
|
|
44
|
-
await trx('gift_links')
|
|
45
|
-
.whereIn('token', trx('post_gift_links').select('gift_link_token'))
|
|
46
|
-
.update({revoked_at: now, updated_at: now});
|
|
47
|
-
revoked = await trx('post_gift_links').del();
|
|
48
|
-
});
|
|
49
|
-
return revoked;
|
|
69
|
+
async create(context: RequestContext, postId: string): Promise<Post> {
|
|
70
|
+
await this.requirePost(postId);
|
|
71
|
+
const minted = await this.mint(postId);
|
|
72
|
+
await this.recordAction(context, 'reset', postId);
|
|
73
|
+
return minted;
|
|
50
74
|
}
|
|
51
75
|
|
|
52
|
-
//
|
|
53
|
-
async
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
.
|
|
57
|
-
|
|
58
|
-
|
|
76
|
+
// Remove every live association; the gift_links rows stay as history.
|
|
77
|
+
async removeAll(context: RequestContext): Promise<number> {
|
|
78
|
+
const removed = await this.knex('post_gift_links').del();
|
|
79
|
+
if (removed > 0) {
|
|
80
|
+
await this.recordAction(context, 'remove', null);
|
|
81
|
+
}
|
|
82
|
+
return removed;
|
|
59
83
|
}
|
|
60
84
|
|
|
61
|
-
// A missing post is a 404, not a post with no live links: no rows means no post, and the
|
|
62
|
-
// remaining rows carrying a token are the live links.
|
|
63
85
|
private async requirePost(postId: string): Promise<Post> {
|
|
64
86
|
const rows = await queries.liveLinksForPost(postId)(this.knex);
|
|
65
87
|
if (rows.length === 0) {
|
|
@@ -71,16 +93,10 @@ export class GiftLinksService {
|
|
|
71
93
|
return {id: postId, giftLinks};
|
|
72
94
|
}
|
|
73
95
|
|
|
74
|
-
|
|
75
|
-
// it. On reissue the replaced link is stamped revoked_at as history. Concurrent issues are
|
|
76
|
-
// last-writer-wins, not an error.
|
|
77
|
-
private async mint(postId: string, replacing?: GiftLinkToken): Promise<Post> {
|
|
96
|
+
private async mint(postId: string): Promise<Post> {
|
|
78
97
|
const now = new Date();
|
|
79
|
-
const link: GiftLink = {token: generateGiftLinkToken(),
|
|
98
|
+
const link: GiftLink = {token: generateGiftLinkToken(), createdAt: now};
|
|
80
99
|
await this.knex.transaction(async (trx) => {
|
|
81
|
-
if (replacing) {
|
|
82
|
-
await trx('gift_links').where({token: replacing}).update({revoked_at: now, updated_at: now});
|
|
83
|
-
}
|
|
84
100
|
await trx('gift_links').insert({...z.encode(queries.giftLinkCodec, link), post_id: postId});
|
|
85
101
|
await trx('post_gift_links')
|
|
86
102
|
.insert({post_id: postId, gift_link_token: link.token, created_at: now})
|
|
@@ -89,4 +105,23 @@ export class GiftLinksService {
|
|
|
89
105
|
});
|
|
90
106
|
return {id: postId, giftLinks: [link]};
|
|
91
107
|
}
|
|
108
|
+
|
|
109
|
+
private async recordAction(context: RequestContext, verb: GiftLinkVerb, subject: string | null): Promise<void> {
|
|
110
|
+
if (!context.actor) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const event = COMMANDS[verb];
|
|
114
|
+
try {
|
|
115
|
+
await this.Action.add({
|
|
116
|
+
event,
|
|
117
|
+
resource_type: 'gift_link',
|
|
118
|
+
resource_id: subject,
|
|
119
|
+
actor_type: context.actor.type,
|
|
120
|
+
actor_id: context.actor.id,
|
|
121
|
+
...(event === 'edited' ? {context: {action_name: verb}} : {})
|
|
122
|
+
}, {autoRefresh: false});
|
|
123
|
+
} catch (err) {
|
|
124
|
+
logging.error(err);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
92
127
|
}
|
|
@@ -7,9 +7,7 @@ exports.GiftReminderScheduler = void 0;
|
|
|
7
7
|
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
8
8
|
const constants_1 = require("./constants");
|
|
9
9
|
// Same-domain (scheduling) primitives, used unconditionally.
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
11
10
|
const urlUtils = require('../../../shared/url-utils');
|
|
12
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
13
11
|
const { getSignedAdminToken } = require('../../adapters/scheduling/utils');
|
|
14
12
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
15
13
|
const GIFT_REMINDER_LEAD_MS = constants_1.GIFT_REMINDER_LEAD_DAYS * MS_PER_DAY;
|
|
@@ -4,9 +4,7 @@ import type {InternalApiKey, InternalKeys} from '../internal-keys';
|
|
|
4
4
|
import type {SchedulerAdapter, SchedulerJob} from '../../adapters/scheduling/types';
|
|
5
5
|
import {GIFT_REMINDER_LEAD_DAYS} from './constants';
|
|
6
6
|
// Same-domain (scheduling) primitives, used unconditionally.
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
8
7
|
const urlUtils = require('../../../shared/url-utils');
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
10
8
|
const {getSignedAdminToken} = require('../../adapters/scheduling/utils');
|
|
11
9
|
|
|
12
10
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
@@ -222,7 +222,14 @@ function indexnowListener(model, options) {
|
|
|
222
222
|
return;
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
-
ping(
|
|
225
|
+
ping({
|
|
226
|
+
...model.toJSON(),
|
|
227
|
+
// tags and authors are needed so the lazy URL service can evaluate
|
|
228
|
+
// collection filters (e.g. `tag:foo`) when resolving the post URL;
|
|
229
|
+
// without them a tag/author-filtered post resolves to /404/
|
|
230
|
+
authors: model.related('authors').toJSON(),
|
|
231
|
+
tags: model.related('tags').toJSON()
|
|
232
|
+
}).catch(() => {
|
|
226
233
|
// Errors are already logged inside ping()
|
|
227
234
|
// This catch is just to prevent unhandled rejection warnings
|
|
228
235
|
});
|
|
@@ -12,7 +12,6 @@ const SLUG_KEY_TYPE = {
|
|
|
12
12
|
// method without polluting the file with `any`. The generic constrains
|
|
13
13
|
// known internal slugs to their seeded type; arbitrary slugs accept any
|
|
14
14
|
// type.
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
16
15
|
const models = require('../../models');
|
|
17
16
|
/**
|
|
18
17
|
* Process-lifetime cache of internal-integration API keys, keyed by slug.
|
|
@@ -35,10 +35,8 @@ export type InternalKeys = AutoFillingMap<InternalIntegrationSlug, Promise<Inter
|
|
|
35
35
|
// method without polluting the file with `any`. The generic constrains
|
|
36
36
|
// known internal slugs to their seeded type; arbitrary slugs accept any
|
|
37
37
|
// type.
|
|
38
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
39
38
|
const models = require('../../models') as {
|
|
40
39
|
Integration: {
|
|
41
|
-
// eslint-disable-next-line no-unused-vars
|
|
42
40
|
getApiKeyBySlug<S extends string>(slug: S, type: S extends InternalIntegrationSlug ? typeof SLUG_KEY_TYPE[S] : ApiKeyType): Promise<InternalApiKey>;
|
|
43
41
|
};
|
|
44
42
|
};
|
|
@@ -37,7 +37,6 @@ class InMemoryRepository {
|
|
|
37
37
|
for (const order of options.order) {
|
|
38
38
|
results.sort((a, b) => {
|
|
39
39
|
if (order.direction === 'asc') {
|
|
40
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
41
40
|
return a[order.field] > b[order.field] ? 1 : -1;
|
|
42
41
|
}
|
|
43
42
|
else {
|
|
@@ -10,7 +10,6 @@ type Order<T> = {
|
|
|
10
10
|
direction: 'asc' | 'desc';
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
13
|
type OrderOption<T extends Entity<any>> = Order<T>[];
|
|
15
14
|
|
|
16
15
|
export abstract class InMemoryRepository<IDType, T extends Entity<IDType>> {
|
|
@@ -52,7 +51,6 @@ export abstract class InMemoryRepository<IDType, T extends Entity<IDType>> {
|
|
|
52
51
|
for (const order of options.order) {
|
|
53
52
|
results.sort((a, b) => {
|
|
54
53
|
if (order.direction === 'asc') {
|
|
55
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
56
54
|
return a[order.field] as any > (b[order.field] as any) ? 1 : -1;
|
|
57
55
|
} else {
|
|
58
56
|
return a[order.field] < b[order.field] ? 1 : -1;
|
|
@@ -170,7 +170,6 @@ function createApiInstance(config) {
|
|
|
170
170
|
`;
|
|
171
171
|
case 'signin':
|
|
172
172
|
default:
|
|
173
|
-
/* eslint-disable indent */
|
|
174
173
|
return trimLeadingWhitespace`
|
|
175
174
|
${t(`Hey there,`)}
|
|
176
175
|
|
|
@@ -190,7 +189,6 @@ function createApiInstance(config) {
|
|
|
190
189
|
${t('Sent to {email}', {email})}
|
|
191
190
|
${t('If you did not make this request, you can safely ignore this email.')}
|
|
192
191
|
`;
|
|
193
|
-
/* eslint-enable indent */
|
|
194
192
|
}
|
|
195
193
|
},
|
|
196
194
|
getHTML(url, type, email, otc) {
|
|
@@ -241,7 +239,6 @@ function createApiInstance(config) {
|
|
|
241
239
|
Comment: models.Comment,
|
|
242
240
|
MemberFeedback: models.MemberFeedback,
|
|
243
241
|
EmailSpamComplaintEvent: models.EmailSpamComplaintEvent,
|
|
244
|
-
Outbox: models.Outbox,
|
|
245
242
|
Automation: models.Automation,
|
|
246
243
|
WelcomeEmailAutomationRun: models.WelcomeEmailAutomationRun,
|
|
247
244
|
AutomatedEmailRecipient: models.AutomatedEmailRecipient,
|
|
@@ -0,0 +1,31 @@
|
|
|
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.createPaidMemberShim = createPaidMemberShim;
|
|
7
|
+
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
8
|
+
const models = require('../../models');
|
|
9
|
+
/**
|
|
10
|
+
* Build a stand-in "all active paid tiers" member for content gating — NOT a real
|
|
11
|
+
* member. It carries only the `status` and `products` that
|
|
12
|
+
* `contentGating.checkPostAccess` / `checkGatedBlockAccess` read, letting previews
|
|
13
|
+
* (`member_status=paid`) and gift-link reads reveal gated content without a
|
|
14
|
+
* logged-in member. Single source of truth for this security-sensitive grant.
|
|
15
|
+
*/
|
|
16
|
+
async function createPaidMemberShim() {
|
|
17
|
+
let products = [];
|
|
18
|
+
try {
|
|
19
|
+
const paidProducts = await models.Product.findAll({ status: 'active', type: 'paid' });
|
|
20
|
+
products = paidProducts.map((product) => ({ slug: product.get('slug') }));
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
// Fall back to no tiers rather than failing the render — still grants
|
|
24
|
+
// status:paid/members content, just not tier-specific blocks.
|
|
25
|
+
logging_1.default.error('Failed to build paid member shim tiers:', error);
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
status: 'paid',
|
|
29
|
+
products
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import logging from '@tryghost/logging';
|
|
2
|
+
const models = require('../../models');
|
|
3
|
+
|
|
4
|
+
interface PaidMemberShim {
|
|
5
|
+
status: 'paid';
|
|
6
|
+
products: Array<{slug: string}>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Build a stand-in "all active paid tiers" member for content gating — NOT a real
|
|
11
|
+
* member. It carries only the `status` and `products` that
|
|
12
|
+
* `contentGating.checkPostAccess` / `checkGatedBlockAccess` read, letting previews
|
|
13
|
+
* (`member_status=paid`) and gift-link reads reveal gated content without a
|
|
14
|
+
* logged-in member. Single source of truth for this security-sensitive grant.
|
|
15
|
+
*/
|
|
16
|
+
export async function createPaidMemberShim(): Promise<PaidMemberShim> {
|
|
17
|
+
let products: Array<{slug: string}> = [];
|
|
18
|
+
try {
|
|
19
|
+
const paidProducts = await models.Product.findAll({status: 'active', type: 'paid'});
|
|
20
|
+
products = paidProducts.map((product: {get(key: string): string}) => ({slug: product.get('slug')}));
|
|
21
|
+
} catch (error) {
|
|
22
|
+
// Fall back to no tiers rather than failing the render — still grants
|
|
23
|
+
// status:paid/members content, just not tier-specific blocks.
|
|
24
|
+
logging.error('Failed to build paid member shim tiers:', error);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
status: 'paid',
|
|
29
|
+
products
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -65,7 +65,6 @@ module.exports = function MembersAPI({
|
|
|
65
65
|
Settings,
|
|
66
66
|
Comment,
|
|
67
67
|
MemberFeedback,
|
|
68
|
-
Outbox,
|
|
69
68
|
Automation,
|
|
70
69
|
WelcomeEmailAutomationRun,
|
|
71
70
|
AutomatedEmailRecipient,
|
|
@@ -119,7 +118,6 @@ module.exports = function MembersAPI({
|
|
|
119
118
|
OfferRedemption,
|
|
120
119
|
StripeCustomer,
|
|
121
120
|
StripeCustomerSubscription,
|
|
122
|
-
Outbox,
|
|
123
121
|
offersAPI
|
|
124
122
|
});
|
|
125
123
|
|
|
@@ -64,7 +64,6 @@ module.exports = class MemberRepository {
|
|
|
64
64
|
* @param {any} deps.StripeCustomer
|
|
65
65
|
* @param {any} deps.StripeCustomerSubscription
|
|
66
66
|
* @param {any} deps.OfferRedemption
|
|
67
|
-
* @param {any} deps.Outbox
|
|
68
67
|
* @param {import('../../../stripe/stripe-api')} deps.stripeAPIService
|
|
69
68
|
* @param {any} deps.productRepository
|
|
70
69
|
* @param {any} deps.offersAPI
|
|
@@ -86,7 +85,6 @@ module.exports = class MemberRepository {
|
|
|
86
85
|
StripeCustomer,
|
|
87
86
|
StripeCustomerSubscription,
|
|
88
87
|
OfferRedemption,
|
|
89
|
-
Outbox,
|
|
90
88
|
stripeAPIService,
|
|
91
89
|
productRepository,
|
|
92
90
|
offersAPI,
|
|
@@ -105,7 +103,6 @@ module.exports = class MemberRepository {
|
|
|
105
103
|
this._MemberStatusEvent = MemberStatusEvent;
|
|
106
104
|
this._MemberProductEvent = MemberProductEvent;
|
|
107
105
|
this._OfferRedemption = OfferRedemption;
|
|
108
|
-
this._Outbox = Outbox;
|
|
109
106
|
this._StripeCustomer = StripeCustomer;
|
|
110
107
|
this._StripeCustomerSubscription = StripeCustomerSubscription;
|
|
111
108
|
this._stripeAPIService = stripeAPIService;
|
|
@@ -171,6 +171,10 @@ module.exports = {
|
|
|
171
171
|
},
|
|
172
172
|
contentGating: require('./content-gating'),
|
|
173
173
|
|
|
174
|
+
// Create an "all active paid tiers" member shim for rendering gated content
|
|
175
|
+
// without a logged-in member (post previews, gift-links reader path).
|
|
176
|
+
createPaidMemberShim: require('./create-paid-member-shim').createPaidMemberShim,
|
|
177
|
+
|
|
174
178
|
config: membersConfig,
|
|
175
179
|
|
|
176
180
|
get api() {
|
|
@@ -6,9 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const post_scheduling_1 = __importDefault(require("./post-scheduling"));
|
|
7
7
|
const internal_keys_1 = __importDefault(require("../internal-keys"));
|
|
8
8
|
// CJS modules without TS declarations — typed loosely at the boundary.
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
10
9
|
const adapterManager = require('../adapter-manager');
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
12
10
|
const urlUtils = require('../../../shared/url-utils');
|
|
13
11
|
exports.default = new post_scheduling_1.default({
|
|
14
12
|
apiUrl: urlUtils.urlFor('api', { type: 'admin' }, true),
|
|
@@ -2,9 +2,7 @@ import PostScheduling from './post-scheduling';
|
|
|
2
2
|
import internalKeys from '../internal-keys';
|
|
3
3
|
|
|
4
4
|
// CJS modules without TS declarations — typed loosely at the boundary.
|
|
5
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
6
5
|
const adapterManager = require('../adapter-manager');
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
8
6
|
const urlUtils = require('../../../shared/url-utils');
|
|
9
7
|
|
|
10
8
|
export default new PostScheduling({
|
|
@@ -3,18 +3,13 @@ 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
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
7
6
|
const moment_1 = __importDefault(require("moment"));
|
|
8
7
|
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
9
8
|
// CJS-only modules — typed loosely below. models is the Bookshelf registry
|
|
10
9
|
// without TS declarations; the rest are JS modules without types.
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
12
10
|
const models = require('../../models');
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
14
11
|
const urlUtils = require('../../../shared/url-utils');
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
16
12
|
const { getSignedAdminToken } = require('../../adapters/scheduling/utils');
|
|
17
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
18
13
|
const events = require('../../lib/common/events');
|
|
19
14
|
// Pages live in the posts table with type:'page', so both types are
|
|
20
15
|
// queried through models.Post and discriminated via the type filter.
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
1
|
import moment from 'moment';
|
|
3
2
|
import logging from '@tryghost/logging';
|
|
4
3
|
import type {InternalApiKey, InternalKeys} from '../internal-keys';
|
|
@@ -6,13 +5,9 @@ import type {SchedulerAdapter, SchedulerJob} from '../../adapters/scheduling/typ
|
|
|
6
5
|
|
|
7
6
|
// CJS-only modules — typed loosely below. models is the Bookshelf registry
|
|
8
7
|
// without TS declarations; the rest are JS modules without types.
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
10
8
|
const models = require('../../models');
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
12
9
|
const urlUtils = require('../../../shared/url-utils');
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
14
10
|
const {getSignedAdminToken} = require('../../adapters/scheduling/utils');
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
16
11
|
const events = require('../../lib/common/events');
|
|
17
12
|
|
|
18
13
|
interface PostSchedulingDeps {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable ghost/filenames/match-exported-class */
|
|
2
1
|
|
|
3
2
|
import {Knex} from 'knex';
|
|
4
3
|
import {mapKeys, chainTransformers} from '@tryghost/mongo-utils';
|
|
@@ -38,11 +37,8 @@ type OptionalPropertyOf<T extends object> = Exclude<{
|
|
|
38
37
|
: K
|
|
39
38
|
}[keyof T], undefined>
|
|
40
39
|
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
40
|
export type OrderOption<T extends Entity<any> = any> = Order<T>[];
|
|
43
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
41
|
export type IncludeOption<T extends Entity<any> = any> = OptionalPropertyOf<T>[];
|
|
45
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
42
|
export type AllOptions<T extends Entity<any> = any> = { filter?: string; order?: OrderOption<T>; page?: number; limit?: number, include?: IncludeOption<T> }
|
|
47
43
|
|
|
48
44
|
export abstract class BookshelfRepository<IDType, T extends Entity<IDType>> {
|
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.RecommendationController = void 0;
|
|
7
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
8
7
|
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
9
8
|
const unsafe_data_1 = require("./unsafe-data");
|
|
10
9
|
const RecommendationIncludesMap = {
|