ghost 6.61.0 → 6.63.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.
Files changed (619) hide show
  1. package/components/ghost-storage-base-3.0.0.tgz +0 -0
  2. package/components/tryghost-adapter-base-cache-0.2.0.tgz +0 -0
  3. package/components/tryghost-adapter-base-jobs-0.0.0.tgz +0 -0
  4. package/components/tryghost-adapter-base-redirects-0.0.0.tgz +0 -0
  5. package/components/tryghost-adapter-base-route-settings-0.0.0.tgz +0 -0
  6. package/components/tryghost-adapter-base-scheduling-0.2.3.tgz +0 -0
  7. package/components/tryghost-adapter-base-sso-0.1.3.tgz +0 -0
  8. package/components/tryghost-admin-api-schema-0.0.0.tgz +0 -0
  9. package/components/tryghost-checkout-0.0.0.tgz +0 -0
  10. package/components/tryghost-i18n-0.0.0.tgz +0 -0
  11. package/components/tryghost-kg-card-factory-5.2.4.tgz +0 -0
  12. package/components/tryghost-kg-clean-basic-html-4.3.4.tgz +0 -0
  13. package/components/tryghost-kg-converters-1.2.5.tgz +0 -0
  14. package/components/tryghost-kg-default-cards-10.3.5.tgz +0 -0
  15. package/components/tryghost-kg-default-nodes-2.2.1.tgz +0 -0
  16. package/components/tryghost-kg-default-transforms-1.3.4.tgz +0 -0
  17. package/components/tryghost-kg-html-to-lexical-1.4.0.tgz +0 -0
  18. package/components/tryghost-kg-lexical-html-renderer-1.5.0.tgz +0 -0
  19. package/components/tryghost-kg-markdown-html-renderer-7.2.4.tgz +0 -0
  20. package/components/tryghost-kg-utils-1.1.4.tgz +0 -0
  21. package/components/tryghost-limit-service-0.0.0.tgz +0 -0
  22. package/components/tryghost-metafield-types-0.0.0.tgz +0 -0
  23. package/components/tryghost-nql-string-0.0.0.tgz +0 -0
  24. package/components/tryghost-parse-email-address-0.0.0.tgz +0 -0
  25. package/content/settings/README.md +1 -1
  26. package/content/themes/casper/.gitignore +28 -0
  27. package/content/themes/casper/assets/built/casper.js +1 -1
  28. package/content/themes/casper/assets/built/screen.css +1 -1
  29. package/content/themes/casper/assets/css/screen.css +2 -1
  30. package/content/themes/casper/assets/js/lightbox.js +63 -46
  31. package/content/themes/casper/package.json +6 -6
  32. package/content/themes/casper/page.hbs +1 -0
  33. package/content/themes/casper/post.hbs +1 -0
  34. package/content/themes/source/.gitignore +28 -0
  35. package/content/themes/source/assets/built/screen.css +1 -1
  36. package/content/themes/source/assets/built/source.js +1 -1
  37. package/content/themes/source/assets/css/screen.css +2 -1
  38. package/content/themes/source/assets/js/lightbox.js +62 -45
  39. package/content/themes/source/assets/js/main.js +2 -2
  40. package/content/themes/source/package.json +4 -4
  41. package/content/themes/source/partials/feature-image.hbs +1 -0
  42. package/content/themes/source/partials/post-card.hbs +1 -1
  43. package/core/boot.js +61 -27
  44. package/core/built/admin/assets/Combination-B0l4MKVh.js +41 -0
  45. package/core/built/admin/assets/InterVariable-DiVDrmQJ.woff2 +0 -0
  46. package/core/built/admin/assets/InterVariable-Italic-FCBEiFp6.woff2 +0 -0
  47. package/core/built/admin/assets/{about-Bve7IJS2.js → about-C1C3s5-g.js} +1 -1
  48. package/core/built/admin/assets/accordion-CxGsDKwa.js +1 -0
  49. package/core/built/admin/assets/account-migration-CbUhW6gk.js +1 -0
  50. package/core/built/admin/assets/activitypub/{account-migration-C-aej4x_.js → account-migration-KA6Jjf9L.js} +16 -16
  51. package/core/built/admin/assets/activitypub/activitypub.js +9 -9
  52. package/core/built/admin/assets/activitypub/{avatar-DLPL3Abs.js → avatar-DVJF5bxP.js} +2 -2
  53. package/core/built/admin/assets/activitypub/{avatar-flipboard-C9iDY-QV.js → avatar-flipboard-csQaNeYK.js} +2 -2
  54. package/core/built/admin/assets/activitypub/{bluesky-sharing-BXkA5mqV.js → bluesky-sharing-C7nTDMvw.js} +37 -37
  55. package/core/built/admin/assets/activitypub/{content-formatters-CHcyMFk4.js → content-formatters-CLcjaBwV.js} +4 -4
  56. package/core/built/admin/assets/activitypub/{copy-DIAOQoCZ.js → copy-DcOh8kXw.js} +2 -2
  57. package/core/built/admin/assets/activitypub/{domain-B3ihkPde.js → domain-fZ-X8i4-.js} +121 -121
  58. package/core/built/admin/assets/activitypub/{edit-profile-DsZM3rTX.js → edit-profile-BqMLQV88.js} +40 -40
  59. package/core/built/admin/assets/activitypub/{explore-BodNrZgR.js → explore-B4yPoP8E.js} +27 -27
  60. package/core/built/admin/assets/activitypub/{feed-PwH1iJ84.js → feed-BRC_mvAe.js} +51 -51
  61. package/core/built/admin/assets/activitypub/{field-D06-kmOJ.js → field-COacNgOt.js} +3 -3
  62. package/core/built/admin/assets/activitypub/{hash-Bm3WxYN4.js → hash-C7u-irQQ.js} +2 -2
  63. package/core/built/admin/assets/activitypub/inbox-BW-yvUoN.js +1284 -0
  64. package/core/built/admin/assets/activitypub/{inbox-d8oJRTf4.js → inbox-CbTTdDQ3.js} +2 -2
  65. package/core/built/admin/assets/activitypub/label-kPMmYI7l.js +16 -0
  66. package/core/built/admin/assets/activitypub/layout-BL4_jtuV.js +1 -0
  67. package/core/built/admin/assets/activitypub/{moderation-D1Yapsod.js → moderation-CuidJzc0.js} +91 -91
  68. package/core/built/admin/assets/activitypub/{note-C5zjqq5C.js → note-CAMRRSqD.js} +24 -24
  69. package/core/built/admin/assets/activitypub/{notifications-B9p8eCHD.js → notifications-BmNlXGgp.js} +51 -51
  70. package/core/built/admin/assets/activitypub/{onboarding-CNelD_uF.js → onboarding-Bqg7fh_L.js} +2 -2
  71. package/core/built/admin/assets/activitypub/{onboarding-mat5Hrl0.js → onboarding-Dmun9jr_.js} +2 -2
  72. package/core/built/admin/assets/activitypub/{preferences-BCqUdC3v.js → preferences--oH19wf9.js} +1519 -1519
  73. package/core/built/admin/assets/activitypub/{profile-BRCWoFem.js → profile-DH_tQx2D.js} +185 -185
  74. package/core/built/admin/assets/activitypub/{reply-DYK5vVqb.js → reply-Cap9PxSH.js} +2 -2
  75. package/core/built/admin/assets/activitypub/{routes-BSXT992i.js → routes-DdyY9uFF.js} +744 -735
  76. package/core/built/admin/assets/activitypub/{separator-BbQqTm-p.js → separator-CAxxu8VV.js} +3 -3
  77. package/core/built/admin/assets/activitypub/settings-B6EEcVkW.js +315 -0
  78. package/core/built/admin/assets/activitypub/{site-DHoMupSB.js → site-BYps63oh.js} +2 -2
  79. package/core/built/admin/assets/activitypub/{step-1-B-YfsVeO.js → step-1-CKjR2KAm.js} +6 -6
  80. package/core/built/admin/assets/activitypub/{step-2-DtPQzlTH.js → step-2-B6PKfOUQ.js} +6 -6
  81. package/core/built/admin/assets/activitypub/{step-3-D6BFMXL_.js → step-3-C-qBbcUo.js} +11 -11
  82. package/core/built/admin/assets/activitypub/{tabs-GpNecvfB.js → tabs-DLhZtVde.js} +306 -306
  83. package/core/built/admin/assets/activitypub/{topic-filter-BPDeQQys.js → topic-filter-DsUOuu0k.js} +3 -3
  84. package/core/built/admin/assets/activitypub/{use-activity-pub-queries-BoVOxXkV.js → use-activity-pub-queries-CX9snsLs.js} +3 -3
  85. package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-Bmk5h4lW.js → use-navigate-with-base-path-DsJTGDSS.js} +988 -959
  86. package/core/built/admin/assets/activitypub/{use-reply-chain-data-wVBX7swM.js → use-reply-chain-data-AJi9zkzm.js} +30 -30
  87. package/core/built/admin/assets/activitypub/{users-CoX6FT_K.js → users-inweyKL5.js} +192 -164
  88. package/core/built/admin/assets/activitypub/{x-DbQZOLiI.js → x-DR8AT3-4.js} +2 -2
  89. package/core/built/admin/assets/add-integration-modal-BT_onDJy.js +1 -0
  90. package/core/built/admin/assets/add-newsletter-modal-Cx1kQpiY.js +1 -0
  91. package/core/built/admin/assets/add-recommendation-modal-B5nvAhvr.js +1 -0
  92. package/core/built/admin/assets/analytics-DjoJWPI7.js +1 -0
  93. package/core/built/admin/assets/{announcement-bar-modal-DM3cYOpo.js → announcement-bar-modal-Dwd0EGFP.js} +1 -1
  94. package/core/built/admin/assets/{api-keys-3-0vJC3Y.js → api-keys-BGPzLHzA.js} +1 -1
  95. package/core/built/admin/assets/{api-keys-BLm2NDBh.js → api-keys-BoeacM-s.js} +1 -1
  96. package/core/built/admin/assets/{audience-9mwU5TW6.js → audience-ceV3XVHq.js} +1 -1
  97. package/core/built/admin/assets/automated-emails-BLesE41L.js +1 -0
  98. package/core/built/admin/assets/{automations-sAcJ1334.js → automations-BN4u3GR8.js} +1 -1
  99. package/core/built/admin/assets/automations-C-ZTUwW3.js +1 -0
  100. package/core/built/admin/assets/bluesky-sharing-vzh-oPXL.js +1 -0
  101. package/core/built/admin/assets/{breadcrumb-DLiqCyFc.js → breadcrumb-CaLk2b7D.js} +1 -1
  102. package/core/built/admin/assets/{button-B2jcu6bk.js → button-Dvcv1QSR.js} +1 -1
  103. package/core/built/admin/assets/calendar-Bl9RLcZX.js +1 -0
  104. package/core/built/admin/assets/{chart-helpers-Fo3bUL3K.js → chart-helpers-FHywU0pj.js} +1 -1
  105. package/core/built/admin/assets/{checkbox-BfKktMph.js → checkbox-BtayFtjg.js} +1 -1
  106. package/core/built/admin/assets/chunk.254.035b85ec456ebbd7336b.js +440 -0
  107. package/core/built/admin/assets/{chunk.524.60ca4692d91c6022042f.js → chunk.524.e6975095fccdf22d90f8.js} +5 -5
  108. package/core/built/admin/assets/{chunk.582.525c7617c2d9e94c940a.js → chunk.582.98b485f9b2802f540897.js} +6 -6
  109. package/core/built/admin/assets/{chunk.492.f24d855d7e3f3aad261c.js → chunk.901.4ccc639821020230bcca.js} +9949 -7921
  110. package/core/built/admin/assets/{code-editor-view-DCQJxsfU.js → code-editor-view-C3ZfoF1X.js} +1 -1
  111. package/core/built/admin/assets/{code-editor-view-CYVu4EW6.js → code-editor-view-CAyRWy1s.js} +1 -1
  112. package/core/built/admin/assets/color-picker-G4kGR7rp.js +3 -0
  113. package/core/built/admin/assets/color-picker-field-DQFVTNnT.js +1 -0
  114. package/core/built/admin/assets/combobox-BnYzgEB4.js +1 -0
  115. package/core/built/admin/assets/command-C_vyTikI.js +1 -0
  116. package/core/built/admin/assets/comments-aBrxfnZf.js +1 -0
  117. package/core/built/admin/assets/{config-DOMQDZGZ.js → config-kSHvwdTG.js} +1 -1
  118. package/core/built/admin/assets/confirmation-context-DwXX_Y5h.js +1 -0
  119. package/core/built/admin/assets/{content-api-modal-CyQEC3fr.js → content-api-modal-D2G0nJP6.js} +1 -1
  120. package/core/built/admin/assets/context-menu-DOVB6yaz.js +1 -0
  121. package/core/built/admin/assets/{copy-field-B3M1s78L.js → copy-field-DCJwh9qf.js} +1 -1
  122. package/core/built/admin/assets/create-ghost-browse-value-source-5C53jJaX.js +1 -0
  123. package/core/built/admin/assets/custom-field-type-option-BAuW0F-E.js +1 -0
  124. package/core/built/admin/assets/custom-integration-modal-AbJGVyKc.js +1 -0
  125. package/core/built/admin/assets/{date-range-select-DD2RKkgB.js → date-range-select-BY3K-ukj.js} +1 -1
  126. package/core/built/admin/assets/design-and-theme-modal-BvEy4_pC.js +2 -0
  127. package/core/built/admin/assets/dirty-confirm-dialog-DVPuGz3U.js +1 -0
  128. package/core/built/admin/assets/{disabled-sources-indicator-Cvy47bE2.js → disabled-sources-indicator-Cy7Zp4c8.js} +1 -1
  129. package/core/built/admin/assets/dist-Dcsslyo72.js +1 -0
  130. package/core/built/admin/assets/domain-Dl61QGuk.js +1 -0
  131. package/core/built/admin/assets/dropzone-Dtz5Rmjt.js +5 -0
  132. package/core/built/admin/assets/edit-profile-DNJSMDwm.js +1 -0
  133. package/core/built/admin/assets/editor-DbAen9zf.js +8 -0
  134. package/core/built/admin/assets/editor-screen-BFWThIai.js +26 -0
  135. package/core/built/admin/assets/email-sending-status-context-CWDOD1FN.js +1 -0
  136. package/core/built/admin/assets/email-sending-status-provider-DCPkDICt.js +1 -0
  137. package/core/built/admin/assets/emails-vFMk4yYl.js +1 -0
  138. package/core/built/admin/assets/{embed-signup-form-modal-DeBMLxlL.js → embed-signup-form-modal-DGqsORxS.js} +1 -1
  139. package/core/built/admin/assets/en-B1jX3WMs.js +1 -0
  140. package/core/built/admin/assets/explore-nnRr1Fja.js +1 -0
  141. package/core/built/admin/assets/feature-flag-overrides-context-DQjdJFAk.js +1 -0
  142. package/core/built/admin/assets/feature-image-placeholder-BrIHmPs8.js +1 -0
  143. package/core/built/admin/assets/feed-BNUcNu-W.js +1 -0
  144. package/core/built/admin/assets/feedback-DJ4Zb9rZ.js +1 -0
  145. package/core/built/admin/assets/{field-Cj8lmDOo.js → field-C93_Mg6j.js} +1 -1
  146. package/core/built/admin/assets/filter-bar-Da1qxybu.js +1 -0
  147. package/core/built/admin/assets/filter-sources-CGJb4C5r.js +1 -0
  148. package/core/built/admin/assets/filters--kKP-EC8.js +1 -0
  149. package/core/built/admin/assets/filters-DxA_a4FP.js +1 -0
  150. package/core/built/admin/assets/first-promoter-modal-BYDtrz2S.js +1 -0
  151. package/core/built/admin/assets/focus-koenig-editor-on-bottom-click-BbSnGOtK.js +1 -0
  152. package/core/built/admin/assets/{ghost-c8807202a07c20030acb719ee0114815.css → ghost-8fd5bb799356bbefb254210ba7e1236d.css} +1 -1
  153. package/core/built/admin/assets/{ghost-3894eedcc6968f658578c0abfe942aab.js → ghost-b4e8a403baba61905cd7560e30b9732d.js} +63 -44
  154. package/core/built/admin/assets/{ghost-dark-fbf1e384aaef3ae315e540f0eb7373a7.css → ghost-dark-cac0cb2d5bb78e9bd14d8d1c2768ed45.css} +1 -1
  155. package/core/built/admin/assets/gift-link-modal-B7u5bD4e.js +1 -0
  156. package/core/built/admin/assets/{gift-links-DLDS7ljO.js → gift-links-CfLSnst2.js} +1 -1
  157. package/core/built/admin/assets/{growth-D6mhcx3q.js → growth-Cd1uO9d2.js} +1 -1
  158. package/core/built/admin/assets/growth-aG32xfdE.js +3 -0
  159. package/core/built/admin/assets/history-modal-Df8lW8h-.js +1 -0
  160. package/core/built/admin/assets/hooks-Cy_-oZ4o.js +2 -0
  161. package/core/built/admin/assets/{html-field-C8qVGGC1.js → html-field-DA4eU7eq.js} +1 -1
  162. package/core/built/admin/assets/{images-h8VZEQ9k.js → images-KXmyO3Ss.js} +1 -1
  163. package/core/built/admin/assets/{inbox-BYd1M06Q.js → inbox-gJHG7_xd.js} +14 -14
  164. package/core/built/admin/assets/index-BHHXtR5C.css +2 -0
  165. package/core/built/admin/assets/index-CgMCwsxN.js +4 -0
  166. package/core/built/admin/assets/index.es-CY6-yuw9.js +1 -0
  167. package/core/built/admin/assets/{input-group-D8sCXRF5.js → input-group-BE8rM2y1.js} +1 -1
  168. package/core/built/admin/assets/{integrations-Bjbu86Z0.js → integrations-B4kuRBFY.js} +1 -1
  169. package/core/built/admin/assets/invite-user-modal-B4CuNcx4.js +1 -0
  170. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +14 -14
  171. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +3 -3
  172. package/core/built/admin/assets/koenig-lexical/style.css +1 -1
  173. package/core/built/admin/assets/{koenig-lexical-_-IsVI7E.js → koenig-lexical-CGXb0F8o.js} +3 -3
  174. package/core/built/admin/assets/koenig-loader-BeM5rFPX.js +2 -0
  175. package/core/built/admin/assets/{kpi-card-DZQk_0W8.js → kpi-card-B21aToe8.js} +1 -1
  176. package/core/built/admin/assets/{kpi-card-DW_2y3ug.js → kpi-card-pz6Wv4Ae.js} +1 -1
  177. package/core/built/admin/assets/{kpi-helpers-PueTKuA6.js → kpi-helpers-Dq5jelmP.js} +1 -1
  178. package/core/built/admin/assets/{kpi-tabs-CojDs-Qz.js → kpi-tabs-DEZHpKUt.js} +1 -1
  179. package/core/built/admin/assets/{label-DjbT91GM.js → label-OLCzze8N.js} +1 -1
  180. package/core/built/admin/assets/label-picker-BigOvMPV.js +1 -0
  181. package/core/built/admin/assets/{labels-CH3Kn8RV.js → labels-Dr0SgUQD.js} +1 -1
  182. package/core/built/admin/assets/layout-DUTL8SH5.js +1 -0
  183. package/core/built/admin/assets/lib-7QPTI0FS.js +1 -0
  184. package/core/built/admin/assets/link-helpers-BRAg9SCj.js +1 -0
  185. package/core/built/admin/assets/links-BDHPTlyj.js +1 -0
  186. package/core/built/admin/assets/member-custom-fields-TRTHCAz9.js +1 -0
  187. package/core/built/admin/assets/member-detail-b6dRwc3C.js +1 -0
  188. package/core/built/admin/assets/members-Czt5lJSc.js +4 -0
  189. package/core/built/admin/assets/moderation-ZWefD9uH.js +1 -0
  190. package/core/built/admin/assets/{multi-select-combobox-B6LiRzDO.js → multi-select-combobox-CT13MTo-.js} +1 -1
  191. package/core/built/admin/assets/navigation-modal-C8FEhBK5.js +1 -0
  192. package/core/built/admin/assets/newsletter-5VYW4RyJ.js +1 -0
  193. package/core/built/admin/assets/newsletter-detail-modal-ChjC0ZqH.js +1 -0
  194. package/core/built/admin/assets/{newsletter-emails-CFeLlt4z.js → newsletter-emails-DZH6I-PY.js} +1 -1
  195. package/core/built/admin/assets/newsletters-DOC9KBcX.js +1 -0
  196. package/core/built/admin/assets/newsletters-Rq1M3GD-.js +1 -0
  197. package/core/built/admin/assets/note-DIV-Pojr.js +1 -0
  198. package/core/built/admin/assets/notifications-s20-H49V.js +1 -0
  199. package/core/built/admin/assets/nql-BLpCn7qX.js +21 -0
  200. package/core/built/admin/assets/{offers-9J1CSiLy.js → offers--e2nGvkW.js} +1 -1
  201. package/core/built/admin/assets/offers-container-modal-BmG5M5Tv.js +1 -0
  202. package/core/built/admin/assets/onboarding-CUuy9unR.js +1 -0
  203. package/core/built/admin/assets/{onboarding-B4YhlZ0i.js → onboarding-pXyct0Jm.js} +1 -1
  204. package/core/built/admin/assets/{onboarding-route-Dmc4IPm3.js → onboarding-route-CK4pcXoR.js} +1 -1
  205. package/core/built/admin/assets/overview-CaPsciMs.js +1 -0
  206. package/core/built/admin/assets/overview-a8GfcsKX.js +1 -0
  207. package/core/built/admin/assets/{page-header-BR_nbIPp.js → page-header-DM_KyoFI.js} +1 -1
  208. package/core/built/admin/assets/pagemenu-vgZVUVKR.js +1 -0
  209. package/core/built/admin/assets/pages-CjDY2CBI.js +1 -0
  210. package/core/built/admin/assets/pages-route-BzKZYdV5.js +1 -0
  211. package/core/built/admin/assets/papaparse.min-cQwnxGCG.js +10 -0
  212. package/core/built/admin/assets/{pintura-modal-BR9hEvS8.js → pintura-modal-DExCF1ii.js} +1 -1
  213. package/core/built/admin/assets/portal-frame-Cqanidq4.js +1 -0
  214. package/core/built/admin/assets/portal-modal-oinBgA27.js +1 -0
  215. package/core/built/admin/assets/post-analytics-C5oJ1dWV.js +1 -0
  216. package/core/built/admin/assets/post-analytics-header-OATo3X_r.js +1 -0
  217. package/core/built/admin/assets/post-analytics-provider-tOpIVGT5.js +1 -0
  218. package/core/built/admin/assets/post-helpers-C88JBa4D.js +1 -0
  219. package/core/built/admin/assets/post-share-modal-DvhC1XgV.js +1 -0
  220. package/core/built/admin/assets/post-utils-DKF4mfuo.js +1 -0
  221. package/core/built/admin/assets/posts-list-screen-o4ZjbgS3.js +2 -0
  222. package/core/built/admin/assets/posts-pCPrhQeR.js +1 -0
  223. package/core/built/admin/assets/posts-route-9F--xdIb.js +1 -0
  224. package/core/built/admin/assets/preferences--vNubsqD.js +5 -0
  225. package/core/built/admin/assets/{preview-modal-C-BL-F9k.js → preview-modal-YYbzlYdO.js} +1 -1
  226. package/core/built/admin/assets/profile-BllKV3dR.js +1 -0
  227. package/core/built/admin/assets/{radio-group-Bgz60i81.js → radio-group-DL8GI8rt.js} +1 -1
  228. package/core/built/admin/assets/{referrers-CnhCMWCs.js → referrers-D8oHPmDB.js} +1 -1
  229. package/core/built/admin/assets/router-provider-BSvTXgZY.js +1 -0
  230. package/core/built/admin/assets/schemas-BoYdB6YU.js +64 -0
  231. package/core/built/admin/assets/select-v5YbA3Mw.js +1 -0
  232. package/core/built/admin/assets/settings-PEsZupw1.js +4 -0
  233. package/core/built/admin/assets/{settings-breadcrumbs-CyP_9zTo.js → settings-breadcrumbs-NwPnCTC7.js} +1 -1
  234. package/core/built/admin/assets/settings-u_s1CRkr.js +1 -0
  235. package/core/built/admin/assets/share-modal-SskCmVGL.js +1 -0
  236. package/core/built/admin/assets/slack-modal-XxSJiYgo.js +1 -0
  237. package/core/built/admin/assets/{sort-button-Cc-Z96sA.js → sort-button-Cx1KtINE.js} +1 -1
  238. package/core/built/admin/assets/{source-icon-v6PUnmyM.js → source-icon-Bdp9Im_5.js} +1 -1
  239. package/core/built/admin/assets/stats-D9PDLS3x.js +1 -0
  240. package/core/built/admin/assets/stats-view-W2g6Jsd-.js +1 -0
  241. package/core/built/admin/assets/{step-1-DSRp2vBj.js → step-1-BQYzvBzr.js} +1 -1
  242. package/core/built/admin/assets/{step-2-COqv2g0u.js → step-2-xES32xJV.js} +1 -1
  243. package/core/built/admin/assets/{step-3-6W1NMVQc.js → step-3-DA_XK5kW.js} +2 -2
  244. package/core/built/admin/assets/{stripe-button-D2K42Uty.js → stripe-button-CVsLHelt.js} +1 -1
  245. package/core/built/admin/assets/stripe-connect-modal-ClmLOMGS.js +1 -0
  246. package/core/built/admin/assets/style-Wd9nQubI.css +1 -0
  247. package/core/built/admin/assets/{table-B2pIKjVh.js → table-BenqVupI.js} +1 -1
  248. package/core/built/admin/assets/{tabs-SaW_UT-Q.js → tabs-eBBlxPp8.js} +1 -1
  249. package/core/built/admin/assets/tag-detail-Ce8Se2qd.js +2 -0
  250. package/core/built/admin/assets/tag-picker-C3UR-uJ-.js +1 -0
  251. package/core/built/admin/assets/tags-B-kJxCs7.js +1 -0
  252. package/core/built/admin/assets/{tags-zTFiKRpb.js → tags-ChfdwJyS.js} +1 -1
  253. package/core/built/admin/assets/testimonials-modal-9Q6fT06V.js +1 -0
  254. package/core/built/admin/assets/tier-detail-modal-CDyYdqK7.js +1 -0
  255. package/core/built/admin/assets/tiers-BCpIOGQr.js +1 -0
  256. package/core/built/admin/assets/{toggle-group-EM9WpESu.js → toggle-group-CviIkyok.js} +1 -1
  257. package/core/built/admin/assets/{topic-filter-DY4gNHn2.js → topic-filter-I2jCBGxm.js} +1 -1
  258. package/core/built/admin/assets/{transistor-modal-CpyPG-MH.js → transistor-modal-p53u3W8y.js} +1 -1
  259. package/core/built/admin/assets/{trend-badge-ByMkuAuH.js → trend-badge-CideVzQd.js} +1 -1
  260. package/core/built/admin/assets/{unsplash-modal-Cv2Q6GtY.js → unsplash-modal-DY8UcKcE.js} +1 -1
  261. package/core/built/admin/assets/{use-analytics-data-CHvjMYuT.js → use-analytics-data-DAIGcr2f.js} +1 -1
  262. package/core/built/admin/assets/use-check-theme-limit-error-B8bjF-gO.css +1 -0
  263. package/core/built/admin/assets/{use-check-theme-limit-error-Qv4SVXqw.js → use-check-theme-limit-error-DRUjK4YM.js} +1 -1
  264. package/core/built/admin/assets/use-filter-params-JkZhIS8L.js +1 -0
  265. package/core/built/admin/assets/{use-filterable-api-CzXcpUh8.js → use-filterable-api-BVEVMrhZ.js} +1 -1
  266. package/core/built/admin/assets/use-growth-stats-937CUj6j.js +1 -0
  267. package/core/built/admin/assets/use-host-limits-D0Dv3tKA.js +1 -0
  268. package/core/built/admin/assets/{use-limiter-cwJvsNBo.js → use-limiter-CohWfzvK.js} +1 -1
  269. package/core/built/admin/assets/{use-navigate-with-base-path-BHPA228f.js → use-navigate-with-base-path-BkxcPj5l.js} +1 -1
  270. package/core/built/admin/assets/use-pintura-config-xgytjU35.js +1 -0
  271. package/core/built/admin/assets/{use-pintura-editor-BDBXWUYq.js → use-pintura-editor-CaV1mbfO.js} +1 -1
  272. package/core/built/admin/assets/{use-post-referrers-DbY-mzci.js → use-post-referrers-BCQI7fDg.js} +1 -1
  273. package/core/built/admin/assets/use-reply-chain-data-CYRhoaxY.js +1 -0
  274. package/core/built/admin/assets/{use-router-history-entry-Bg6BhBQQ.js → use-router-history-entry-NOKcd--l.js} +1 -1
  275. package/core/built/admin/assets/{use-setting-group-VM7FQwMY.js → use-setting-group-bLKMwoBT.js} +1 -1
  276. package/core/built/admin/assets/use-settings-navigation-B-qrriKD.js +1 -0
  277. package/core/built/admin/assets/{use-simple-pagination-Dum6Irbs.js → use-simple-pagination-CNPd6Rf6.js} +1 -1
  278. package/core/built/admin/assets/use-staff-users-pRIMIyiW.js +1 -0
  279. package/core/built/admin/assets/use-tinybird-query-CmdbCS9X.js +1 -0
  280. package/core/built/admin/assets/use-tinybird-token-KLne235s.js +1 -0
  281. package/core/built/admin/assets/{use-unsaved-changes-guard-BAy0RANR.js → use-unsaved-changes-guard-7-ug0JdH.js} +1 -1
  282. package/core/built/admin/assets/use-upgrade-route-Dm_qqKr0.js +1 -0
  283. package/core/built/admin/assets/{use-url-input-Df5QzNa7.js → use-url-input-fvp-TpPx.js} +1 -1
  284. package/core/built/admin/assets/user-detail-modal-D3KlGYv-.js +1 -0
  285. package/core/built/admin/assets/users-DVNWrqg9.js +1 -0
  286. package/core/built/admin/assets/{vendor-5753232c7d6ffb3c44e1eb0a02133953.js → vendor-2dd263291938d407802568d3357ec69e.js} +19 -17
  287. package/core/built/admin/assets/{virtual-list-DEx8WgiO.js → virtual-list-CZ3RK2Yf.js} +1 -1
  288. package/core/built/admin/assets/web-ClEJsCAj.js +2 -0
  289. package/core/built/admin/assets/web-X9rdnrtq.js +1 -0
  290. package/core/built/admin/assets/{zapier-modal-Cw3BTBUu.js → zapier-modal-DfVhV17j.js} +1 -1
  291. package/core/built/admin/index.html +23 -27
  292. package/core/frontend/apps/private-blogging/lib/views/private.hbs +44 -43
  293. package/core/frontend/helpers/cancel_link.js +2 -2
  294. package/core/frontend/helpers/pagination.js +2 -2
  295. package/core/frontend/helpers/social_accounts.js +2 -2
  296. package/core/frontend/public/ghost.css +1 -1
  297. package/core/frontend/public/ghost.min.css +1 -1
  298. package/core/frontend/services/sitemap/user-map-generator.js +9 -2
  299. package/core/server/adapters/jobs/InMemoryJobsBackend.js +74 -29
  300. package/core/server/api/endpoints/authentication.js +1 -2
  301. package/core/server/api/endpoints/authors-public.js +15 -5
  302. package/core/server/api/endpoints/emails.js +13 -0
  303. package/core/server/api/endpoints/index.js +10 -2
  304. package/core/server/api/endpoints/mail.js +1 -1
  305. package/core/server/api/endpoints/member-metafields-members.js +23 -0
  306. package/core/server/api/endpoints/member-metafields.js +102 -0
  307. package/core/server/api/endpoints/members-account.js +42 -0
  308. package/core/server/api/endpoints/members.js +4 -4
  309. package/core/server/api/endpoints/newsletters-public.js +10 -1
  310. package/core/server/api/endpoints/pages-public.js +15 -5
  311. package/core/server/api/endpoints/posts-public.js +15 -5
  312. package/core/server/api/endpoints/posts.js +3 -3
  313. package/core/server/api/endpoints/tags-public.js +22 -3
  314. package/core/server/api/endpoints/tiers-checkout-config.js +2 -2
  315. package/core/server/api/endpoints/tiers-public.js +38 -1
  316. package/core/server/api/endpoints/users.js +2 -2
  317. package/core/server/api/endpoints/utils/api-filter-utils.js +170 -3
  318. package/core/server/api/endpoints/utils/public-cache-keys.js +3 -0
  319. package/core/server/api/endpoints/utils/serializers/input/authors.js +2 -0
  320. package/core/server/api/endpoints/utils/serializers/input/members.js +20 -9
  321. package/core/server/api/endpoints/utils/serializers/input/pages.js +2 -0
  322. package/core/server/api/endpoints/utils/serializers/input/posts.js +2 -0
  323. package/core/server/api/endpoints/utils/serializers/input/tags.js +2 -0
  324. package/core/server/api/endpoints/utils/serializers/output/emails.js +7 -0
  325. package/core/server/api/endpoints/utils/serializers/output/index.js +6 -2
  326. package/core/server/api/endpoints/utils/serializers/output/member-metafields.js +18 -0
  327. package/core/server/api/endpoints/utils/serializers/output/members-account.js +19 -0
  328. package/core/server/api/endpoints/utils/serializers/output/members-csv-transform.js +1 -1
  329. package/core/server/api/endpoints/utils/serializers/output/members.js +2 -4
  330. package/core/server/api/endpoints/utils/serializers/output/tiers.js +10 -2
  331. package/core/server/api/endpoints/utils/serializers/output/users.js +0 -10
  332. package/core/server/api/endpoints/utils/validators/input/invitations.js +0 -5
  333. package/core/server/api/endpoints/utils/validators/input/pages.js +1 -1
  334. package/core/server/api/endpoints/utils/validators/input/posts.js +1 -1
  335. package/core/server/data/exporter/table-lists.js +3 -3
  336. package/core/server/data/importer/importers/data/data-importer.js +3 -3
  337. package/core/server/data/migrations/utils/migrations.js +1 -1
  338. package/core/server/data/migrations/versions/6.53/2026-07-15-20-22-53-add-members-custom-field-values.js +1 -1
  339. package/core/server/data/migrations/versions/6.57/2026-08-04-18-00-00-store-custom-field-values-as-leaf-rows.js +10 -1
  340. package/core/server/data/migrations/versions/6.63/2026-09-03-10-07-03-rename-custom-field-tables-to-metafields.js +169 -0
  341. package/core/server/data/migrations/versions/6.63/2026-09-03-11-03-31-remove-member-custom-field-read-permissions.js +30 -0
  342. package/core/server/data/schema/fixtures/fixtures.json +0 -11
  343. package/core/server/data/schema/lib/default-index-name.js +8 -11
  344. package/core/server/data/schema/schema.js +18 -18
  345. package/core/server/data/seeders/README.md +48 -0
  346. package/core/server/data/tinybird/pipes/mv_hits.pipe +86 -50
  347. package/core/server/lib/db-types/count.js +16 -0
  348. package/core/server/lib/image/image-size.js +24 -0
  349. package/core/server/lib/package-json/parse.js +2 -2
  350. package/core/server/lib/validate-password.js +81 -120
  351. package/core/server/models/action.js +4 -4
  352. package/core/server/models/base/plugins/filtered-collection.js +16 -0
  353. package/core/server/models/member.js +10 -21
  354. package/core/server/models/post.js +2 -2
  355. package/core/server/models/relations/authors.js +2 -16
  356. package/core/server/models/user.js +10 -3
  357. package/core/server/services/auth/passwordreset.js +13 -0
  358. package/core/server/services/automations/automations-api.js +1 -1
  359. package/core/server/services/automations/database-automations-repository.js +11 -4
  360. package/core/server/services/comments/comments-controller.js +30 -9
  361. package/core/server/services/comments/comments-service.js +55 -5
  362. package/core/server/services/content-import/csv/formula.js +12 -0
  363. package/core/server/services/content-import/csv/index.js +6 -1
  364. package/core/server/services/content-import/csv/parse.js +27 -6
  365. package/core/server/services/content-import/csv/serialize.js +13 -0
  366. package/core/server/services/content-import/import/completion-email.js +164 -0
  367. package/core/server/services/content-import/import/errors-file.js +36 -0
  368. package/core/server/services/content-import/import/importer.js +160 -53
  369. package/core/server/services/content-import/import/local-media-url.js +63 -0
  370. package/core/server/services/content-import/import/media.js +254 -0
  371. package/core/server/services/content-import/import/post-data.js +0 -1
  372. package/core/server/services/content-import/import/post-link.js +11 -0
  373. package/core/server/services/content-import/import/post-repository.js +25 -3
  374. package/core/server/services/content-import/import/reader.js +9 -2
  375. package/core/server/services/content-import/import/report.js +34 -0
  376. package/core/server/services/content-import/import/row.js +0 -2
  377. package/core/server/services/content-import/import/schema.js +1 -0
  378. package/core/server/services/content-import/import/staged-file.js +29 -0
  379. package/core/server/services/content-import/import/store.js +25 -2
  380. package/core/server/services/content-import/index.js +52 -6
  381. package/core/server/services/content-import/jobs/content-csv-import-job.js +20 -0
  382. package/core/server/services/custom-redirects/redirect-config-parser.js +2 -2
  383. package/core/server/services/custom-redirects/redirects-service.js +1 -1
  384. package/core/server/services/custom-redirects/validation.js +1 -1
  385. package/core/server/services/email-address/email-address-parser.js +30 -38
  386. package/core/server/services/email-address/email-address-service.js +37 -4
  387. package/core/server/services/email-analytics/index.js +2 -7
  388. package/core/server/services/email-service/CONTEXT.md +37 -0
  389. package/core/server/services/email-service/README.md +42 -0
  390. package/core/server/services/email-service/batch-sending-service.js +2 -4
  391. package/core/server/services/email-service/email-controller.js +18 -2
  392. package/core/server/services/email-service/email-renderer.js +14 -4
  393. package/core/server/services/email-service/email-service-wrapper.js +3 -9
  394. package/core/server/services/email-service/mailgun-email-provider.js +20 -9
  395. package/core/server/services/email-service/sending-status-schema.js +21 -0
  396. package/core/server/services/email-service/sending-status-serializers.js +33 -0
  397. package/core/server/services/email-service/sending-status-service.js +47 -0
  398. package/core/server/services/email-service/sending-status.js +111 -0
  399. package/core/server/services/email-suppression-list/email-suppression-list.js +0 -33
  400. package/core/server/services/email-suppression-list/mailgun-email-suppression-list.js +6 -7
  401. package/core/server/services/gifts/README.md +2 -2
  402. package/core/server/services/gifts/constants.js +1 -1
  403. package/core/server/services/gifts/email-templates/gift-delivery.hbs +3 -3
  404. package/core/server/services/gifts/gift-email-service.js +0 -1
  405. package/core/server/services/gifts/gift-service.js +19 -57
  406. package/core/server/services/gifts/index.js +3 -5
  407. package/core/server/services/gifts/jobs/index.js +4 -4
  408. package/core/server/services/indexnow-ping/indexnow-ping-service.js +2 -2
  409. package/core/server/services/invitations/accept.js +4 -2
  410. package/core/server/services/jobs/job-service.js +0 -9
  411. package/core/server/services/jobs-service/index.js +8 -0
  412. package/core/server/services/jobs-service/jobs-service.js +52 -3
  413. package/core/server/services/jobs-service/register-job-handlers.js +32 -11
  414. package/core/server/services/mail/ghost-mailer.js +4 -4
  415. package/core/server/services/member-welcome-emails/service.js +7 -7
  416. package/core/server/services/members/account-service.js +98 -0
  417. package/core/server/services/members/api.js +4 -3
  418. package/core/server/services/members/import-export/csv/parse.js +0 -7
  419. package/core/server/services/members/import-export/export/exporter.js +20 -20
  420. package/core/server/services/members/import-export/import/completion-email.js +8 -11
  421. package/core/server/services/members/import-export/import/importer.js +13 -13
  422. package/core/server/services/members/import-export/import/row.js +0 -3
  423. package/core/server/services/members/import-export/index.js +10 -17
  424. package/core/server/services/members/jobs/clean-expired-comped-job.js +7 -0
  425. package/core/server/services/members/jobs/clean-expired-comped-task.js +145 -0
  426. package/core/server/services/members/jobs/index.js +48 -24
  427. package/core/server/services/members/members-api/controllers/member-controller.js +11 -0
  428. package/core/server/services/members/members-api/controllers/router-controller.js +3 -6
  429. package/core/server/services/members/members-api/members-api.js +26 -8
  430. package/core/server/services/members/members-api/repositories/event-repository.js +0 -4
  431. package/core/server/services/members/members-api/repositories/member-repository.js +4 -4
  432. package/core/server/services/members/members-api/services/member-bread-service.js +62 -84
  433. package/core/server/services/members/members-api/services/payments-service.js +1 -1
  434. package/core/server/services/members/members-ssr.js +18 -0
  435. package/core/server/services/members/middleware.js +95 -81
  436. package/core/server/services/members/service.js +71 -47
  437. package/core/server/services/members/utils.js +9 -0
  438. package/core/server/services/members-metafields/access.js +28 -0
  439. package/core/server/services/{members-custom-fields → members-metafields}/actions.js +5 -5
  440. package/core/server/services/members-metafields/bindings-service.js +147 -0
  441. package/core/server/services/members-metafields/codec.js +14 -0
  442. package/core/server/services/{members-custom-fields → members-metafields}/config.js +1 -1
  443. package/core/server/services/{members-custom-fields → members-metafields}/definitions-service.js +68 -22
  444. package/core/server/services/members-metafields/filter.js +181 -0
  445. package/core/server/services/{members-custom-fields → members-metafields}/index.js +16 -7
  446. package/core/server/services/{members-custom-fields → members-metafields}/key.js +2 -1
  447. package/core/server/services/{members-custom-fields → members-metafields}/models.js +5 -5
  448. package/core/server/services/members-metafields/namespaces.js +34 -0
  449. package/core/server/services/{members-custom-fields → members-metafields}/queries.js +1 -1
  450. package/core/server/services/{members-custom-fields → members-metafields}/schema.js +16 -12
  451. package/core/server/services/members-metafields/serializers.js +22 -0
  452. package/core/server/services/{members-custom-fields → members-metafields}/values-service.js +80 -48
  453. package/core/server/services/mentions/mention-controller.js +23 -21
  454. package/core/server/services/mentions/mention-sending-service.js +26 -9
  455. package/core/server/services/mentions/process-webmention-job.js +16 -0
  456. package/core/server/services/mentions/send-webmentions-job.js +18 -0
  457. package/core/server/services/mentions/service.js +7 -33
  458. package/core/server/services/route-settings/validation-errors.js +1 -1
  459. package/core/server/services/route-settings/yaml-parser.js +1 -1
  460. package/core/server/services/settings/settings-service.js +1 -8
  461. package/core/server/services/settings-helpers/settings-helpers.js +4 -6
  462. package/core/server/services/slack-ping/slack-ping-service.js +1 -1
  463. package/core/server/services/staff/staff-service-emails.js +2 -2
  464. package/core/server/services/stripe/config.js +14 -8
  465. package/core/server/services/stripe/service.js +10 -1
  466. package/core/server/services/stripe/services/checkout/completed-session.js +2 -2
  467. package/core/server/services/stripe/services/checkout/session-options.js +18 -15
  468. package/core/server/services/stripe/services/webhook/checkout-session-event-service.js +28 -7
  469. package/core/server/services/stripe/stripe-api.js +2 -0
  470. package/core/server/services/stripe/stripe-service.js +24 -14
  471. package/core/server/services/stripe/webhook-controller.js +10 -0
  472. package/core/server/services/tier-checkout-config/codec.js +11 -7
  473. package/core/server/services/tier-checkout-config/index.js +2 -1
  474. package/core/server/services/tier-checkout-config/models.js +11 -5
  475. package/core/server/services/tier-checkout-config/queries.js +12 -12
  476. package/core/server/services/tier-checkout-config/serializers.js +73 -10
  477. package/core/server/services/tier-checkout-config/service.js +14 -13
  478. package/core/server/services/tiers/service.js +3 -3
  479. package/core/server/services/update-check/index.js +13 -13
  480. package/core/server/services/update-check/jobs/update-check-job.js +7 -0
  481. package/core/server/services/update-check/update-check-service.js +2 -2
  482. package/core/server/services/url/router-filter.js +8 -10
  483. package/core/server/services/users.js +1 -19
  484. package/core/server/web/admin/controller.js +1 -1
  485. package/core/server/web/api/endpoints/admin/routes.js +20 -16
  486. package/core/server/web/members/account/index.js +2 -0
  487. package/core/server/web/members/account/routes.js +46 -0
  488. package/core/server/web/members/app.js +4 -18
  489. package/core/shared/config/defaults.json +1 -1
  490. package/core/shared/config/env/config.testing-mysql.json +1 -1
  491. package/core/shared/labs.js +7 -2
  492. package/package.json +42 -41
  493. package/pnpm-lock.yaml +1159 -582
  494. package/pnpm-workspace.yaml +18 -15
  495. package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
  496. package/components/tryghost-kg-default-nodes-2.2.0.tgz +0 -0
  497. package/core/built/admin/assets/Combination-5fYEzgbs.js +0 -41
  498. package/core/built/admin/assets/account-migration-DRhAehfw.js +0 -1
  499. package/core/built/admin/assets/activitypub/inbox-BluD2ucT.js +0 -1284
  500. package/core/built/admin/assets/activitypub/label-FHSh6ZAw.js +0 -16
  501. package/core/built/admin/assets/activitypub/layout-Cq4NG0Xr.js +0 -1
  502. package/core/built/admin/assets/activitypub/settings-DQDkr06X.js +0 -315
  503. package/core/built/admin/assets/add-integration-modal-BC0jExDZ.js +0 -1
  504. package/core/built/admin/assets/add-newsletter-modal-DchTkA7l.js +0 -1
  505. package/core/built/admin/assets/add-recommendation-modal-DMvaJZKp.js +0 -1
  506. package/core/built/admin/assets/alert-dialog-QhXzdHfc.js +0 -1
  507. package/core/built/admin/assets/analytics-No1DDY3A.js +0 -1
  508. package/core/built/admin/assets/automated-emails-te1D5kq-.js +0 -1
  509. package/core/built/admin/assets/automations-DpUNUdcZ.js +0 -1
  510. package/core/built/admin/assets/bluesky-sharing-Cjrv_f62.js +0 -1
  511. package/core/built/admin/assets/chunk.896.435fe0637944d4a69810.js +0 -366
  512. package/core/built/admin/assets/color-picker-BTY_NdEm.js +0 -3
  513. package/core/built/admin/assets/color-picker-field-CPlkzOH0.js +0 -1
  514. package/core/built/admin/assets/combobox-DrMtv_4P.js +0 -1
  515. package/core/built/admin/assets/command-ZdgYJpoI.js +0 -1
  516. package/core/built/admin/assets/comments-kidj60-h.js +0 -1
  517. package/core/built/admin/assets/confirmation-context-BhbmQQEl.js +0 -1
  518. package/core/built/admin/assets/custom-field-type-option-CsGIZk1J.js +0 -10
  519. package/core/built/admin/assets/custom-integration-modal-BY37O_9X.js +0 -1
  520. package/core/built/admin/assets/design-and-theme-modal-DUSKM4uC.js +0 -22
  521. package/core/built/admin/assets/dialog-B44iRwlc.js +0 -1
  522. package/core/built/admin/assets/dirty-confirm-dialog-BxgQgQ6H.js +0 -1
  523. package/core/built/admin/assets/dist-Cy8tfrp_.js +0 -1
  524. package/core/built/admin/assets/domain-Ca6KhoQt.js +0 -1
  525. package/core/built/admin/assets/dropzone-Bb-5zQTk.js +0 -5
  526. package/core/built/admin/assets/edit-profile-BdupLlus.js +0 -1
  527. package/core/built/admin/assets/editor-BP883Lpn.js +0 -8
  528. package/core/built/admin/assets/explore-FB-CimXw.js +0 -1
  529. package/core/built/admin/assets/feed-C1GxsmI2.js +0 -1
  530. package/core/built/admin/assets/filter-sources-D5n5bFA2.js +0 -1
  531. package/core/built/admin/assets/filters-DJEzkMUK.js +0 -1
  532. package/core/built/admin/assets/filters-MZXvdH5D.js +0 -1
  533. package/core/built/admin/assets/first-promoter-modal-CGTGLCr5.js +0 -1
  534. package/core/built/admin/assets/gift-link-modal-B6v0tnRN.js +0 -1
  535. package/core/built/admin/assets/growth-BGAJD1rs.js +0 -3
  536. package/core/built/admin/assets/history-modal-iKwUY3XR.js +0 -1
  537. package/core/built/admin/assets/hooks-CuEZV2-q.js +0 -2
  538. package/core/built/admin/assets/index-DjQe-e5s.js +0 -4
  539. package/core/built/admin/assets/index-Dqf2x-ry.css +0 -1
  540. package/core/built/admin/assets/index.es-VihPwfeH.js +0 -1
  541. package/core/built/admin/assets/input--W-rCTrX.js +0 -1
  542. package/core/built/admin/assets/invite-user-modal-MdImLCaJ.js +0 -1
  543. package/core/built/admin/assets/koenig-loader-DYZpm6El.js +0 -2
  544. package/core/built/admin/assets/label-picker-cB51xl1r.js +0 -1
  545. package/core/built/admin/assets/layout-c_B_1hax.js +0 -1
  546. package/core/built/admin/assets/link-helpers-MVDdnFCY.js +0 -1
  547. package/core/built/admin/assets/loading-indicator-BpFWTVgh.js +0 -1
  548. package/core/built/admin/assets/member-custom-fields-qs0dIkxM.js +0 -1
  549. package/core/built/admin/assets/member-detail-B6uec2a6.js +0 -1
  550. package/core/built/admin/assets/members-BQF3CqhI.js +0 -2
  551. package/core/built/admin/assets/moderation-DY4wF1Q3.js +0 -1
  552. package/core/built/admin/assets/navigation-modal-DX-gNF3X.js +0 -1
  553. package/core/built/admin/assets/newsletter-CyQA7m3m.js +0 -1
  554. package/core/built/admin/assets/newsletter-detail-modal-BDrptuxn.js +0 -1
  555. package/core/built/admin/assets/newsletters-DXuNmC42.js +0 -1
  556. package/core/built/admin/assets/newsletters-DhNigJUh.js +0 -1
  557. package/core/built/admin/assets/note-Cgo2LCJ6.js +0 -1
  558. package/core/built/admin/assets/notifications-BC50AMku.js +0 -1
  559. package/core/built/admin/assets/offers-container-modal-DWycIMzT.js +0 -1
  560. package/core/built/admin/assets/onboarding-DGQuV7Ew.js +0 -1
  561. package/core/built/admin/assets/overview-CVbFtn-k.js +0 -1
  562. package/core/built/admin/assets/overview-YKj7SZaK.js +0 -1
  563. package/core/built/admin/assets/pages-B6vr9F_D.js +0 -1
  564. package/core/built/admin/assets/popover-CCy0h5rq.js +0 -1
  565. package/core/built/admin/assets/portal-frame-dc4XKr0e.js +0 -1
  566. package/core/built/admin/assets/portal-modal-BvvdF_B9.js +0 -1
  567. package/core/built/admin/assets/post-analytics-DX470WRG.js +0 -1
  568. package/core/built/admin/assets/post-analytics-header-CXpJmdDv.js +0 -1
  569. package/core/built/admin/assets/post-analytics-provider-CLfKGWZy.js +0 -1
  570. package/core/built/admin/assets/post-helpers-C5OQMBoi.js +0 -1
  571. package/core/built/admin/assets/post-share-modal-Cl0NXRJr.js +0 -1
  572. package/core/built/admin/assets/posts-KY3aUhVV.js +0 -1
  573. package/core/built/admin/assets/preferences-DO0UUWFp.js +0 -5
  574. package/core/built/admin/assets/profile-CxT-0l4d.js +0 -1
  575. package/core/built/admin/assets/router-provider-B0gZyiGJ.js +0 -1
  576. package/core/built/admin/assets/schemas-4UPic-oD.js +0 -64
  577. package/core/built/admin/assets/select-DuDUFdPq.js +0 -1
  578. package/core/built/admin/assets/settings-BjCii7BM.js +0 -1
  579. package/core/built/admin/assets/settings-b8kNzZSQ.js +0 -4
  580. package/core/built/admin/assets/share-modal-BV70mr9k.js +0 -1
  581. package/core/built/admin/assets/shim-ClF_m5ux.js +0 -1
  582. package/core/built/admin/assets/slack-modal-Be2_KK-z.js +0 -1
  583. package/core/built/admin/assets/stats-C4reGh9O.js +0 -1
  584. package/core/built/admin/assets/stats-view-DP9pQ62k.js +0 -1
  585. package/core/built/admin/assets/stripe-connect-modal-Z-UT_BGc.js +0 -1
  586. package/core/built/admin/assets/tag-detail-Dc0nTOtU.js +0 -2
  587. package/core/built/admin/assets/tags-BLaXBwnb.js +0 -1
  588. package/core/built/admin/assets/testimonials-modal-sFwRnNLh.js +0 -1
  589. package/core/built/admin/assets/tier-detail-modal-BCFpWwUS.js +0 -1
  590. package/core/built/admin/assets/tiers-Nd_z4BZY.js +0 -1
  591. package/core/built/admin/assets/use-filter-params-CAvfDvf1.js +0 -1
  592. package/core/built/admin/assets/use-growth-stats-D6mZXGhK.js +0 -1
  593. package/core/built/admin/assets/use-host-limits-DZtR08oa.js +0 -1
  594. package/core/built/admin/assets/use-pintura-config-CzTfnufz.js +0 -1
  595. package/core/built/admin/assets/use-reply-chain-data-BeQwz8oF.js +0 -1
  596. package/core/built/admin/assets/use-settings-navigation-BbrSUVcf.js +0 -1
  597. package/core/built/admin/assets/use-staff-users-cZg4ugOF.js +0 -1
  598. package/core/built/admin/assets/use-tinybird-query-B1IMyAcv.js +0 -39
  599. package/core/built/admin/assets/use-tinybird-token-Bow0Zwn8.js +0 -1
  600. package/core/built/admin/assets/use-upgrade-route-DhRSo7at.js +0 -1
  601. package/core/built/admin/assets/user-detail-modal-yipSoQfv.js +0 -1
  602. package/core/built/admin/assets/users-5msE1WMs.js +0 -1
  603. package/core/built/admin/assets/web-CKcXAu86.js +0 -1
  604. package/core/built/admin/assets/web-DR4TqM3E.js +0 -2
  605. package/core/server/api/endpoints/member-custom-fields.js +0 -90
  606. package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.js +0 -20
  607. package/core/server/services/email-suppression-list/in-memory-email-suppression-list.js +0 -39
  608. package/core/server/services/jobs/worker-model-event-bridge.js +0 -149
  609. package/core/server/services/members/jobs/clean-expired-comped.js +0 -132
  610. package/core/server/services/members-custom-fields/bindings-service.js +0 -119
  611. package/core/server/services/members-custom-fields/codec.js +0 -15
  612. package/core/server/services/members-custom-fields/filter.js +0 -199
  613. package/core/server/services/members-custom-fields/serializers.js +0 -24
  614. package/core/server/services/stripe/services/checkout/allowed-countries.js +0 -267
  615. package/core/server/services/stripe/services/checkout/field-ports.js +0 -34
  616. package/core/server/services/tier-checkout-config/destinations.js +0 -17
  617. package/core/server/services/update-check/run-update-check.js +0 -63
  618. /package/core/built/admin/assets/{chunk.492.f24d855d7e3f3aad261c.js.LICENSE.txt → chunk.901.4ccc639821020230bcca.js.LICENSE.txt} +0 -0
  619. /package/core/server/services/{members-custom-fields → members-metafields}/storage.js +0 -0
@@ -10,6 +10,9 @@ const later = require('@breejs/later');
10
10
  const logging = require('@tryghost/logging');
11
11
  const DEFAULT_SHUTDOWN_TIMEOUT_MS = 10000;
12
12
  const DEFAULT_CONCURRENCY = 3;
13
+ // Envelopes with no routing share this lane; routing to "default" by name is
14
+ // the same lane, not a collision.
15
+ const DEFAULT_QUEUE = 'default';
13
16
  function hasSeconds(cron) {
14
17
  return cron.trim().split(/\s+/).length >= 6;
15
18
  }
@@ -29,60 +32,99 @@ function delay(ms) {
29
32
  setTimeout(resolve, ms);
30
33
  });
31
34
  }
35
+ // Work only flows between start() and shutdown(): boot starts the service
36
+ // before the web app is mounted or any recurring job is scheduled, so an
37
+ // enqueue or recurring registration before start() is a boot-ordering bug and
38
+ // throws, while an enqueue after shutdown() is a benign shutdown race and is
39
+ // dropped.
32
40
  class InMemoryJobsBackend extends adapter_base_jobs_1.JobsBackendBase {
33
41
  _processor;
34
42
  _stopped;
35
- _concurrency;
36
- _queue;
43
+ _defaultConcurrency;
44
+ _queues;
37
45
  _recurring;
38
46
  constructor(config = {}) {
39
47
  super();
40
48
  this._processor = null;
41
49
  this._stopped = false;
42
- this._concurrency = resolveConcurrency(config.concurrency);
43
- this._queue = this._createQueue();
50
+ this._defaultConcurrency = resolveConcurrency(config.concurrency);
51
+ this._queues = new Map();
44
52
  this._recurring = new Map();
45
53
  }
46
- _createQueue() {
47
- const queue = fastq_1.default.promise((envelope) => this._deliver(envelope), this._concurrency);
48
- // Paused until start() attaches a processor; enqueue buffers meanwhile.
49
- queue.pause();
50
- return queue;
54
+ _makeQueue(concurrency) {
55
+ return fastq_1.default.promise((envelope) => this._deliver(envelope), concurrency);
51
56
  }
52
- start({ processor }) {
57
+ start({ processor, queues }) {
58
+ const declared = new Map();
59
+ for (const [name, { concurrency }] of Object.entries(queues ?? {})) {
60
+ // A declaration the backend cannot satisfy must fail loudly here, never
61
+ // silently fall back (see the jobs-base README).
62
+ if (concurrency !== undefined && (!Number.isInteger(concurrency) || concurrency < 1)) {
63
+ throw new errors_1.default.IncorrectUsageError({
64
+ message: `Invalid concurrency for declared queue "${name}": ${JSON.stringify(concurrency)}. Expected a positive integer.`,
65
+ });
66
+ }
67
+ declared.set(name, concurrency ?? this._defaultConcurrency);
68
+ }
69
+ // State only changes once every declaration is valid, so a rejected
70
+ // start() never leaves a partially started backend that accepts work.
53
71
  this._processor = processor;
54
72
  this._stopped = false;
55
- this._queue.resume();
73
+ for (const [name, concurrency] of declared) {
74
+ this._queues.set(name, this._makeQueue(concurrency));
75
+ }
56
76
  }
57
- enqueue(envelope) {
77
+ enqueue(envelope, routing) {
58
78
  if (this._stopped) {
59
79
  return;
60
80
  }
61
- this._queue.push(envelope);
62
- }
63
- async _deliver(envelope) {
64
- const processor = this._processor;
65
- if (!processor) {
81
+ if (!this._processor) {
66
82
  throw new errors_1.default.IncorrectUsageError({
67
- message: 'InMemoryJobsBackend attempted a delivery with no processor attached - the backend lifecycle is broken.',
83
+ message: `Cannot enqueue job "${envelope.type}" before the jobs backend is started.`,
68
84
  });
69
85
  }
86
+ const name = routing?.queue ?? DEFAULT_QUEUE;
87
+ let queue = this._queues.get(name);
88
+ if (!queue) {
89
+ // Lanes are created lazily: the default lane, and any queue name no
90
+ // handler declared, each get their own lane at the default concurrency.
91
+ queue = this._makeQueue(this._defaultConcurrency);
92
+ this._queues.set(name, queue);
93
+ }
94
+ queue.push(envelope);
95
+ }
96
+ async _deliver(envelope) {
70
97
  try {
71
- await processor(envelope);
98
+ await this._processor(envelope);
72
99
  }
73
100
  catch (err) {
74
101
  logging.error(`Job "${envelope.type}" delivery failed`, err);
75
102
  }
76
103
  }
77
- scheduleRecurring(envelope, { cron }) {
104
+ scheduleRecurring(envelope, { cron }, routing) {
105
+ if (this._stopped) {
106
+ return;
107
+ }
108
+ if (!this._processor) {
109
+ throw new errors_1.default.IncorrectUsageError({
110
+ message: `Cannot schedule recurring job "${envelope.type}" before the jobs backend is started.`,
111
+ });
112
+ }
78
113
  // First schedule per type wins; a re-registration must not disturb a
79
114
  // schedule that is already running (parity with a durable backend).
80
- if (this._stopped || this._recurring.has(envelope.type)) {
115
+ if (this._recurring.has(envelope.type)) {
81
116
  return;
82
117
  }
83
118
  const parsed = later.parse.cron(cron, hasSeconds(cron));
84
119
  const timer = later.setInterval(() => {
85
- this.enqueue(envelope);
120
+ // A throw inside a later timer callback would be an uncaughtException;
121
+ // a recurring tick must never take the process down.
122
+ try {
123
+ this.enqueue(envelope, routing);
124
+ }
125
+ catch (err) {
126
+ logging.error(`Recurring job "${envelope.type}" tick failed to enqueue`, err);
127
+ }
86
128
  }, parsed);
87
129
  this._recurring.set(envelope.type, timer);
88
130
  }
@@ -99,14 +141,17 @@ class InMemoryJobsBackend extends adapter_base_jobs_1.JobsBackendBase {
99
141
  for (const type of [...this._recurring.keys()]) {
100
142
  this._clearRecurring(type);
101
143
  }
102
- const queue = this._queue;
103
- queue.kill();
104
- if (!queue.idle()) {
105
- await Promise.race([queue.drained(), delay(timeoutMs)]);
144
+ const queues = [...this._queues.values()];
145
+ for (const queue of queues) {
146
+ queue.kill();
147
+ }
148
+ const draining = queues.filter((queue) => !queue.idle());
149
+ if (draining.length > 0) {
150
+ await Promise.race([Promise.all(draining.map((queue) => queue.drained())), delay(timeoutMs)]);
106
151
  }
107
- // Fresh (paused) queue so a re-boot never inherits this lifecycle's
108
- // abandoned in-flight deliveries against its concurrency limit.
109
- this._queue = this._createQueue();
152
+ // Discard the queues so a re-boot never inherits this lifecycle's
153
+ // abandoned in-flight deliveries against its concurrency limits.
154
+ this._queues = new Map();
110
155
  this._processor = null;
111
156
  }
112
157
  }
@@ -7,11 +7,10 @@ const web = require('../../web');
7
7
  const models = require('../../models');
8
8
  const auth = require('../../services/auth');
9
9
  const invitations = require('../../services/invitations');
10
- const dbBackup = require('../../data/db/backup');
11
10
  const apiMail = require('./index').mail;
12
11
  const apiSettings = require('./index').settings;
13
12
  const UsersService = require('../../services/users');
14
- const userService = new UsersService({ dbBackup, models, auth, apiMail, apiSettings });
13
+ const userService = new UsersService({ models, auth, apiMail, apiSettings });
15
14
  const adapterManager = require('../../services/adapter-manager').default;
16
15
  const schedulerAdapter = adapterManager.getAdapter('scheduling');
17
16
 
@@ -1,12 +1,15 @@
1
1
  const tpl = require('@tryghost/tpl');
2
2
  const errors = require('@tryghost/errors');
3
+ const pick = require('lodash/pick');
3
4
  const models = require('../../models');
4
- const { rejectContentApiRestrictedFieldsTransformer } = require('./utils/api-filter-utils');
5
+ const { rejectAuthorsContentApiRestrictedFieldsTransformer } = require('./utils/api-filter-utils');
5
6
 
6
7
  const ALLOWED_INCLUDES = ['count.posts'];
8
+ const ALLOWED_READ_FIELDS = ['id', 'slug'];
7
9
 
8
10
  const messages = {
9
11
  notFound: 'Author not found.',
12
+ missingIdentifier: 'An author id or slug is required.',
10
13
  };
11
14
 
12
15
  /** @type {import('@tryghost/api-framework').Controller} */
@@ -29,7 +32,7 @@ const controller = {
29
32
  query(frame) {
30
33
  const options = {
31
34
  ...frame.options,
32
- mongoTransformer: rejectContentApiRestrictedFieldsTransformer,
35
+ mongoTransformer: rejectAuthorsContentApiRestrictedFieldsTransformer,
33
36
  };
34
37
  return models.Author.findPage(options);
35
38
  },
@@ -40,7 +43,7 @@ const controller = {
40
43
  cacheInvalidate: false,
41
44
  },
42
45
  options: ['include', 'filter', 'fields'],
43
- data: ['id', 'slug', 'email', 'role'],
46
+ data: ALLOWED_READ_FIELDS,
44
47
  validation: {
45
48
  options: {
46
49
  include: {
@@ -50,12 +53,19 @@ const controller = {
50
53
  },
51
54
  permissions: true,
52
55
  async query(frame) {
56
+ // GET bodies bypass the framework's declared data fields. Restrict the
57
+ // actual lookup too, before the model turns it into SQL predicates.
58
+ const data = pick(frame.data, ALLOWED_READ_FIELDS);
59
+ if (!Object.values(data).some(Boolean)) {
60
+ throw new errors.BadRequestError({ message: tpl(messages.missingIdentifier) });
61
+ }
62
+
53
63
  const options = {
54
64
  ...frame.options,
55
- mongoTransformer: rejectContentApiRestrictedFieldsTransformer,
65
+ mongoTransformer: rejectAuthorsContentApiRestrictedFieldsTransformer,
56
66
  };
57
67
 
58
- const model = await models.Author.findOne(frame.data, options);
68
+ const model = await models.Author.findOne(data, options);
59
69
  if (!model) {
60
70
  throw new errors.NotFoundError({
61
71
  message: tpl(messages.notFound),
@@ -51,6 +51,19 @@ const controller = {
51
51
  },
52
52
  },
53
53
 
54
+ sendingStatus: {
55
+ headers: {
56
+ cacheInvalidate: false,
57
+ },
58
+ data: ['id'],
59
+ permissions: {
60
+ method: 'read',
61
+ },
62
+ async query(frame) {
63
+ return await emailService.controller.getSendingStatus(frame);
64
+ },
65
+ },
66
+
54
67
  retry: {
55
68
  headers: {
56
69
  cacheInvalidate: false,
@@ -112,8 +112,8 @@ module.exports = {
112
112
  return apiFramework.pipeline(require('./members'), localUtils);
113
113
  },
114
114
 
115
- get membersCustomFields() {
116
- return apiFramework.pipeline(require('./member-custom-fields'), localUtils);
115
+ get membersMetafields() {
116
+ return apiFramework.pipeline(require('./member-metafields'), localUtils);
117
117
  },
118
118
 
119
119
  get tiersCheckoutConfig() {
@@ -312,6 +312,14 @@ module.exports = {
312
312
  return apiFramework.pipeline(require('./feedback-members'), localUtils, 'members');
313
313
  },
314
314
 
315
+ get membersAccount() {
316
+ return apiFramework.pipeline(require('./members-account'), localUtils, 'members');
317
+ },
318
+
319
+ get memberMetafieldsMembers() {
320
+ return apiFramework.pipeline(require('./member-metafields-members'), localUtils, 'members');
321
+ },
322
+
315
323
  get giftsMembers() {
316
324
  return apiFramework.pipeline(require('./gifts-members'), localUtils, 'members');
317
325
  },
@@ -25,7 +25,7 @@ _private.sendMail = (object) => {
25
25
  message: [
26
26
  tpl(messages.unableToSendEmail),
27
27
  tpl(messages.seeLinkForInstructions, {
28
- link: 'https://ghost.org/docs/concepts/config/#mail',
28
+ link: 'https://docs.ghost.org/concepts/config/#mail',
29
29
  }),
30
30
  ].join(' '),
31
31
  },
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const members_metafields_1 = require("../../services/members-metafields");
4
+ const controller = {
5
+ // The Admin resource's name, so the response Portal reads is the one Admin's
6
+ // serializer already produces. Only who may ask differs, and that is the route's
7
+ // business rather than the response's.
8
+ docName: 'members_metafields',
9
+ browse: {
10
+ headers: { cacheInvalidate: false },
11
+ options: ['namespace'],
12
+ validation: { options: { namespace: { required: true } } },
13
+ permissions: false,
14
+ query(frame) {
15
+ // No `filter`, which Admin offers: whether a field is archived is a
16
+ // publisher's business, and a member is only ever shown what they can still
17
+ // fill in.
18
+ return members_metafields_1.definitions.browse({ namespace: frame.options.namespace }, members_metafields_1.MEMBERS);
19
+ },
20
+ },
21
+ };
22
+ exports.default = controller;
23
+ module.exports = controller;
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const members_metafields_1 = require("../../services/members-metafields");
4
+ const namespaces_1 = require("../../services/members-metafields/namespaces");
5
+ const permissionsService = require('../../services/permissions');
6
+ // Reading a definition needs no permission. A definition says only that the site collects
7
+ // a shoe size, and every signed-in member is already shown the whole list, so there is
8
+ // nothing here to keep from staff. Defining one is the publisher's own, and with
9
+ // `permissions: true` the framework would check against the Bookshelf model named after
10
+ // the resource — these fields have no Bookshelf model, so each writing handler asks the
11
+ // permissions service directly.
12
+ function canThis(frame) {
13
+ return permissionsService.canThis(frame.options.context);
14
+ }
15
+ /**
16
+ * Settle the namespace before the caller.
17
+ *
18
+ * Which namespace is being written to decides whose authority applies, so it is resolved
19
+ * first; only once the publisher turns out to own it does a staff role become the
20
+ * question. The other order answers a request to define a field somewhere nobody owns
21
+ * with "you lack a permission", which sends the caller after a permission that would not
22
+ * have helped.
23
+ */
24
+ async function canDefine(frame, action) {
25
+ (0, namespaces_1.assertDefinable)(frame.options.namespace);
26
+ return action(frame);
27
+ }
28
+ const noCacheInvalidation = { cacheInvalidate: false };
29
+ const controller = {
30
+ docName: 'members_metafields',
31
+ browse: {
32
+ headers: noCacheInvalidation,
33
+ options: ['namespace', 'filter'],
34
+ validation: { options: { namespace: { required: true } } },
35
+ permissions: false,
36
+ query(frame) {
37
+ return members_metafields_1.definitions.browse({
38
+ namespace: frame.options.namespace,
39
+ filter: frame.options.filter,
40
+ });
41
+ },
42
+ },
43
+ read: {
44
+ headers: noCacheInvalidation,
45
+ options: ['namespace', 'key'],
46
+ validation: { options: { namespace: { required: true }, key: { required: true } } },
47
+ permissions: false,
48
+ query(frame) {
49
+ return members_metafields_1.definitions.read(frame.options.namespace, frame.options.key);
50
+ },
51
+ },
52
+ add: {
53
+ statusCode: 201,
54
+ headers: noCacheInvalidation,
55
+ options: ['namespace'],
56
+ validation: { options: { namespace: { required: true } } },
57
+ permissions(frame) {
58
+ return canDefine(frame, (f) => canThis(f).add.member_custom_field());
59
+ },
60
+ query(frame) {
61
+ return members_metafields_1.definitions.add((0, members_metafields_1.actingContext)(frame.options.context), frame.options.namespace, frame.data.members_metafields);
62
+ },
63
+ },
64
+ reorder: {
65
+ headers: noCacheInvalidation,
66
+ options: ['namespace'],
67
+ validation: { options: { namespace: { required: true } } },
68
+ permissions(frame) {
69
+ return canDefine(frame, (f) => canThis(f).edit.member_custom_field());
70
+ },
71
+ query(frame) {
72
+ return members_metafields_1.definitions.reorder((0, members_metafields_1.actingContext)(frame.options.context), frame.options.namespace, frame.data.members_metafields);
73
+ },
74
+ },
75
+ edit: {
76
+ headers: noCacheInvalidation,
77
+ options: ['namespace', 'key'],
78
+ validation: { options: { namespace: { required: true }, key: { required: true } } },
79
+ permissions(frame) {
80
+ return canDefine(frame, (f) => canThis(f).edit.member_custom_field(f.options.key));
81
+ },
82
+ query(frame) {
83
+ return members_metafields_1.definitions.edit((0, members_metafields_1.actingContext)(frame.options.context), frame.options.namespace, frame.options.key, frame.data.members_metafields[0]);
84
+ },
85
+ },
86
+ destroy: {
87
+ statusCode: 204,
88
+ headers: noCacheInvalidation,
89
+ options: ['namespace', 'key'],
90
+ validation: { options: { namespace: { required: true }, key: { required: true } } },
91
+ permissions(frame) {
92
+ return canDefine(frame, (f) => canThis(f).destroy.member_custom_field(f.options.key));
93
+ },
94
+ async query(frame) {
95
+ await members_metafields_1.definitions.destroy((0, members_metafields_1.actingContext)(frame.options.context), frame.options.namespace, frame.options.key);
96
+ return null;
97
+ },
98
+ },
99
+ };
100
+ // The API framework loads this file with `require()`, so it exports CommonJS-style;
101
+ // `export default` would not be picked up.
102
+ module.exports = controller;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const membersService = require('../../services/members');
4
+ const memberOf = (frame) => frame.options?.context?.member ?? null;
5
+ const controller = {
6
+ docName: 'members_account',
7
+ read: {
8
+ headers: { cacheInvalidate: false },
9
+ permissions: false,
10
+ query(frame) {
11
+ return membersService.api.account.read(memberOf(frame).id);
12
+ },
13
+ },
14
+ /**
15
+ * Let Ghost email this member again.
16
+ *
17
+ * Under the account rather than as a resource of its own: being emailable is a
18
+ * fact about a member, and the only person who can restore it here is the member
19
+ * themselves.
20
+ */
21
+ destroySuppression: {
22
+ statusCode: 204,
23
+ headers: { cacheInvalidate: false },
24
+ permissions: false,
25
+ query(frame) {
26
+ const member = memberOf(frame);
27
+ return membersService.api.account.allowEmail(member.id, member.email);
28
+ },
29
+ },
30
+ // `update` rather than `edit`: the framework reserves `edit` for the Admin API's
31
+ // enveloped bodies, and this request has always carried a bare one. The
32
+ // members-facing gift endpoints name their own verbs for the same reason.
33
+ update: {
34
+ headers: { cacheInvalidate: false },
35
+ permissions: false,
36
+ query(frame) {
37
+ return membersService.api.account.edit(frame.data, memberOf(frame).id);
38
+ },
39
+ },
40
+ };
41
+ exports.default = controller;
42
+ module.exports = controller;
@@ -44,10 +44,10 @@ const messages = {
44
44
  resourceNotFound: '{resource} not found.',
45
45
  };
46
46
 
47
- // `custom_fields` is a browse include only: a read returns values whenever the
48
- // flag is on, the same way it returns tiers. Values are not a member relation, so
49
- // the input serializer lifts the key out of withRelated before the model sees it.
50
- const allowedIncludes = ['email_recipients', 'products', 'tiers', 'custom_fields'];
47
+ // `metafields` is not a relation on the member model. It is allowed here only so callers
48
+ // can ask for it with `include=`; the input serializer removes it before the model tries
49
+ // to eager-load it.
50
+ const allowedIncludes = ['email_recipients', 'products', 'tiers', 'metafields'];
51
51
 
52
52
  /** @type {import('@tryghost/api-framework').Controller} */
53
53
  const controller = {
@@ -1,4 +1,8 @@
1
1
  const models = require('../../models');
2
+ const {
3
+ rejectNewslettersContentApiRestrictedFieldsTransformer,
4
+ rejectNewslettersContentApiRestrictedOrderFields,
5
+ } = require('./utils/api-filter-utils');
2
6
 
3
7
  /** @type {import('@tryghost/api-framework').Controller} */
4
8
  const controller = {
@@ -11,7 +15,12 @@ const controller = {
11
15
  options: ['filter', 'fields', 'limit', 'order', 'page'],
12
16
  permissions: true,
13
17
  query(frame) {
14
- return models.Newsletter.findPage(frame.options);
18
+ const options = {
19
+ ...frame.options,
20
+ order: rejectNewslettersContentApiRestrictedOrderFields(frame.options.order),
21
+ mongoTransformer: rejectNewslettersContentApiRestrictedFieldsTransformer,
22
+ };
23
+ return models.Newsletter.findPage(options);
15
24
  },
16
25
  },
17
26
  };
@@ -1,14 +1,17 @@
1
1
  const tpl = require('@tryghost/tpl');
2
2
  const errors = require('@tryghost/errors');
3
+ const pick = require('lodash/pick');
3
4
  const models = require('../../models');
4
- const { rejectContentApiRestrictedFieldsTransformer } = require('./utils/api-filter-utils');
5
+ const { rejectPagesContentApiRestrictedFieldsTransformer } = require('./utils/api-filter-utils');
5
6
  const { generateGiftKeyData, applyGiftAccess } = require('./utils/gift-link-access');
6
7
  const { generateOptionsData, generateAuthData } = require('./utils/public-cache-keys');
7
8
 
8
9
  const ALLOWED_INCLUDES = ['tags', 'authors', 'tiers'];
10
+ const ALLOWED_READ_FIELDS = ['id', 'slug', 'uuid'];
9
11
 
10
12
  const messages = {
11
13
  pageNotFound: 'Page not found.',
14
+ missingIdentifier: 'A page id, slug or uuid is required.',
12
15
  };
13
16
 
14
17
  /** @type {import('@tryghost/api-framework').Controller} */
@@ -44,7 +47,7 @@ const controller = {
44
47
  query(frame) {
45
48
  const options = {
46
49
  ...frame.options,
47
- mongoTransformer: rejectContentApiRestrictedFieldsTransformer,
50
+ mongoTransformer: rejectPagesContentApiRestrictedFieldsTransformer,
48
51
  };
49
52
  return models.Post.findPage(options);
50
53
  },
@@ -72,7 +75,7 @@ const controller = {
72
75
  };
73
76
  },
74
77
  options: ['include', 'fields', 'formats', 'debug', 'absolute_urls'],
75
- data: ['id', 'slug', 'uuid'],
78
+ data: ALLOWED_READ_FIELDS,
76
79
  validation: {
77
80
  options: {
78
81
  include: {
@@ -85,11 +88,18 @@ const controller = {
85
88
  },
86
89
  permissions: true,
87
90
  async query(frame) {
91
+ // GET bodies bypass the framework's declared data fields. Restrict the
92
+ // actual lookup too, before the model turns it into SQL predicates.
93
+ const data = pick(frame.data, ALLOWED_READ_FIELDS);
94
+ if (!Object.values(data).some(Boolean)) {
95
+ throw new errors.BadRequestError({ message: tpl(messages.missingIdentifier) });
96
+ }
97
+
88
98
  const options = {
89
99
  ...frame.options,
90
- mongoTransformer: rejectContentApiRestrictedFieldsTransformer,
100
+ mongoTransformer: rejectPagesContentApiRestrictedFieldsTransformer,
91
101
  };
92
- const model = await models.Post.findOne(frame.data, options);
102
+ const model = await models.Post.findOne(data, options);
93
103
  if (!model) {
94
104
  throw new errors.NotFoundError({
95
105
  message: tpl(messages.pageNotFound),
@@ -1,17 +1,20 @@
1
1
  const models = require('../../models');
2
2
  const tpl = require('@tryghost/tpl');
3
3
  const errors = require('@tryghost/errors');
4
+ const pick = require('lodash/pick');
4
5
  const postsPublicService = require('../../services/posts-public');
5
6
  const getPostServiceInstance = require('../../services/posts/posts-service-instance');
6
7
  const postsService = getPostServiceInstance();
7
- const { rejectContentApiRestrictedFieldsTransformer } = require('./utils/api-filter-utils');
8
+ const { rejectPostsContentApiRestrictedFieldsTransformer } = require('./utils/api-filter-utils');
8
9
  const { generateGiftKeyData, applyGiftAccess } = require('./utils/gift-link-access');
9
10
  const { generateOptionsData, generateAuthData } = require('./utils/public-cache-keys');
10
11
 
11
12
  const ALLOWED_INCLUDES = ['tags', 'authors', 'tiers', 'sentiment'];
13
+ const ALLOWED_READ_FIELDS = ['id', 'slug', 'uuid'];
12
14
 
13
15
  const messages = {
14
16
  postNotFound: 'Post not found.',
17
+ missingIdentifier: 'A post id, slug or uuid is required.',
15
18
  };
16
19
 
17
20
  /** @type {import('@tryghost/api-framework').Controller} */
@@ -68,7 +71,7 @@ const controller = {
68
71
  query(frame) {
69
72
  const options = {
70
73
  ...frame.options,
71
- mongoTransformer: rejectContentApiRestrictedFieldsTransformer,
74
+ mongoTransformer: rejectPostsContentApiRestrictedFieldsTransformer,
72
75
  };
73
76
  return postsService.browsePosts(options);
74
77
  },
@@ -93,7 +96,7 @@ const controller = {
93
96
  };
94
97
  },
95
98
  options: ['include', 'fields', 'formats', 'debug', 'absolute_urls'],
96
- data: ['id', 'slug', 'uuid'],
99
+ data: ALLOWED_READ_FIELDS,
97
100
  validation: {
98
101
  options: {
99
102
  include: {
@@ -106,11 +109,18 @@ const controller = {
106
109
  },
107
110
  permissions: true,
108
111
  async query(frame) {
112
+ // GET bodies bypass the framework's declared data fields. Restrict the
113
+ // actual lookup too, before the model turns it into SQL predicates.
114
+ const data = pick(frame.data, ALLOWED_READ_FIELDS);
115
+ if (!Object.values(data).some(Boolean)) {
116
+ throw new errors.BadRequestError({ message: tpl(messages.missingIdentifier) });
117
+ }
118
+
109
119
  const options = {
110
120
  ...frame.options,
111
- mongoTransformer: rejectContentApiRestrictedFieldsTransformer,
121
+ mongoTransformer: rejectPostsContentApiRestrictedFieldsTransformer,
112
122
  };
113
- const model = await models.Post.findOne(frame.data, options);
123
+ const model = await models.Post.findOne(data, options);
114
124
  if (!model) {
115
125
  throw new errors.NotFoundError({
116
126
  message: tpl(messages.postNotFound),
@@ -129,13 +129,13 @@ const controller = {
129
129
  method: 'importContent',
130
130
  },
131
131
  async query(frame) {
132
- // The CSV must be parsed before the response goes out: the uploaded temp file is
133
- // deleted as soon as it is sent. The posts are written by a background job behind
134
- // the 202.
132
+ // The content-import service stages and validates the upload before this response;
133
+ // Multer deletes the request temp file as soon as the 202 is sent.
135
134
  const { importId, total } = await contentImportService.importCSV({
136
135
  filePath: frame.file.path,
137
136
  fileName: frame.file.name,
138
137
  mapping: frame.data.mapping,
138
+ requestUserEmail: frame.user ? frame.user.get('email') : null,
139
139
  });
140
140
  return { meta: { import_id: importId, total } };
141
141
  },