ghost 5.86.2 → 5.87.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +6 -5
  3. package/components/tryghost-adapter-cache-memory-ttl-5.87.1.tgz +0 -0
  4. package/components/{tryghost-adapter-cache-redis-5.86.2.tgz → tryghost-adapter-cache-redis-5.87.1.tgz} +0 -0
  5. package/components/tryghost-adapter-manager-5.87.1.tgz +0 -0
  6. package/components/tryghost-announcement-bar-settings-5.87.1.tgz +0 -0
  7. package/components/{tryghost-api-framework-5.86.2.tgz → tryghost-api-framework-5.87.1.tgz} +0 -0
  8. package/components/tryghost-api-version-compatibility-service-5.87.1.tgz +0 -0
  9. package/components/tryghost-audience-feedback-5.87.1.tgz +0 -0
  10. package/components/tryghost-bookshelf-repository-5.87.1.tgz +0 -0
  11. package/components/tryghost-bootstrap-socket-5.87.1.tgz +0 -0
  12. package/components/tryghost-collections-5.87.1.tgz +0 -0
  13. package/components/{tryghost-constants-5.86.2.tgz → tryghost-constants-5.87.1.tgz} +0 -0
  14. package/components/{tryghost-custom-theme-settings-service-5.86.2.tgz → tryghost-custom-theme-settings-service-5.87.1.tgz} +0 -0
  15. package/components/{tryghost-data-generator-5.86.2.tgz → tryghost-data-generator-5.87.1.tgz} +0 -0
  16. package/components/tryghost-domain-events-5.87.1.tgz +0 -0
  17. package/components/tryghost-donations-5.87.1.tgz +0 -0
  18. package/components/tryghost-dynamic-routing-events-5.87.1.tgz +0 -0
  19. package/components/{tryghost-email-addresses-5.86.2.tgz → tryghost-email-addresses-5.87.1.tgz} +0 -0
  20. package/components/tryghost-email-analytics-provider-mailgun-5.87.1.tgz +0 -0
  21. package/components/tryghost-email-analytics-service-5.87.1.tgz +0 -0
  22. package/components/tryghost-email-content-generator-5.87.1.tgz +0 -0
  23. package/components/{tryghost-email-events-5.86.2.tgz → tryghost-email-events-5.87.1.tgz} +0 -0
  24. package/components/tryghost-email-service-5.87.1.tgz +0 -0
  25. package/components/tryghost-email-suppression-list-5.87.1.tgz +0 -0
  26. package/components/tryghost-express-dynamic-redirects-5.87.1.tgz +0 -0
  27. package/components/tryghost-external-media-inliner-5.87.1.tgz +0 -0
  28. package/components/tryghost-extract-api-key-5.87.1.tgz +0 -0
  29. package/components/tryghost-ghost-5.87.1.tgz +0 -0
  30. package/components/tryghost-html-to-plaintext-5.87.1.tgz +0 -0
  31. package/components/tryghost-i18n-5.87.1.tgz +0 -0
  32. package/components/tryghost-importer-handler-content-files-5.87.1.tgz +0 -0
  33. package/components/tryghost-importer-revue-5.87.1.tgz +0 -0
  34. package/components/tryghost-in-memory-repository-5.87.1.tgz +0 -0
  35. package/components/{tryghost-job-manager-5.86.2.tgz → tryghost-job-manager-5.87.1.tgz} +0 -0
  36. package/components/tryghost-link-redirects-5.87.1.tgz +0 -0
  37. package/components/tryghost-link-replacer-5.87.1.tgz +0 -0
  38. package/components/tryghost-link-tracking-5.87.1.tgz +0 -0
  39. package/components/tryghost-magic-link-5.87.1.tgz +0 -0
  40. package/components/{tryghost-mail-events-5.86.2.tgz → tryghost-mail-events-5.87.1.tgz} +0 -0
  41. package/components/{tryghost-mailgun-client-5.86.2.tgz → tryghost-mailgun-client-5.87.1.tgz} +0 -0
  42. package/components/tryghost-member-attribution-5.87.1.tgz +0 -0
  43. package/components/{tryghost-member-events-5.86.2.tgz → tryghost-member-events-5.87.1.tgz} +0 -0
  44. package/components/tryghost-members-api-5.87.1.tgz +0 -0
  45. package/components/{tryghost-members-csv-5.86.2.tgz → tryghost-members-csv-5.87.1.tgz} +0 -0
  46. package/components/tryghost-members-events-service-5.87.1.tgz +0 -0
  47. package/components/tryghost-members-importer-5.87.1.tgz +0 -0
  48. package/components/{tryghost-members-offers-5.86.2.tgz → tryghost-members-offers-5.87.1.tgz} +0 -0
  49. package/components/tryghost-members-payments-5.87.1.tgz +0 -0
  50. package/components/tryghost-members-ssr-5.87.1.tgz +0 -0
  51. package/components/tryghost-members-stripe-service-5.87.1.tgz +0 -0
  52. package/components/tryghost-mentions-email-report-5.87.1.tgz +0 -0
  53. package/components/tryghost-milestones-5.87.1.tgz +0 -0
  54. package/components/tryghost-minifier-5.87.1.tgz +0 -0
  55. package/components/tryghost-model-to-domain-event-interceptor-5.87.1.tgz +0 -0
  56. package/components/tryghost-mw-api-version-mismatch-5.87.1.tgz +0 -0
  57. package/components/tryghost-mw-cache-control-5.87.1.tgz +0 -0
  58. package/components/tryghost-mw-error-handler-5.87.1.tgz +0 -0
  59. package/components/tryghost-mw-session-from-token-5.87.1.tgz +0 -0
  60. package/components/tryghost-mw-update-user-last-seen-5.87.1.tgz +0 -0
  61. package/components/tryghost-mw-version-match-5.87.1.tgz +0 -0
  62. package/components/tryghost-mw-vhost-5.87.1.tgz +0 -0
  63. package/components/tryghost-nql-filter-expansions-5.87.1.tgz +0 -0
  64. package/components/tryghost-oembed-service-5.87.1.tgz +0 -0
  65. package/components/tryghost-package-json-5.87.1.tgz +0 -0
  66. package/components/tryghost-post-events-5.87.1.tgz +0 -0
  67. package/components/tryghost-post-revisions-5.87.1.tgz +0 -0
  68. package/components/tryghost-posts-service-5.87.1.tgz +0 -0
  69. package/components/tryghost-recommendations-5.87.1.tgz +0 -0
  70. package/components/tryghost-referrers-5.87.1.tgz +0 -0
  71. package/components/{tryghost-security-5.86.2.tgz → tryghost-security-5.87.1.tgz} +0 -0
  72. package/components/tryghost-session-service-5.87.1.tgz +0 -0
  73. package/components/tryghost-settings-path-manager-5.87.1.tgz +0 -0
  74. package/components/tryghost-slack-notifications-5.87.1.tgz +0 -0
  75. package/components/tryghost-staff-service-5.87.1.tgz +0 -0
  76. package/components/tryghost-stats-service-5.87.1.tgz +0 -0
  77. package/components/{tryghost-tiers-5.86.2.tgz → tryghost-tiers-5.87.1.tgz} +0 -0
  78. package/components/{tryghost-update-check-service-5.86.2.tgz → tryghost-update-check-service-5.87.1.tgz} +0 -0
  79. package/components/tryghost-verification-trigger-5.87.1.tgz +0 -0
  80. package/components/tryghost-version-notifications-data-service-5.87.1.tgz +0 -0
  81. package/components/tryghost-webmentions-5.87.1.tgz +0 -0
  82. package/content/themes/casper/assets/built/screen.css +1 -1
  83. package/content/themes/casper/assets/built/screen.css.map +1 -1
  84. package/content/themes/casper/assets/css/screen.css +10 -0
  85. package/content/themes/casper/package.json +1 -1
  86. package/content/themes/casper/post.hbs +1 -1
  87. package/content/themes/source/assets/built/screen.css +1 -1
  88. package/content/themes/source/assets/built/screen.css.map +1 -1
  89. package/content/themes/source/assets/css/screen.css +11 -45
  90. package/content/themes/source/default.hbs +3 -0
  91. package/content/themes/source/package.json +1 -1
  92. package/content/themes/source/partials/email-subscription.hbs +1 -1
  93. package/content/themes/source/partials/feature-image.hbs +8 -9
  94. package/content/themes/source/partials/typography/fonts.hbs +15 -0
  95. package/content/themes/source/partials/typography/mono.hbs +21 -0
  96. package/content/themes/source/partials/typography/sans.hbs +11 -0
  97. package/content/themes/source/partials/typography/serif.hbs +21 -0
  98. package/content/themes/source/post.hbs +2 -2
  99. package/core/boot.js +0 -4
  100. package/core/built/admin/assets/admin-x-activitypub/admin-x-activitypub.js +3 -3
  101. package/core/built/admin/assets/admin-x-activitypub/index-9a6a8e4b.mjs +18689 -0
  102. package/core/built/admin/assets/admin-x-activitypub/modals-5aad7e41.mjs +516 -0
  103. package/core/built/admin/assets/admin-x-demo/admin-x-demo.js +1 -1
  104. package/core/built/admin/assets/admin-x-demo/index-f1fae1e6.mjs +12341 -0
  105. package/core/built/admin/assets/admin-x-demo/{modals-0790023d.mjs → modals-344029a3.mjs} +109 -108
  106. package/core/built/admin/assets/admin-x-settings/{CodeEditorView-7dd72fff.mjs → CodeEditorView-1a93227f.mjs} +2 -2
  107. package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +1 -1
  108. package/core/built/admin/assets/admin-x-settings/{index-3b15dfb3.mjs → index-1caa03f1.mjs} +2 -2
  109. package/core/built/admin/assets/admin-x-settings/{index-8b8bf7d6.mjs → index-bb355172.mjs} +14004 -10340
  110. package/core/built/admin/assets/admin-x-settings/{modals-71f5a60d.mjs → modals-f496bf28.mjs} +10881 -14500
  111. package/core/built/admin/assets/{chunk.216.1641331b33471771559d.js → chunk.42.167fc5e3f3a1c1088f2e.js} +2032 -2307
  112. package/core/built/admin/assets/{chunk.216.1641331b33471771559d.js.LICENSE.txt → chunk.42.167fc5e3f3a1c1088f2e.js.LICENSE.txt} +0 -43
  113. package/core/built/admin/assets/{chunk.524.6932df81384274864737.js → chunk.524.a032fbf6d6bbe20b0eb3.js} +5 -5
  114. package/core/built/admin/assets/{chunk.582.8f5385ac30ddd4826b66.js → chunk.582.bc65953e4022c385c144.js} +11 -11
  115. package/core/built/admin/assets/{ghost-cc7512accd98e0fa3cc0906c52204a55.js → ghost-b645099f33022aa37d96a2be8d8ddad1.js} +115 -130
  116. package/core/built/admin/assets/ghost-cc31d867156dbb76ec96cdd93bd39d36.css +1 -0
  117. package/core/built/admin/assets/ghost-dark-69968977cce01f9101da418724176290.css +1 -0
  118. package/core/built/admin/assets/koenig-lexical/index.css +1 -1
  119. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +30259 -29018
  120. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +167 -182
  121. package/core/built/admin/assets/{vendor-232fd88c6ffbd896b34c449112793e93.js → vendor-4e0f92ca2b1c0850606b912c70852e32.js} +505 -929
  122. package/core/built/admin/index.html +6 -6
  123. package/core/frontend/helpers/get.js +7 -5
  124. package/core/frontend/src/cards/css/bookmark.css +2 -0
  125. package/core/server/api/endpoints/utils/serializers/input/pages.js +32 -1
  126. package/core/server/api/endpoints/utils/serializers/input/posts.js +2 -2
  127. package/core/server/api/endpoints/utils/serializers/output/authentication.js +1 -1
  128. package/core/server/data/migrations/versions/5.87/2024-06-25-12-08-20-add-posts-tags-post-tag-index.js +26 -0
  129. package/core/server/data/migrations/versions/5.87/2024-06-25-12-08-45-add-posts-type-status-updated-at-index.js +4 -0
  130. package/core/server/data/schema/schema.js +7 -1
  131. package/core/server/models/base/plugins/crud.js +5 -0
  132. package/core/server/services/custom-redirects/validation.js +21 -3
  133. package/core/server/services/webhooks/WebhookTrigger.js +2 -1
  134. package/core/server/web/parent/app.js +1 -1
  135. package/core/shared/labs.js +0 -3
  136. package/package.json +158 -160
  137. package/yarn.lock +625 -892
  138. package/components/tryghost-adapter-cache-memory-ttl-5.86.2.tgz +0 -0
  139. package/components/tryghost-adapter-manager-5.86.2.tgz +0 -0
  140. package/components/tryghost-announcement-bar-settings-5.86.2.tgz +0 -0
  141. package/components/tryghost-api-version-compatibility-service-5.86.2.tgz +0 -0
  142. package/components/tryghost-audience-feedback-5.86.2.tgz +0 -0
  143. package/components/tryghost-bookshelf-repository-5.86.2.tgz +0 -0
  144. package/components/tryghost-bootstrap-socket-5.86.2.tgz +0 -0
  145. package/components/tryghost-collections-5.86.2.tgz +0 -0
  146. package/components/tryghost-domain-events-5.86.2.tgz +0 -0
  147. package/components/tryghost-donations-5.86.2.tgz +0 -0
  148. package/components/tryghost-dynamic-routing-events-5.86.2.tgz +0 -0
  149. package/components/tryghost-email-analytics-provider-mailgun-5.86.2.tgz +0 -0
  150. package/components/tryghost-email-analytics-service-5.86.2.tgz +0 -0
  151. package/components/tryghost-email-content-generator-5.86.2.tgz +0 -0
  152. package/components/tryghost-email-service-5.86.2.tgz +0 -0
  153. package/components/tryghost-email-suppression-list-5.86.2.tgz +0 -0
  154. package/components/tryghost-express-dynamic-redirects-5.86.2.tgz +0 -0
  155. package/components/tryghost-external-media-inliner-5.86.2.tgz +0 -0
  156. package/components/tryghost-extract-api-key-5.86.2.tgz +0 -0
  157. package/components/tryghost-ghost-5.86.2.tgz +0 -0
  158. package/components/tryghost-html-to-plaintext-5.86.2.tgz +0 -0
  159. package/components/tryghost-i18n-5.86.2.tgz +0 -0
  160. package/components/tryghost-importer-handler-content-files-5.86.2.tgz +0 -0
  161. package/components/tryghost-importer-revue-5.86.2.tgz +0 -0
  162. package/components/tryghost-in-memory-repository-5.86.2.tgz +0 -0
  163. package/components/tryghost-link-redirects-5.86.2.tgz +0 -0
  164. package/components/tryghost-link-replacer-5.86.2.tgz +0 -0
  165. package/components/tryghost-link-tracking-5.86.2.tgz +0 -0
  166. package/components/tryghost-magic-link-5.86.2.tgz +0 -0
  167. package/components/tryghost-member-attribution-5.86.2.tgz +0 -0
  168. package/components/tryghost-members-api-5.86.2.tgz +0 -0
  169. package/components/tryghost-members-events-service-5.86.2.tgz +0 -0
  170. package/components/tryghost-members-importer-5.86.2.tgz +0 -0
  171. package/components/tryghost-members-payments-5.86.2.tgz +0 -0
  172. package/components/tryghost-members-ssr-5.86.2.tgz +0 -0
  173. package/components/tryghost-members-stripe-service-5.86.2.tgz +0 -0
  174. package/components/tryghost-mentions-email-report-5.86.2.tgz +0 -0
  175. package/components/tryghost-milestones-5.86.2.tgz +0 -0
  176. package/components/tryghost-minifier-5.86.2.tgz +0 -0
  177. package/components/tryghost-model-to-domain-event-interceptor-5.86.2.tgz +0 -0
  178. package/components/tryghost-mw-api-version-mismatch-5.86.2.tgz +0 -0
  179. package/components/tryghost-mw-cache-control-5.86.2.tgz +0 -0
  180. package/components/tryghost-mw-error-handler-5.86.2.tgz +0 -0
  181. package/components/tryghost-mw-session-from-token-5.86.2.tgz +0 -0
  182. package/components/tryghost-mw-update-user-last-seen-5.86.2.tgz +0 -0
  183. package/components/tryghost-mw-version-match-5.86.2.tgz +0 -0
  184. package/components/tryghost-mw-vhost-5.86.2.tgz +0 -0
  185. package/components/tryghost-nql-filter-expansions-5.86.2.tgz +0 -0
  186. package/components/tryghost-oembed-service-5.86.2.tgz +0 -0
  187. package/components/tryghost-package-json-5.86.2.tgz +0 -0
  188. package/components/tryghost-post-events-5.86.2.tgz +0 -0
  189. package/components/tryghost-post-revisions-5.86.2.tgz +0 -0
  190. package/components/tryghost-posts-service-5.86.2.tgz +0 -0
  191. package/components/tryghost-recommendations-5.86.2.tgz +0 -0
  192. package/components/tryghost-referrers-5.86.2.tgz +0 -0
  193. package/components/tryghost-session-service-5.86.2.tgz +0 -0
  194. package/components/tryghost-settings-path-manager-5.86.2.tgz +0 -0
  195. package/components/tryghost-slack-notifications-5.86.2.tgz +0 -0
  196. package/components/tryghost-staff-service-5.86.2.tgz +0 -0
  197. package/components/tryghost-stats-service-5.86.2.tgz +0 -0
  198. package/components/tryghost-verification-trigger-5.86.2.tgz +0 -0
  199. package/components/tryghost-version-notifications-data-service-5.86.2.tgz +0 -0
  200. package/components/tryghost-webmentions-5.86.2.tgz +0 -0
  201. package/core/built/admin/assets/admin-x-activitypub/index-8aaa062c.mjs +0 -14980
  202. package/core/built/admin/assets/admin-x-activitypub/modals-124e649f.mjs +0 -521
  203. package/core/built/admin/assets/admin-x-demo/index-ea257d67.mjs +0 -8664
  204. package/core/built/admin/assets/ghost-117facae643a21dde076079b84fce471.css +0 -1
  205. package/core/built/admin/assets/ghost-dark-031957661056b00048f03aac0618c480.css +0 -1
  206. package/core/server/services/websockets/index.js +0 -1
  207. package/core/server/services/websockets/service.js +0 -38
@@ -8,7 +8,7 @@
8
8
  <title>Ghost Admin</title>
9
9
 
10
10
 
11
- <meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22cdnUrl%22%3A%22%22%2C%22editorUrl%22%3A%22%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.86%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22ember-websockets%22%3A%7B%22socketIO%22%3Atrue%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%2C%22editorFilename%22%3A%22koenig-lexical.umd.js%22%2C%22editorHash%22%3A%2262f98e1b33%22%2C%22adminXDemoFilename%22%3A%22admin-x-demo.js%22%2C%22adminXDemoHash%22%3A%224245030234%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%226b8583f4e9%22%2C%22adminXActivitypubFilename%22%3A%22admin-x-activitypub.js%22%2C%22adminXActivitypubHash%22%3A%22f6cd11e49b%22%7D" />
11
+ <meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22cdnUrl%22%3A%22%22%2C%22editorUrl%22%3A%22%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.87%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%2C%22editorFilename%22%3A%22koenig-lexical.umd.js%22%2C%22editorHash%22%3A%2247bfbf88f0%22%2C%22adminXDemoFilename%22%3A%22admin-x-demo.js%22%2C%22adminXDemoHash%22%3A%229c49d06c68%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%2236ec618662%22%2C%22adminXActivitypubFilename%22%3A%22admin-x-activitypub.js%22%2C%22adminXActivitypubHash%22%3A%22b147b1abae%22%7D" />
12
12
 
13
13
  <meta name="HandheldFriendly" content="True" />
14
14
  <meta name="MobileOptimized" content="320" />
@@ -37,7 +37,7 @@
37
37
  </style>
38
38
 
39
39
  <link integrity="" rel="stylesheet" href="assets/vendor-0ede59da8efb5e28fa929557f7ff7154.css">
40
- <link integrity="" rel="stylesheet" href="assets/ghost-117facae643a21dde076079b84fce471.css" title="light">
40
+ <link integrity="" rel="stylesheet" href="assets/ghost-cc31d867156dbb76ec96cdd93bd39d36.css" title="light">
41
41
 
42
42
 
43
43
  </head>
@@ -56,9 +56,9 @@
56
56
 
57
57
  <div id="ember-basic-dropdown-wormhole"></div>
58
58
 
59
- <script src="assets/vendor-232fd88c6ffbd896b34c449112793e93.js"></script>
60
- <script src="assets/chunk.216.1641331b33471771559d.js"></script>
61
- <script src="assets/chunk.524.6932df81384274864737.js"></script>
62
- <script src="assets/ghost-cc7512accd98e0fa3cc0906c52204a55.js"></script>
59
+ <script src="assets/vendor-4e0f92ca2b1c0850606b912c70852e32.js"></script>
60
+ <script src="assets/chunk.42.167fc5e3f3a1c1088f2e.js"></script>
61
+ <script src="assets/chunk.524.a032fbf6d6bbe20b0eb3.js"></script>
62
+ <script src="assets/ghost-b645099f33022aa37d96a2be8d8ddad1.js"></script>
63
63
  </body>
64
64
  </html>
@@ -299,7 +299,7 @@ module.exports = async function get(resource, options) {
299
299
  try {
300
300
  const spanName = `{{#get "${resource}"${apiOptionsString}}} ${data.member ? 'member' : 'public'}`;
301
301
  const result = await Sentry.startSpan({
302
- op: 'frontend.helpers.get',
302
+ op: 'frontend.helpers.get',
303
303
  name: spanName,
304
304
  tags: {
305
305
  resource,
@@ -313,11 +313,11 @@ module.exports = async function get(resource, options) {
313
313
  if (response[resource] && response[resource].length) {
314
314
  response[resource].forEach(prepareContextResource);
315
315
  }
316
-
316
+
317
317
  // used for logging details of slow requests
318
318
  returnedRowsCount = response[resource] && response[resource].length;
319
319
  span?.setTag('returnedRows', returnedRowsCount);
320
-
320
+
321
321
  // block params allows the theme developer to name the data using something like
322
322
  // `{{#get "posts" as |result pageInfo|}}`
323
323
  const blockParams = [response[resource]];
@@ -325,7 +325,7 @@ module.exports = async function get(resource, options) {
325
325
  response.pagination = response.meta.pagination;
326
326
  blockParams.push(response.meta.pagination);
327
327
  }
328
-
328
+
329
329
  // Call the main template function
330
330
  const rendered = options.fn(response, {
331
331
  data: data,
@@ -357,7 +357,9 @@ module.exports = async function get(resource, options) {
357
357
  apiOptions,
358
358
  returnedRows: returnedRowsCount
359
359
  }
360
- }));
360
+ }), {
361
+ time: totalMs
362
+ });
361
363
  }
362
364
  }
363
365
  }
@@ -12,6 +12,7 @@
12
12
  .kg-bookmark-card a.kg-bookmark-container,
13
13
  .kg-bookmark-card a.kg-bookmark-container:hover {
14
14
  display: flex;
15
+ background: #fff;
15
16
  text-decoration: none;
16
17
  border-radius: 6px;
17
18
  border: 1px solid rgb(124 139 154 / 25%);
@@ -28,6 +29,7 @@
28
29
  justify-content: flex-start;
29
30
  padding: 20px;
30
31
  overflow: hidden;
32
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
31
33
  }
32
34
 
33
35
  .kg-bookmark-title {
@@ -7,6 +7,7 @@ const slugFilterOrder = require('./utils/slug-filter-order');
7
7
  const localUtils = require('../../index');
8
8
  const mobiledoc = require('../../../../../lib/mobiledoc');
9
9
  const postsMetaSchema = require('../../../../../data/schema').tables.posts_meta;
10
+ const postsSchema = require('../../../../../data/schema').tables.posts;
10
11
  const clean = require('./utils/clean');
11
12
  const lexical = require('../../../../../lib/lexical');
12
13
  const sentry = require('../../../../../../shared/sentry');
@@ -24,6 +25,33 @@ function removeSourceFormats(frame) {
24
25
  }
25
26
  }
26
27
 
28
+ /**
29
+ * Selects all allowed columns for the given frame.
30
+ *
31
+ * This removes the lexical and mobiledoc columns from the query. This is a performance improvement as we never intend
32
+ * to expose those columns in the content API and they are very large datasets to be passing around and de/serializing.
33
+ *
34
+ * NOTE: This is only intended for the Content API. We need these fields within Admin API responses.
35
+ *
36
+ * @param {Object} frame - The frame object.
37
+ */
38
+ function selectAllAllowedColumns(frame) {
39
+ if (!frame.options.columns && !frame.options.selectRaw) {
40
+ // Because we're returning columns directly from the schema we need to remove info columns like @@UNIQUE_CONSTRAINTS@@ and @@INDEXES@@
41
+ frame.options.selectRaw = _.keys(_.omit(postsSchema, ['lexical','mobiledoc','@@INDEXES@@','@@UNIQUE_CONSTRAINTS@@'])).join(',');
42
+ } else if (frame.options.columns) {
43
+ frame.options.columns = frame.options.columns.filter((column) => {
44
+ return !['mobiledoc', 'lexical'].includes(column);
45
+ });
46
+ } else if (frame.options.selectRaw) {
47
+ frame.options.selectRaw = frame.options.selectRaw.split(',').map((column) => {
48
+ return column.trim();
49
+ }).filter((column) => {
50
+ return !['mobiledoc', 'lexical'].includes(column);
51
+ }).join(',');
52
+ }
53
+ }
54
+
27
55
  function defaultRelations(frame) {
28
56
  if (frame.options.withRelated) {
29
57
  return;
@@ -97,7 +125,10 @@ module.exports = {
97
125
  forcePageFilter(frame);
98
126
 
99
127
  if (localUtils.isContentAPI(frame)) {
100
- removeSourceFormats(frame);
128
+ // CASE: the content api endpoint for posts should not return mobiledoc or lexical
129
+ removeSourceFormats(frame); // remove from the format field
130
+ selectAllAllowedColumns(frame); // remove from any specified column or selectRaw options
131
+
101
132
  setDefaultOrder(frame);
102
133
  forceVisibilityColumn(frame);
103
134
  }
@@ -47,8 +47,8 @@ function removeSourceFormats(frame) {
47
47
  */
48
48
  function selectAllAllowedColumns(frame) {
49
49
  if (!frame.options.columns && !frame.options.selectRaw) {
50
- // Because we're returning columns directly from the table we need to remove info columns like @@UNIQUE_CONSTRAINTS@@
51
- frame.options.selectRaw = _.keys(_.omit(postsSchema, ['lexical','mobiledoc','@@UNIQUE_CONSTRAINTS@@'])).join(',');
50
+ // Because we're returning columns directly from the schema we need to remove info columns like @@UNIQUE_CONSTRAINTS@@ and @@INDEXES@@
51
+ frame.options.selectRaw = _.keys(_.omit(postsSchema, ['lexical','mobiledoc','@@INDEXES@@','@@UNIQUE_CONSTRAINTS@@'])).join(',');
52
52
  } else if (frame.options.columns) {
53
53
  frame.options.columns = frame.options.columns.filter((column) => {
54
54
  return !['mobiledoc', 'lexical'].includes(column);
@@ -4,7 +4,7 @@ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output
4
4
 
5
5
  const messages = {
6
6
  checkEmailForInstructions: 'Check your email for further instructions.',
7
- passwordChanged: 'Password changed successfully.',
7
+ passwordChanged: 'Password updated',
8
8
  invitationAccepted: 'Invitation accepted.'
9
9
  };
10
10
 
@@ -0,0 +1,26 @@
1
+ const logging = require('@tryghost/logging');
2
+ const {createNonTransactionalMigration} = require('../../utils');
3
+ const {addIndex, dropIndex} = require('../../../schema/commands');
4
+
5
+ module.exports = createNonTransactionalMigration(
6
+ async function up(knex) {
7
+ await addIndex('posts_tags', ['post_id', 'tag_id'], knex);
8
+ },
9
+ async function down(knex) {
10
+ try {
11
+ await dropIndex('posts_tags', ['post_id', 'tag_id'], knex);
12
+ } catch (err) {
13
+ if (err.code === 'ER_DROP_INDEX_FK') {
14
+ logging.error({
15
+ message: 'Error dropping index over posts_tags(post_id, tag_id), re-adding index for post_id'
16
+ });
17
+
18
+ await addIndex('posts_tags', ['post_id'], knex);
19
+ await dropIndex('posts_tags', ['post_id', 'tag_id'], knex);
20
+ return;
21
+ }
22
+
23
+ throw err;
24
+ }
25
+ }
26
+ );
@@ -0,0 +1,4 @@
1
+ // For information on writing migrations, see https://www.notion.so/ghost/Database-migrations-eb5b78c435d741d2b34a582d57c24253
2
+ const {createAddIndexMigration} = require('../../utils');
3
+
4
+ module.exports = createAddIndexMigration('posts',['type','status','updated_at']);
@@ -93,6 +93,9 @@ module.exports = {
93
93
  canonical_url: {type: 'text', maxlength: 2000, nullable: true},
94
94
  newsletter_id: {type: 'string', maxlength: 24, nullable: true, references: 'newsletters.id'},
95
95
  show_title_and_feature_image: {type: 'boolean', nullable: false, defaultTo: true},
96
+ '@@INDEXES@@': [
97
+ ['type','status','updated_at']
98
+ ],
96
99
  '@@UNIQUE_CONSTRAINTS@@': [
97
100
  ['slug', 'type']
98
101
  ]
@@ -295,7 +298,10 @@ module.exports = {
295
298
  id: {type: 'string', maxlength: 24, nullable: false, primary: true},
296
299
  post_id: {type: 'string', maxlength: 24, nullable: false, references: 'posts.id'},
297
300
  tag_id: {type: 'string', maxlength: 24, nullable: false, references: 'tags.id'},
298
- sort_order: {type: 'integer', nullable: false, unsigned: true, defaultTo: 0}
301
+ sort_order: {type: 'integer', nullable: false, unsigned: true, defaultTo: 0},
302
+ '@@INDEXES@@': [
303
+ ['post_id','tag_id']
304
+ ]
299
305
  },
300
306
  invites: {
301
307
  id: {type: 'string', maxlength: 24, nullable: false, primary: true},
@@ -120,6 +120,11 @@ module.exports = function (Bookshelf) {
120
120
  });
121
121
  }
122
122
 
123
+ //option param to skip distinct from count query, distinct adds a lot of latency and in this case the result set will always be unique.
124
+ if (unfilteredOptions.useBasicCount) {
125
+ options.useBasicCount = unfilteredOptions.useBasicCount;
126
+ }
127
+
123
128
  const response = await itemCollection.fetchPage(options);
124
129
  // Attributes are being filtered here, so they are not leaked into calling layer
125
130
  // where models are serialized to json and do not do more filtering.
@@ -1,6 +1,7 @@
1
1
  const _ = require('lodash');
2
2
  const tpl = require('@tryghost/tpl');
3
3
  const errors = require('@tryghost/errors');
4
+ const {isSafePattern} = require('redos-detector');
4
5
 
5
6
  const messages = {
6
7
  redirectsWrongFormat: 'Incorrect redirects file format.',
@@ -33,18 +34,35 @@ const validate = (redirects) => {
33
34
  if (!redirect.from || !redirect.to) {
34
35
  throw new errors.ValidationError({
35
36
  message: tpl(messages.redirectsWrongFormat),
36
- context: redirect,
37
37
  help: tpl(messages.redirectsHelp)
38
38
  });
39
39
  }
40
40
 
41
+ // Ensure valid regex
41
42
  try {
42
- // each 'from' property should be a valid RegExp string
43
43
  new RegExp(redirect.from);
44
44
  } catch (error) {
45
45
  throw new errors.ValidationError({
46
46
  message: tpl(messages.invalidRedirectsFromRegex),
47
- context: redirect,
47
+ errorDetails: {
48
+ redirect,
49
+ invalid: true
50
+ },
51
+ help: tpl(messages.redirectsHelp)
52
+ });
53
+ }
54
+
55
+ // Ensure safe regex
56
+ const analysis = isSafePattern(redirect.from);
57
+
58
+ if (analysis.safe === false) {
59
+ throw new errors.ValidationError({
60
+ message: tpl(messages.invalidRedirectsFromRegex),
61
+ errorDetails: {
62
+ redirect,
63
+ unsafe: true,
64
+ reason: analysis.error
65
+ },
48
66
  help: tpl(messages.redirectsHelp)
49
67
  });
50
68
  }
@@ -87,6 +87,7 @@ class WebhookTrigger {
87
87
  const reqPayload = JSON.stringify(hookPayload);
88
88
  const url = webhook.get('target_url');
89
89
  const secret = webhook.get('secret') || '';
90
+ const ts = Date.now();
90
91
 
91
92
  const headers = {
92
93
  'Content-Length': Buffer.byteLength(reqPayload),
@@ -95,7 +96,7 @@ class WebhookTrigger {
95
96
  };
96
97
 
97
98
  if (secret !== '') {
98
- headers['X-Ghost-Signature'] = `sha256=${crypto.createHmac('sha256', secret).update(reqPayload).digest('hex')}, t=${Date.now()}`;
99
+ headers['X-Ghost-Signature'] = `sha256=${crypto.createHmac('sha256', secret).update(`${reqPayload}${ts}`).digest('hex')}, t=${ts}`;
99
100
  }
100
101
 
101
102
  const opts = {
@@ -29,7 +29,7 @@ module.exports = function setupParentApp() {
29
29
  // Enable request queuing if configured
30
30
  const queueConfig = config.get('optimization:requestQueue');
31
31
 
32
- if (queueConfig?.enabled === true) {
32
+ if (queueConfig) {
33
33
  parentApp.use(mw.queueRequest(queueConfig));
34
34
  }
35
35
 
@@ -24,8 +24,6 @@ const GA_FEATURES = [
24
24
  'listUnsubscribeHeader',
25
25
  'filterEmailDisabled',
26
26
  'newEmailAddresses',
27
- 'portalImprovements',
28
- 'newsletterExcerpt',
29
27
  'internalLinking'
30
28
  ];
31
29
 
@@ -45,7 +43,6 @@ const ALPHA_FEATURES = [
45
43
  'NestPlayground',
46
44
  'urlCache',
47
45
  'lexicalMultiplayer',
48
- 'websockets',
49
46
  'emailCustomization',
50
47
  'mailEvents',
51
48
  'collectionsCard',