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
@@ -2,19 +2,23 @@ TOKEN "axis" READ
2
2
 
3
3
  NODE mv_hits_0
4
4
  SQL >
5
-
6
- SELECT timestamp,
5
+ SELECT
6
+ timestamp,
7
7
  inserted_at,
8
8
  -- payload.meta.received_timestamp may be missing or null
9
- -- Nullable fields incur performance penalty in clickhouse, so we default to zero (unix epoch) instead of null.
10
- parseDateTime64BestEffortOrZero(JSONExtractString(payload, 'meta', 'received_timestamp'), 3) as received_at,
9
+ -- Nullable fields incur performance penalty in clickhouse, so we default to zero (unix epoch)
10
+ -- instead of null.
11
+ parseDateTime64BestEffortOrZero(
12
+ JSONExtractString(payload, 'meta', 'received_timestamp'), 3
13
+ ) as received_at,
11
14
  action,
12
15
  version,
13
16
  coalesce(session_id, '0') as session_id,
14
17
  JSONExtractString(payload, 'locale') as locale,
15
18
  JSONExtractString(payload, 'location') as location,
16
19
  case
17
- when JSONExtractString(payload, 'referrerSource') = '' then JSONExtractString(payload, 'meta', 'referrerSource')
20
+ when JSONExtractString(payload, 'referrerSource') = ''
21
+ then JSONExtractString(payload, 'meta', 'referrerSource')
18
22
  else JSONExtractString(payload, 'referrerSource')
19
23
  end as referrer,
20
24
  JSONExtractString(payload, 'pathname') as pathname,
@@ -35,11 +39,8 @@ SQL >
35
39
  FROM analytics_events
36
40
  where action = 'page_hit'
37
41
 
38
-
39
-
40
42
  NODE mv_hits_1
41
43
  SQL >
42
-
43
44
  SELECT
44
45
  site_uuid,
45
46
  timestamp,
@@ -47,8 +48,10 @@ SQL >
47
48
  inserted_at,
48
49
  case
49
50
  -- set to -1 if received_at is the unix epoch, or if received_at is after inserted_at
50
- when toUnixTimestamp(received_at) = 0 then -1
51
- when received_at > inserted_at then -1
51
+ when toUnixTimestamp(received_at) = 0
52
+ then -1
53
+ when received_at > inserted_at
54
+ then -1
52
55
  else date_diff('millisecond', received_at, inserted_at)
53
56
  end as ingestion_latency_ms,
54
57
  action,
@@ -61,58 +64,91 @@ SQL >
61
64
  gift_link,
62
65
  location,
63
66
  case
64
- when referrer = '' then ''
67
+ when referrer = ''
68
+ then ''
65
69
  -- Social Media Consolidation
66
- when referrer IN ('Facebook', 'www.facebook.com', 'l.facebook.com', 'lm.facebook.com', 'm.facebook.com', 'facebook') then 'Facebook'
67
- when referrer IN ('Twitter', 'x.com', 'com.twitter.android') then 'Twitter'
68
- when referrer IN ('go.bsky.app', 'bsky', 'bsky.app') then 'Bluesky'
69
- when referrer IN ('Instagram', 'www.instagram.com') then 'Instagram'
70
- when referrer IN ('LinkedIn', 'LINKEDIN_COMPANY') then 'LinkedIn'
71
- when referrer IN ('l.threads.com') then 'Threads'
72
-
70
+ when
71
+ referrer IN (
72
+ 'Facebook',
73
+ 'www.facebook.com',
74
+ 'l.facebook.com',
75
+ 'lm.facebook.com',
76
+ 'm.facebook.com',
77
+ 'facebook'
78
+ )
79
+ then 'Facebook'
80
+ when referrer IN ('Twitter', 'x.com', 'com.twitter.android')
81
+ then 'Twitter'
82
+ when referrer IN ('go.bsky.app', 'bsky', 'bsky.app')
83
+ then 'Bluesky'
84
+ when referrer IN ('Instagram', 'www.instagram.com')
85
+ then 'Instagram'
86
+ when referrer IN ('LinkedIn', 'LINKEDIN_COMPANY')
87
+ then 'LinkedIn'
88
+ when referrer IN ('l.threads.com')
89
+ then 'Threads'
73
90
  -- Reddit Ecosystem
74
- when referrer IN ('www.reddit.com', 'out.reddit.com', 'old.reddit.com', 'com.reddit.frontpage') then 'Reddit'
75
-
91
+ when
92
+ referrer
93
+ IN ('www.reddit.com', 'out.reddit.com', 'old.reddit.com', 'com.reddit.frontpage')
94
+ then 'Reddit'
76
95
  -- Search Engines (keep distinctions)
77
- when referrer IN ('search.brave.com') then 'Brave Search'
78
- when referrer IN ('www.ecosia.org') then 'Ecosia'
79
-
96
+ when referrer IN ('search.brave.com')
97
+ then 'Brave Search'
98
+ when referrer IN ('www.ecosia.org')
99
+ then 'Ecosia'
80
100
  -- Email Services
81
- when referrer IN ('Gmail', 'com.google.android.gm', 'mail.google.com') then 'Gmail'
82
- when referrer IN ('Outlook.com') then 'Outlook'
83
- when referrer IN ('Yahoo!', 'www.yahoo.com', 'Yahoo! Mail', 'r.search.yahoo.com') then 'Yahoo!'
84
- when referrer IN ('AOL Mail') then 'AOL Mail'
85
-
101
+ when referrer IN ('Gmail', 'com.google.android.gm', 'mail.google.com')
102
+ then 'Gmail'
103
+ when referrer IN ('Outlook.com')
104
+ then 'Outlook'
105
+ when referrer IN ('Yahoo!', 'www.yahoo.com', 'Yahoo! Mail', 'r.search.yahoo.com')
106
+ then 'Yahoo!'
107
+ when referrer IN ('AOL Mail')
108
+ then 'AOL Mail'
86
109
  -- Content Platforms
87
- when referrer IN ('flipboard', 'flipboard.com', 'flipboard.app') then 'Flipboard'
88
- when referrer IN ('substack', 'substack.com') then 'Substack'
89
- when referrer IN ('Ghost.org', 'ghost.org') then 'Ghost'
90
- when referrer IN ('buffer') then 'Buffer'
91
- when referrer IN ('Taboola') then 'Taboola'
92
- when referrer IN ('AppNexus') then 'AppNexus'
93
-
110
+ when referrer IN ('flipboard', 'flipboard.com', 'flipboard.app')
111
+ then 'Flipboard'
112
+ when referrer IN ('substack', 'substack.com')
113
+ then 'Substack'
114
+ when referrer IN ('Ghost.org', 'ghost.org')
115
+ then 'Ghost'
116
+ when referrer IN ('buffer')
117
+ then 'Buffer'
118
+ when referrer IN ('Taboola')
119
+ then 'Taboola'
120
+ when referrer IN ('AppNexus')
121
+ then 'AppNexus'
94
122
  -- Wikipedia
95
- when referrer IN ('en.wikipedia.org', 'en.m.wikipedia.org') then 'Wikipedia'
96
-
123
+ when referrer IN ('en.wikipedia.org', 'en.m.wikipedia.org')
124
+ then 'Wikipedia'
97
125
  -- Mastodon Network
98
- when referrer IN ('mastodon.social', 'mastodon.online', 'org.joinmastodon.android', 'phanpy.social', 'dev.phanpy.social') then 'Mastodon'
99
-
126
+ when
127
+ referrer IN (
128
+ 'mastodon.social',
129
+ 'mastodon.online',
130
+ 'org.joinmastodon.android',
131
+ 'phanpy.social',
132
+ 'dev.phanpy.social'
133
+ )
134
+ then 'Mastodon'
100
135
  -- News Aggregators
101
- when referrer IN ('www.memeorandum.com', 'memeorandum.com') then 'Memeorandum'
102
- when referrer IN ('ground.news') then 'Ground News'
103
- when referrer IN ('apple.news') then 'Apple News'
104
- when referrer IN ('www.smartnews.com') then 'SmartNews'
105
-
136
+ when referrer IN ('www.memeorandum.com', 'memeorandum.com')
137
+ then 'Memeorandum'
138
+ when referrer IN ('ground.news')
139
+ then 'Ground News'
140
+ when referrer IN ('apple.news')
141
+ then 'Apple News'
142
+ when referrer IN ('www.smartnews.com')
143
+ then 'SmartNews'
106
144
  -- Keep other sources as-is
107
- when domainWithoutWWW(referrer) != '' then domainWithoutWWW(referrer)
145
+ when domainWithoutWWW(referrer) != ''
146
+ then domainWithoutWWW(referrer)
108
147
  else referrer
109
148
  end as source,
110
149
  pathname,
111
150
  href,
112
- case
113
- when device = '' then 'unknown'
114
- else device
115
- end as device,
151
+ case when device = '' then 'unknown' else device end as device,
116
152
  case
117
153
  when match(user_agent, 'windows')
118
154
  then 'windows'
@@ -146,5 +182,5 @@ SQL >
146
182
  utm_content
147
183
  FROM mv_hits_0
148
184
 
149
- TYPE materialized
185
+ TYPE MATERIALIZED
150
186
  DATASOURCE _mv_hits
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DbCount = void 0;
4
+ const zod_1 = require("zod");
5
+ const databaseCountInput = zod_1.z.union([zod_1.z.number(), zod_1.z.string().regex(/^\d+$/)]);
6
+ /**
7
+ * A non-negative integer count, whichever database driver handed it back.
8
+ *
9
+ * Aggregate functions such as COUNT can return a decimal string from MySQL and
10
+ * a number from SQLite. Every read normalises to a safe integer so callers do
11
+ * not need to handle that driver difference themselves.
12
+ */
13
+ exports.DbCount = zod_1.z.codec(databaseCountInput, zod_1.z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER), {
14
+ decode: (stored) => (typeof stored === 'string' ? Number(stored) : stored),
15
+ encode: (value) => value,
16
+ });
@@ -31,6 +31,12 @@ class ImageSize {
31
31
  },
32
32
  response_timeout: this.config.get('times:getImageSizeTimeoutInMS') || 10000,
33
33
  };
34
+
35
+ // Coalesces concurrent getImageSizeFromUrl() calls for the same URL so we only
36
+ // ever issue one underlying request/read per URL at a time. A single post's
37
+ // coverImage/ogImage/twitterImage often resolve to the same feature_image URL
38
+ // and are looked up concurrently, which otherwise fans out into duplicate requests.
39
+ this.inFlightImageSizeLookups = new Map();
34
40
  }
35
41
 
36
42
  // processes the Buffer result of an image file using image-size
@@ -153,6 +159,24 @@ class ImageSize {
153
159
  * @returns {Promise<Object>} imageObject or error
154
160
  */
155
161
  getImageSizeFromUrl(imagePath) {
162
+ if (this.inFlightImageSizeLookups.has(imagePath)) {
163
+ return this.inFlightImageSizeLookups.get(imagePath);
164
+ }
165
+
166
+ const promise = this._getImageSizeFromUrl(imagePath).finally(() => {
167
+ this.inFlightImageSizeLookups.delete(imagePath);
168
+ });
169
+ this.inFlightImageSizeLookups.set(imagePath, promise);
170
+
171
+ return promise;
172
+ }
173
+
174
+ /**
175
+ * @description read image dimensions from URL, without in-flight deduplication
176
+ * @param {string} imagePath as URL
177
+ * @returns {Promise<Object>} imageObject or error
178
+ */
179
+ _getImageSizeFromUrl(imagePath) {
156
180
  if (this.storageUtils.isLocalImage(imagePath)) {
157
181
  // don't make a request for a locally stored image
158
182
  return this.getImageSizeFromStoragePath(imagePath);
@@ -37,7 +37,7 @@ async function parse(path) {
37
37
  message: tpl(messages.themeFileIsMalformed),
38
38
  context: path,
39
39
  err: parseError,
40
- help: tpl(messages.willBeRequired, { url: 'https://ghost.org/docs/themes/' }),
40
+ help: tpl(messages.willBeRequired, { url: 'https://docs.ghost.org/themes/' }),
41
41
  });
42
42
  }
43
43
 
@@ -47,7 +47,7 @@ async function parse(path) {
47
47
  throw new errors.IncorrectUsageError({
48
48
  message: tpl(messages.nameOrVersionMissing),
49
49
  context: path,
50
- help: tpl(messages.willBeRequired, { url: 'https://ghost.org/docs/themes/' }),
50
+ help: tpl(messages.willBeRequired, { url: 'https://docs.ghost.org/themes/' }),
51
51
  });
52
52
  }
53
53
 
@@ -1,131 +1,92 @@
1
- const _ = require('lodash');
2
-
3
- const validator = require('@tryghost/validator');
4
-
5
- const tpl = require('@tryghost/tpl');
6
- const settingsCache = require('../../shared/settings-cache');
7
- const urlUtils = require('../../shared/url-utils').default;
8
-
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.validatePassword = validatePassword;
7
+ const tpl_1 = __importDefault(require("@tryghost/tpl"));
8
+ // @ts-expect-error This module lacks type definitions.
9
+ const validator_1 = __importDefault(require("@tryghost/validator"));
10
+ // @ts-expect-error This module lacks type definitions.
11
+ const settings_cache_1 = __importDefault(require("../../shared/settings-cache"));
12
+ const url_utils_1 = __importDefault(require("../../shared/url-utils"));
9
13
  const messages = {
10
- passwordDoesNotComplyLength: 'Your password must be at least {minLength} characters long.',
11
- passwordDoesNotComplySecurity: 'Sorry, you cannot use an insecure password.',
14
+ passwordTooShort: 'Your password must be at least {minLength} characters long.',
15
+ passwordTooLong: 'Your password is too long.',
16
+ passwordDoesNotComplySecurity: 'Sorry, you cannot use an insecure password.',
12
17
  };
13
-
14
18
  /**
15
19
  * Counts repeated characters in a string. When 50% or more characters are the same,
16
20
  * we return false and therefore invalidate the string.
17
- * @param {string} stringToTest The password string to check.
18
- * @return {boolean}
19
21
  */
20
- function characterOccurance(stringToTest) {
21
- const chars = {};
22
- let allowedOccurancy;
23
- let valid = true;
24
-
25
- stringToTest = _.toString(stringToTest);
26
- allowedOccurancy = stringToTest.length / 2;
27
-
28
- // Loop through string and accumulate character counts
29
- _.each(stringToTest, function (char) {
30
- if (!chars[char]) {
31
- chars[char] = 1;
32
- } else {
33
- chars[char] += 1;
34
- }
35
- });
36
-
37
- // check if any of the accumulated chars exceed the allowed occurancy
38
- // of 50% of the words' length.
39
- _.forIn(chars, function (charCount) {
40
- if (charCount >= allowedOccurancy) {
41
- valid = false;
22
+ function characterOccurrence(stringToTest) {
23
+ const limit = stringToTest.length / 2;
24
+ const counts = new Map();
25
+ for (let i = 0; i < stringToTest.length; i++) {
26
+ const char = stringToTest[i];
27
+ const count = (counts.get(char) || 0) + 1;
28
+ if (count >= limit) {
29
+ return false;
30
+ }
31
+ counts.set(char, count);
42
32
  }
43
- });
44
-
45
- return valid;
33
+ return true;
46
34
  }
47
-
48
- /**
49
- * Validation against simple password rules
50
- * Returns false when validation fails and true for a valid password
51
- * @param {string} password The password string to check.
52
- * @param {string} email The users email address to validate agains password.
53
- * @param {string} [blogTitle] Optional blogTitle value, when blog title is not set yet, e. g. in setup process.
54
- * @return {Object} example for returned validation Object:
55
- * invalid password: `validationResult: {isValid: false, message: 'Sorry, you cannot use an insecure password.'}`
56
- * valid password: `validationResult: {isValid: true}`
57
- */
58
- function validatePassword(password, email, blogTitle) {
59
- const validationResult = { isValid: true };
60
- const disallowedPasswords = ['password', 'ghost', 'passw0rd'];
61
- let blogUrl = urlUtils.urlFor('home', true);
62
-
63
- const badPasswords = [
64
- '1234567890',
65
- 'qwertyuiop',
66
- 'qwertzuiop',
67
- 'asdfghjkl;',
68
- 'abcdefghij',
69
- '0987654321',
70
- '1q2w3e4r5t',
71
- '12345asdfg',
72
- ];
73
-
74
- blogTitle = blogTitle ? blogTitle : settingsCache.get('title');
75
- blogUrl = blogUrl.replace(/^http(s?):\/\//, '');
76
-
77
- // password must be longer than 10 characters
78
- if (!validator.isLength(password, 10)) {
79
- validationResult.isValid = false;
80
- validationResult.message = tpl(messages.passwordDoesNotComplyLength, { minLength: 10 });
81
-
82
- return validationResult;
83
- }
84
-
85
- // dissallow password from badPasswords list (e. g. '1234567890')
86
- _.each(badPasswords, function (badPassword) {
87
- if (badPassword === password) {
88
- validationResult.isValid = false;
35
+ /** Validation against simple password rules. */
36
+ function validatePassword(password, email, siteTitle) {
37
+ // password cannot be longer than 256 code units, for performance
38
+ if (password.length > 256) {
39
+ return { isValid: false, message: (0, tpl_1.default)(messages.passwordTooLong) };
40
+ }
41
+ // password must be longer than 10 characters
42
+ if (!validator_1.default.isLength(password, 10)) {
43
+ return { isValid: false, message: (0, tpl_1.default)(messages.passwordTooShort, { minLength: 10 }) };
44
+ }
45
+ const invalidValidationResult = {
46
+ isValid: false,
47
+ message: (0, tpl_1.default)(messages.passwordDoesNotComplySecurity),
48
+ };
49
+ // password must not match with users' email
50
+ if (email && email.toLowerCase() === password.toLowerCase()) {
51
+ return invalidValidationResult;
52
+ }
53
+ // password must not match with site title
54
+ siteTitle = siteTitle || settings_cache_1.default.get('title');
55
+ if (siteTitle && siteTitle.toLowerCase() === password.toLowerCase()) {
56
+ return invalidValidationResult;
57
+ }
58
+ // password must not match with site URL (without protocol, with or without trailing slash)
59
+ let siteUrl = url_utils_1.default.urlFor('home', true);
60
+ siteUrl = siteUrl.replace(/^http(s?):\/\//, '');
61
+ if (siteUrl &&
62
+ (siteUrl.toLowerCase() === password.toLowerCase() ||
63
+ siteUrl.toLowerCase().replace(/\/$/, '') === password.toLowerCase())) {
64
+ return invalidValidationResult;
65
+ }
66
+ // disallow password from badPasswords list (e. g. '1234567890')
67
+ const badPasswords = [
68
+ '1234567890',
69
+ 'qwertyuiop',
70
+ 'qwertzuiop',
71
+ 'asdfghjkl;',
72
+ 'abcdefghij',
73
+ '0987654321',
74
+ '1q2w3e4r5t',
75
+ '12345asdfg',
76
+ ];
77
+ if (badPasswords.includes(password)) {
78
+ return invalidValidationResult;
79
+ }
80
+ // password must not contain the words 'ghost', 'password', or 'passw0rd'
81
+ const disallowedPasswords = ['password', 'ghost', 'passw0rd'];
82
+ for (const disallowedPassword of disallowedPasswords) {
83
+ if (password.toLowerCase().includes(disallowedPassword)) {
84
+ return invalidValidationResult;
85
+ }
89
86
  }
90
- });
91
-
92
- // password must not match with users' email
93
- if (email && email.toLowerCase() === password.toLowerCase()) {
94
- validationResult.isValid = false;
95
- }
96
-
97
- // password must not contain the words 'ghost', 'password', or 'passw0rd'
98
- _.each(disallowedPasswords, function (disallowedPassword) {
99
- if (password.toLowerCase().indexOf(disallowedPassword) >= 0) {
100
- validationResult.isValid = false;
87
+ // dissallow passwords where 50% or more of characters are the same
88
+ if (!characterOccurrence(password)) {
89
+ return invalidValidationResult;
101
90
  }
102
- });
103
-
104
- // password must not match with blog title
105
- if (blogTitle && blogTitle.toLowerCase() === password.toLowerCase()) {
106
- validationResult.isValid = false;
107
- }
108
-
109
- // password must not match with blog URL (without protocol, with or without trailing slash)
110
- if (
111
- blogUrl &&
112
- (blogUrl.toLowerCase() === password.toLowerCase() ||
113
- blogUrl.toLowerCase().replace(/\/$/, '') === password.toLowerCase())
114
- ) {
115
- validationResult.isValid = false;
116
- }
117
-
118
- // dissallow passwords where 50% or more of characters are the same
119
- if (!characterOccurance(password)) {
120
- validationResult.isValid = false;
121
- }
122
-
123
- // Generic error message for the rules where no dedicated error massage is set
124
- if (!validationResult.isValid && !validationResult.message) {
125
- validationResult.message = tpl(messages.passwordDoesNotComplySecurity);
126
- }
127
-
128
- return validationResult;
91
+ return { isValid: true };
129
92
  }
130
-
131
- module.exports = validatePassword;
@@ -1,10 +1,10 @@
1
1
  const ghostBookshelf = require('./base');
2
2
 
3
- // Member custom fields are owned by a raw-knex service rather than the Bookshelf
3
+ // Member metafields are owned by a raw-knex service rather than the Bookshelf
4
4
  // registry. Actions still need a read model for `include=resource` to recognise
5
5
  // their polymorphic resource type and load the current field definition.
6
- const MemberCustomFieldResource = ghostBookshelf.Model.extend({
7
- tableName: 'members_custom_fields',
6
+ const MemberMetafieldResource = ghostBookshelf.Model.extend({
7
+ tableName: 'members_metafields',
8
8
  });
9
9
 
10
10
  const Action = ghostBookshelf.Model.extend(
@@ -26,7 +26,7 @@ const Action = ghostBookshelf.Model.extend(
26
26
  candidates.push([User, 'security_action']);
27
27
  }
28
28
 
29
- candidates.push([MemberCustomFieldResource, 'member_custom_field']);
29
+ candidates.push([MemberMetafieldResource, 'member_custom_field']);
30
30
 
31
31
  return candidates;
32
32
  },
@@ -1,3 +1,6 @@
1
+ const _ = require('lodash');
2
+ const { hasPosts } = require('@tryghost/bookshelf-plugins');
3
+
1
4
  /**
2
5
  * @param {import('bookshelf')} Bookshelf
3
6
  */
@@ -17,6 +20,19 @@ module.exports = function (Bookshelf) {
17
20
  // Apply model-specific search behavior
18
21
  filteredCollection.applySearchQuery(options);
19
22
 
23
+ // Authors are hidden unless they have posts. Apply that constraint before
24
+ // fetchPage clones its count query so pagination cannot reveal hidden staff.
25
+ // Keep this author-specific: tags have separate, established count semantics.
26
+ if (filteredCollection.shouldHavePosts?.joinTable === 'posts_authors') {
27
+ filteredCollection.query(
28
+ hasPosts.addHasPostsWhere(
29
+ _.result(filteredCollection, 'tableName'),
30
+ filteredCollection.shouldHavePosts,
31
+ ),
32
+ );
33
+ filteredCollection.shouldHavePosts = null;
34
+ }
35
+
20
36
  return filteredCollection;
21
37
  },
22
38
 
@@ -3,12 +3,11 @@ const crypto = require('crypto');
3
3
  const _ = require('lodash');
4
4
  const { chainTransformers } = require('@tryghost/mongo-utils');
5
5
  const config = require('../../shared/config');
6
- const labs = require('../../shared/labs');
7
6
  const { MemberCommentingCodec } = require('../services/members/commenting');
8
7
  const {
9
- CUSTOM_FIELDS_RELATION,
10
- createCustomFieldsFilterTransformer,
11
- } = require('../services/members-custom-fields/filter');
8
+ METAFIELDS_RELATION,
9
+ createMetafieldsFilterTransformer,
10
+ } = require('../services/members-metafields/filter');
12
11
 
13
12
  const DEEP_OFFSET_THRESHOLD = 1000;
14
13
 
@@ -191,19 +190,13 @@ const Member = ghostBookshelf.Model.extend(
191
190
  ];
192
191
  },
193
192
 
194
- // Chain the custom-field filter transformer at this single choke point the method
195
- // every members query routes its filter through (list, CSV export, bulk edit/destroy,
196
- // count, email send all reach it via findPage or getFilteredCollectionQuery) — so a
197
- // saved `custom_fields.*` segment works the same everywhere without each call site
198
- // wiring it. Runs only behind the flag and only when the filter names the relation; the
199
- // transformer maps the public `key`/`value` grammar onto the leaf-row columns.
193
+ // Every members query routes its filter through this one method: list, CSV export, bulk
194
+ // edit and delete, counts and email sends all reach it via findPage or
195
+ // getFilteredCollectionQuery. Chaining the metafield filter transformer here covers them
196
+ // all without any call site wiring it.
200
197
  applyDefaultAndCustomFilters(options) {
201
- if (
202
- labs.isSet('membersCustomFields') &&
203
- options.filter &&
204
- options.filter.includes(`${CUSTOM_FIELDS_RELATION.tableNameAs}.`)
205
- ) {
206
- const transformer = createCustomFieldsFilterTransformer();
198
+ if (options.filter && options.filter.includes(`${METAFIELDS_RELATION.tableNameAs}.`)) {
199
+ const transformer = createMetafieldsFilterTransformer();
207
200
  options.mongoTransformer = options.mongoTransformer
208
201
  ? chainTransformers(options.mongoTransformer, transformer)
209
202
  : transformer;
@@ -213,11 +206,7 @@ const Member = ghostBookshelf.Model.extend(
213
206
 
214
207
  filterRelations() {
215
208
  return {
216
- // Custom field values are filterable only behind the feature flag. Gating the
217
- // relation here (rather than the whole model) means a `custom_fields.*` filter
218
- // is simply an unknown relation when the flag is off, and the filter is
219
- // rejected — nothing to special-case downstream.
220
- ...(labs.isSet('membersCustomFields') ? { custom_fields: CUSTOM_FIELDS_RELATION } : {}),
209
+ metafields: METAFIELDS_RELATION,
221
210
  labels: {
222
211
  tableName: 'labels',
223
212
  type: 'manyToMany',
@@ -29,9 +29,9 @@ const messages = {
29
29
  notEnoughPermission: 'You do not have permission to perform this action',
30
30
  invalidNewsletter: "The newsletter parameter doesn't match any active newsletter.",
31
31
  invalidMobiledocStructure: 'Invalid mobiledoc structure.',
32
- invalidMobiledocStructureHelp: 'https://ghost.org/docs/publishing/',
32
+ invalidMobiledocStructureHelp: 'https://docs.ghost.org/publishing/',
33
33
  invalidLexicalStructure: 'Invalid lexical structure.',
34
- invalidLexicalStructureHelp: 'https://ghost.org/docs/publishing/',
34
+ invalidLexicalStructureHelp: 'https://docs.ghost.org/publishing/',
35
35
  emailOnlyWithoutNewsletter: 'Scheduling an email requires a newsletter reference.',
36
36
  };
37
37
 
@@ -149,7 +149,6 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
149
149
 
150
150
  // CASE: `posts.authors` was not requested, but fetched in specific cases (see top)
151
151
  if (
152
- !this._originalOptions ||
153
152
  !this._originalOptions.withRelated ||
154
153
  this._originalOptions.withRelated.indexOf('authors') === -1
155
154
  ) {
@@ -157,10 +156,7 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
157
156
  }
158
157
 
159
158
  // If the current column settings allow it...
160
- if (
161
- !options.columns ||
162
- (options.columns && options.columns.indexOf('primary_author') > -1)
163
- ) {
159
+ if (!options.columns || options.columns.indexOf('primary_author') > -1) {
164
160
  // ... attach a computed property of primary_author which is the first author
165
161
  if (attrs.authors && attrs.authors.length) {
166
162
  attrs.primary_author = attrs.authors[0];
@@ -398,20 +394,10 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
398
394
  }
399
395
 
400
396
  function isOwner() {
401
- let isCorrectOwner = true;
402
-
403
397
  if (!unsafeAttrs.authors) {
404
398
  return false;
405
399
  }
406
-
407
- if (unsafeAttrs.authors) {
408
- isCorrectOwner =
409
- isCorrectOwner &&
410
- unsafeAttrs.authors.length &&
411
- unsafeAttrs.authors[0].id === context.user;
412
- }
413
-
414
- return isCorrectOwner;
400
+ return unsafeAttrs.authors.length && unsafeAttrs.authors[0].id === context.user;
415
401
  }
416
402
 
417
403
  function isPrimaryAuthor() {