ghost 5.74.5 → 5.75.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 (157) hide show
  1. package/components/tryghost-adapter-cache-memory-ttl-5.75.0.tgz +0 -0
  2. package/components/tryghost-adapter-cache-redis-5.75.0.tgz +0 -0
  3. package/components/{tryghost-adapter-manager-5.74.5.tgz → tryghost-adapter-manager-5.75.0.tgz} +0 -0
  4. package/components/tryghost-announcement-bar-settings-5.75.0.tgz +0 -0
  5. package/components/{tryghost-api-framework-5.74.5.tgz → tryghost-api-framework-5.75.0.tgz} +0 -0
  6. package/components/{tryghost-api-version-compatibility-service-5.74.5.tgz → tryghost-api-version-compatibility-service-5.75.0.tgz} +0 -0
  7. package/components/{tryghost-audience-feedback-5.74.5.tgz → tryghost-audience-feedback-5.75.0.tgz} +0 -0
  8. package/components/tryghost-bookshelf-repository-5.75.0.tgz +0 -0
  9. package/components/{tryghost-bootstrap-socket-5.74.5.tgz → tryghost-bootstrap-socket-5.75.0.tgz} +0 -0
  10. package/components/tryghost-collections-5.75.0.tgz +0 -0
  11. package/components/tryghost-constants-5.75.0.tgz +0 -0
  12. package/components/{tryghost-custom-theme-settings-service-5.74.5.tgz → tryghost-custom-theme-settings-service-5.75.0.tgz} +0 -0
  13. package/components/{tryghost-data-generator-5.74.5.tgz → tryghost-data-generator-5.75.0.tgz} +0 -0
  14. package/components/tryghost-domain-events-5.75.0.tgz +0 -0
  15. package/components/tryghost-donations-5.75.0.tgz +0 -0
  16. package/components/tryghost-dynamic-routing-events-5.75.0.tgz +0 -0
  17. package/components/tryghost-email-addresses-5.75.0.tgz +0 -0
  18. package/components/tryghost-email-analytics-provider-mailgun-5.75.0.tgz +0 -0
  19. package/components/tryghost-email-analytics-service-5.75.0.tgz +0 -0
  20. package/components/tryghost-email-content-generator-5.75.0.tgz +0 -0
  21. package/components/{tryghost-email-events-5.74.5.tgz → tryghost-email-events-5.75.0.tgz} +0 -0
  22. package/components/tryghost-email-service-5.75.0.tgz +0 -0
  23. package/components/tryghost-email-suppression-list-5.75.0.tgz +0 -0
  24. package/components/tryghost-event-aware-cache-wrapper-5.75.0.tgz +0 -0
  25. package/components/tryghost-express-dynamic-redirects-5.75.0.tgz +0 -0
  26. package/components/tryghost-external-media-inliner-5.75.0.tgz +0 -0
  27. package/components/{tryghost-extract-api-key-5.74.5.tgz → tryghost-extract-api-key-5.75.0.tgz} +0 -0
  28. package/components/tryghost-html-to-plaintext-5.75.0.tgz +0 -0
  29. package/components/tryghost-i18n-5.75.0.tgz +0 -0
  30. package/components/{tryghost-importer-handler-content-files-5.74.5.tgz → tryghost-importer-handler-content-files-5.75.0.tgz} +0 -0
  31. package/components/{tryghost-importer-revue-5.74.5.tgz → tryghost-importer-revue-5.75.0.tgz} +0 -0
  32. package/components/tryghost-in-memory-repository-5.75.0.tgz +0 -0
  33. package/components/{tryghost-job-manager-5.74.5.tgz → tryghost-job-manager-5.75.0.tgz} +0 -0
  34. package/components/tryghost-link-redirects-5.75.0.tgz +0 -0
  35. package/components/{tryghost-link-replacer-5.74.5.tgz → tryghost-link-replacer-5.75.0.tgz} +0 -0
  36. package/components/{tryghost-link-tracking-5.74.5.tgz → tryghost-link-tracking-5.75.0.tgz} +0 -0
  37. package/components/{tryghost-magic-link-5.74.5.tgz → tryghost-magic-link-5.75.0.tgz} +0 -0
  38. package/components/{tryghost-mail-events-5.74.5.tgz → tryghost-mail-events-5.75.0.tgz} +0 -0
  39. package/components/{tryghost-mailgun-client-5.74.5.tgz → tryghost-mailgun-client-5.75.0.tgz} +0 -0
  40. package/components/{tryghost-member-attribution-5.74.5.tgz → tryghost-member-attribution-5.75.0.tgz} +0 -0
  41. package/components/{tryghost-member-events-5.74.5.tgz → tryghost-member-events-5.75.0.tgz} +0 -0
  42. package/components/{tryghost-members-api-5.74.5.tgz → tryghost-members-api-5.75.0.tgz} +0 -0
  43. package/components/tryghost-members-csv-5.75.0.tgz +0 -0
  44. package/components/{tryghost-members-events-service-5.74.5.tgz → tryghost-members-events-service-5.75.0.tgz} +0 -0
  45. package/components/{tryghost-members-importer-5.74.5.tgz → tryghost-members-importer-5.75.0.tgz} +0 -0
  46. package/components/tryghost-members-offers-5.75.0.tgz +0 -0
  47. package/components/tryghost-members-payments-5.75.0.tgz +0 -0
  48. package/components/{tryghost-members-ssr-5.74.5.tgz → tryghost-members-ssr-5.75.0.tgz} +0 -0
  49. package/components/{tryghost-members-stripe-service-5.74.5.tgz → tryghost-members-stripe-service-5.75.0.tgz} +0 -0
  50. package/components/tryghost-mentions-email-report-5.75.0.tgz +0 -0
  51. package/components/{tryghost-milestones-5.74.5.tgz → tryghost-milestones-5.75.0.tgz} +0 -0
  52. package/components/{tryghost-minifier-5.74.5.tgz → tryghost-minifier-5.75.0.tgz} +0 -0
  53. package/components/tryghost-model-to-domain-event-interceptor-5.75.0.tgz +0 -0
  54. package/components/tryghost-mw-api-version-mismatch-5.75.0.tgz +0 -0
  55. package/components/tryghost-mw-cache-control-5.75.0.tgz +0 -0
  56. package/components/{tryghost-mw-error-handler-5.74.5.tgz → tryghost-mw-error-handler-5.75.0.tgz} +0 -0
  57. package/components/{tryghost-mw-session-from-token-5.74.5.tgz → tryghost-mw-session-from-token-5.75.0.tgz} +0 -0
  58. package/components/tryghost-mw-update-user-last-seen-5.75.0.tgz +0 -0
  59. package/components/tryghost-mw-version-match-5.75.0.tgz +0 -0
  60. package/components/tryghost-mw-vhost-5.75.0.tgz +0 -0
  61. package/components/tryghost-nql-filter-expansions-5.75.0.tgz +0 -0
  62. package/components/tryghost-oembed-service-5.75.0.tgz +0 -0
  63. package/components/tryghost-package-json-5.75.0.tgz +0 -0
  64. package/components/tryghost-post-events-5.75.0.tgz +0 -0
  65. package/components/tryghost-post-revisions-5.75.0.tgz +0 -0
  66. package/components/tryghost-posts-service-5.75.0.tgz +0 -0
  67. package/components/tryghost-recommendations-5.75.0.tgz +0 -0
  68. package/components/tryghost-referrers-5.75.0.tgz +0 -0
  69. package/components/{tryghost-security-5.74.5.tgz → tryghost-security-5.75.0.tgz} +0 -0
  70. package/components/{tryghost-session-service-5.74.5.tgz → tryghost-session-service-5.75.0.tgz} +0 -0
  71. package/components/tryghost-settings-path-manager-5.75.0.tgz +0 -0
  72. package/components/tryghost-slack-notifications-5.75.0.tgz +0 -0
  73. package/components/{tryghost-staff-service-5.74.5.tgz → tryghost-staff-service-5.75.0.tgz} +0 -0
  74. package/components/tryghost-stats-service-5.75.0.tgz +0 -0
  75. package/components/tryghost-tiers-5.75.0.tgz +0 -0
  76. package/components/{tryghost-update-check-service-5.74.5.tgz → tryghost-update-check-service-5.75.0.tgz} +0 -0
  77. package/components/{tryghost-verification-trigger-5.74.5.tgz → tryghost-verification-trigger-5.75.0.tgz} +0 -0
  78. package/components/tryghost-version-notifications-data-service-5.75.0.tgz +0 -0
  79. package/components/{tryghost-webmentions-5.74.5.tgz → tryghost-webmentions-5.75.0.tgz} +0 -0
  80. package/content/themes/source/assets/built/screen.css +1 -1
  81. package/content/themes/source/assets/built/screen.css.map +1 -1
  82. package/content/themes/source/assets/css/screen.css +5 -5
  83. package/content/themes/source/package.json +1 -1
  84. package/content/themes/source/partials/components/post-list.hbs +1 -1
  85. package/core/built/admin/assets/admin-x-demo/admin-x-demo.js +2 -2
  86. package/core/built/admin/assets/admin-x-demo/{index-2fa5a3c2.mjs → index-46cd6bae.mjs} +2224 -2147
  87. package/core/built/admin/assets/admin-x-demo/{modals-10ef986a.mjs → modals-e3fd0bee.mjs} +3 -3
  88. package/core/built/admin/assets/admin-x-settings/{CodeEditorView-b41ea5f8.mjs → CodeEditorView-3275fab6.mjs} +2 -2
  89. package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +2 -2
  90. package/core/built/admin/assets/admin-x-settings/{index-e5bc288c.mjs → index-02a155fd.mjs} +7077 -7023
  91. package/core/built/admin/assets/admin-x-settings/{index-bc03188e.mjs → index-147f4a79.mjs} +2 -2
  92. package/core/built/admin/assets/admin-x-settings/{index-b8cc4f2e.mjs → index-6cc60dce.mjs} +4 -2
  93. package/core/built/admin/assets/admin-x-settings/{modals-98e015fa.mjs → modals-b9d9ac8e.mjs} +6424 -6393
  94. package/core/built/admin/assets/{chunk.143.2a6618f48157c893c4e3.js → chunk.143.48ba4e0e6f8fd2e11002.js} +5 -5
  95. package/core/built/admin/assets/{chunk.178.96746925976b7fb428bd.js → chunk.178.41fac9c06d1c4c6371dc.js} +4 -4
  96. package/core/built/admin/assets/{chunk.137.0297fba124bc9ba1bbc1.js → chunk.214.611b4f2521fabe34eea8.js} +2848 -2768
  97. package/core/built/admin/assets/{ghost-7d0f91cd17901ac15ce0ae64a3091e2a.js → ghost-ceacd55503e4d34de4b4e7ba2309a6ab.js} +47 -41
  98. package/core/built/admin/assets/koenig-lexical/index.css +1 -1
  99. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +5695 -5643
  100. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +115 -115
  101. package/core/built/admin/index.html +4 -4
  102. package/core/frontend/meta/context-object.js +6 -11
  103. package/core/server/data/migrations/versions/5.75/2023-11-27-15-55-add-members-newsletters-index.js +26 -0
  104. package/core/server/data/schema/schema.js +4 -1
  105. package/core/server/models/newsletter.js +1 -8
  106. package/core/server/services/newsletters/NewslettersService.js +18 -7
  107. package/core/server/services/settings/SettingsBREADService.js +25 -4
  108. package/core/server/services/settings/settings-service.js +3 -1
  109. package/core/shared/settings-cache/public.js +3 -1
  110. package/package.json +153 -153
  111. package/yarn.lock +782 -794
  112. package/components/tryghost-adapter-cache-memory-ttl-5.74.5.tgz +0 -0
  113. package/components/tryghost-adapter-cache-redis-5.74.5.tgz +0 -0
  114. package/components/tryghost-announcement-bar-settings-5.74.5.tgz +0 -0
  115. package/components/tryghost-bookshelf-repository-5.74.5.tgz +0 -0
  116. package/components/tryghost-collections-5.74.5.tgz +0 -0
  117. package/components/tryghost-constants-5.74.5.tgz +0 -0
  118. package/components/tryghost-domain-events-5.74.5.tgz +0 -0
  119. package/components/tryghost-donations-5.74.5.tgz +0 -0
  120. package/components/tryghost-dynamic-routing-events-5.74.5.tgz +0 -0
  121. package/components/tryghost-email-addresses-5.74.5.tgz +0 -0
  122. package/components/tryghost-email-analytics-provider-mailgun-5.74.5.tgz +0 -0
  123. package/components/tryghost-email-analytics-service-5.74.5.tgz +0 -0
  124. package/components/tryghost-email-content-generator-5.74.5.tgz +0 -0
  125. package/components/tryghost-email-service-5.74.5.tgz +0 -0
  126. package/components/tryghost-email-suppression-list-5.74.5.tgz +0 -0
  127. package/components/tryghost-event-aware-cache-wrapper-5.74.5.tgz +0 -0
  128. package/components/tryghost-express-dynamic-redirects-5.74.5.tgz +0 -0
  129. package/components/tryghost-external-media-inliner-5.74.5.tgz +0 -0
  130. package/components/tryghost-html-to-plaintext-5.74.5.tgz +0 -0
  131. package/components/tryghost-i18n-5.74.5.tgz +0 -0
  132. package/components/tryghost-in-memory-repository-5.74.5.tgz +0 -0
  133. package/components/tryghost-link-redirects-5.74.5.tgz +0 -0
  134. package/components/tryghost-members-csv-5.74.5.tgz +0 -0
  135. package/components/tryghost-members-offers-5.74.5.tgz +0 -0
  136. package/components/tryghost-members-payments-5.74.5.tgz +0 -0
  137. package/components/tryghost-mentions-email-report-5.74.5.tgz +0 -0
  138. package/components/tryghost-model-to-domain-event-interceptor-5.74.5.tgz +0 -0
  139. package/components/tryghost-mw-api-version-mismatch-5.74.5.tgz +0 -0
  140. package/components/tryghost-mw-cache-control-5.74.5.tgz +0 -0
  141. package/components/tryghost-mw-update-user-last-seen-5.74.5.tgz +0 -0
  142. package/components/tryghost-mw-version-match-5.74.5.tgz +0 -0
  143. package/components/tryghost-mw-vhost-5.74.5.tgz +0 -0
  144. package/components/tryghost-nql-filter-expansions-5.74.5.tgz +0 -0
  145. package/components/tryghost-oembed-service-5.74.5.tgz +0 -0
  146. package/components/tryghost-package-json-5.74.5.tgz +0 -0
  147. package/components/tryghost-post-events-5.74.5.tgz +0 -0
  148. package/components/tryghost-post-revisions-5.74.5.tgz +0 -0
  149. package/components/tryghost-posts-service-5.74.5.tgz +0 -0
  150. package/components/tryghost-recommendations-5.74.5.tgz +0 -0
  151. package/components/tryghost-referrers-5.74.5.tgz +0 -0
  152. package/components/tryghost-settings-path-manager-5.74.5.tgz +0 -0
  153. package/components/tryghost-slack-notifications-5.74.5.tgz +0 -0
  154. package/components/tryghost-stats-service-5.74.5.tgz +0 -0
  155. package/components/tryghost-tiers-5.74.5.tgz +0 -0
  156. package/components/tryghost-version-notifications-data-service-5.74.5.tgz +0 -0
  157. /package/core/built/admin/assets/{chunk.137.0297fba124bc9ba1bbc1.js.LICENSE.txt → chunk.214.611b4f2521fabe34eea8.js.LICENSE.txt} +0 -0
@@ -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.74%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%22a5d777fdf2%22%2C%22adminXDemoFilename%22%3A%22admin-x-demo.js%22%2C%22adminXDemoHash%22%3A%2254a22f23e1%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%22f76ec8c678%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.75%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%228fe2f5ae8e%22%2C%22adminXDemoFilename%22%3A%22admin-x-demo.js%22%2C%22adminXDemoHash%22%3A%22b092dea02b%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%2290920a9a6f%22%7D" />
12
12
 
13
13
  <meta name="HandheldFriendly" content="True" />
14
14
  <meta name="MobileOptimized" content="320" />
@@ -57,8 +57,8 @@
57
57
  <div id="ember-basic-dropdown-wormhole"></div>
58
58
 
59
59
  <script src="assets/vendor-f6856af9fcd8ab6533f2a4339ececbc8.js"></script>
60
- <script src="assets/chunk.137.0297fba124bc9ba1bbc1.js"></script>
61
- <script src="assets/chunk.143.2a6618f48157c893c4e3.js"></script>
62
- <script src="assets/ghost-7d0f91cd17901ac15ce0ae64a3091e2a.js"></script>
60
+ <script src="assets/chunk.214.611b4f2521fabe34eea8.js"></script>
61
+ <script src="assets/chunk.143.48ba4e0e6f8fd2e11002.js"></script>
62
+ <script src="assets/ghost-ceacd55503e4d34de4b4e7ba2309a6ab.js"></script>
63
63
  </body>
64
64
  </html>
@@ -2,15 +2,6 @@ const settingsCache = require('../../shared/settings-cache');
2
2
  const _ = require('lodash');
3
3
 
4
4
  function getContextObject(data, context) {
5
- /**
6
- * If the data object does not contain the requested context, we return the fallback object.
7
- */
8
- const blog = {
9
- cover_image: settingsCache.get('cover_image'),
10
- twitter: settingsCache.get('twitter'),
11
- facebook: settingsCache.get('facebook')
12
- };
13
-
14
5
  let chosenContext;
15
6
 
16
7
  // @TODO: meta layer is very broken, it's really hard to understand what it's doing
@@ -31,9 +22,13 @@ function getContextObject(data, context) {
31
22
  chosenContext = data[context];
32
23
  }
33
24
 
34
- // Super fallback.
25
+ // If the data object does not contain the requested context, we return the fallback object.
35
26
  if (!chosenContext) {
36
- chosenContext = blog;
27
+ chosenContext = {
28
+ cover_image: settingsCache.get('cover_image'),
29
+ twitter: settingsCache.get('twitter'),
30
+ facebook: settingsCache.get('facebook')
31
+ };
37
32
  }
38
33
 
39
34
  return chosenContext;
@@ -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('members_newsletters', ['newsletter_id', 'member_id'], knex);
8
+ },
9
+ async function down(knex) {
10
+ try {
11
+ await dropIndex('members_newsletters', ['newsletter_id', 'member_id'], knex);
12
+ } catch (err) {
13
+ if (err.code === 'ER_DROP_INDEX_FK') {
14
+ logging.error({
15
+ message: 'Error dropping index over members_newsletters(newsletter_id, member_id), re-adding index for newsletter_id'
16
+ });
17
+
18
+ await addIndex('members_newsletters', ['newsletter_id'], knex);
19
+ await dropIndex('members_newsletters', ['newsletter_id', 'member_id'], knex);
20
+ return;
21
+ }
22
+
23
+ throw err;
24
+ }
25
+ }
26
+ );
@@ -936,7 +936,10 @@ module.exports = {
936
936
  members_newsletters: {
937
937
  id: {type: 'string', maxlength: 24, nullable: false, primary: true},
938
938
  member_id: {type: 'string', maxlength: 24, nullable: false, references: 'members.id', cascadeDelete: true},
939
- newsletter_id: {type: 'string', maxlength: 24, nullable: false, references: 'newsletters.id', cascadeDelete: true}
939
+ newsletter_id: {type: 'string', maxlength: 24, nullable: false, references: 'newsletters.id', cascadeDelete: true},
940
+ '@@INDEXES@@': [
941
+ ['newsletter_id', 'member_id']
942
+ ]
940
943
  },
941
944
  comments: {
942
945
  id: {type: 'string', maxlength: 24, nullable: false, primary: true},
@@ -1,7 +1,6 @@
1
1
  const ghostBookshelf = require('./base');
2
2
  const ObjectID = require('bson-objectid').default;
3
3
  const uuid = require('uuid');
4
- const DatabaseInfo = require('@tryghost/database-info');
5
4
  const urlUtils = require('../../shared/url-utils');
6
5
 
7
6
  const Newsletter = ghostBookshelf.Model.extend({
@@ -156,17 +155,11 @@ const Newsletter = ghostBookshelf.Model.extend({
156
155
  active_members(modelOrCollection) {
157
156
  modelOrCollection.query('columns', 'newsletters.*', (qb) => {
158
157
  qb.count('members_newsletters.id')
158
+ .from('members_newsletters')
159
159
  .join('members', 'members.id', 'members_newsletters.member_id')
160
160
  .whereRaw('members_newsletters.newsletter_id = newsletters.id')
161
161
  .andWhere('members.email_disabled', false)
162
162
  .as('count__active_members');
163
-
164
- // https://github.com/TryGhost/Product/issues/4181
165
- if (DatabaseInfo.isMySQL(ghostBookshelf.knex)) {
166
- qb.fromRaw('members_newsletters force index (members_newsletters_newsletter_id_foreign)');
167
- } else {
168
- qb.from('members_newsletters');
169
- }
170
163
  });
171
164
  }
172
165
  };
@@ -159,8 +159,7 @@ class NewslettersService {
159
159
  throw error;
160
160
  }
161
161
 
162
- // Load relations correctly
163
- newsletter = await this.NewsletterModel.findOne({id: newsletter.id}, {...options, require: true});
162
+ let optedInMemberCount = undefined;
164
163
 
165
164
  // subscribe existing members if opt_in_existing=true
166
165
  if (options.opt_in_existing) {
@@ -169,8 +168,7 @@ class NewslettersService {
169
168
  // subscribe members that have an existing subscription to an active newsletter
170
169
  const memberIds = await this.MemberModel.fetchAllSubscribed(_.pick(options, 'transacting'));
171
170
 
172
- newsletter.meta = newsletter.meta || {};
173
- newsletter.meta.opted_in_member_count = memberIds.length;
171
+ optedInMemberCount = memberIds.length;
174
172
 
175
173
  if (memberIds.length) {
176
174
  debug(`Found ${memberIds.length} members to subscribe`);
@@ -179,6 +177,14 @@ class NewslettersService {
179
177
  }
180
178
  }
181
179
 
180
+ // Load relations correctly
181
+ newsletter = await this.NewsletterModel.findOne({id: newsletter.id}, {...options, require: true});
182
+
183
+ if (optedInMemberCount !== undefined) {
184
+ newsletter.meta = newsletter.meta || {};
185
+ newsletter.meta.opted_in_member_count = optedInMemberCount;
186
+ }
187
+
182
188
  // send any verification emails and respond with the appropriate meta added
183
189
  return this.respondWithEmailVerification(newsletter, emailsToVerify);
184
190
  }
@@ -237,7 +243,12 @@ class NewslettersService {
237
243
  const attrs = {};
238
244
  attrs[property] = value;
239
245
 
240
- return this.NewsletterModel.edit(attrs, {id});
246
+ const updatedNewsletter = await this.NewsletterModel.edit(attrs, {id});
247
+
248
+ updatedNewsletter.meta = updatedNewsletter.meta || {};
249
+ updatedNewsletter.meta.email_verified = property;
250
+
251
+ return updatedNewsletter;
241
252
  }
242
253
 
243
254
  /* Email verification Internals */
@@ -330,11 +341,11 @@ class NewslettersService {
330
341
  fromEmail = `no-reply@${toDomain}`;
331
342
  }
332
343
 
333
- if (this.emailAddressService.useNewEmailAddresses) {
344
+ if (this.emailAddressService.service.useNewEmailAddresses) {
334
345
  // Gone with the old logic: always use the default email address here
335
346
  // We don't need to validate the FROM address, only the to address
336
347
  // Also because we are not only validating FROM addresses, but also possible REPLY-TO addresses, which we won't send FROM
337
- fromEmail = this.emailAddressService.defaultFromAddress;
348
+ fromEmail = this.emailAddressService.service.defaultFromAddress;
338
349
  }
339
350
 
340
351
  const {ghostMailer} = this;
@@ -1,6 +1,6 @@
1
1
  const _ = require('lodash');
2
2
  const tpl = require('@tryghost/tpl');
3
- const {NotFoundError, NoPermissionError, BadRequestError, IncorrectUsageError} = require('@tryghost/errors');
3
+ const {NotFoundError, NoPermissionError, BadRequestError, IncorrectUsageError, ValidationError} = require('@tryghost/errors');
4
4
  const {obfuscatedSetting, isSecretSetting, hideValueIfSecret} = require('./settings-utils');
5
5
  const logging = require('@tryghost/logging');
6
6
  const MagicLink = require('@tryghost/magic-link');
@@ -9,7 +9,8 @@ const verifyEmailTemplate = require('./emails/verify-email');
9
9
  const EMAIL_KEYS = ['members_support_address'];
10
10
  const messages = {
11
11
  problemFindingSetting: 'Problem finding setting: {key}',
12
- accessCoreSettingFromExtReq: 'Attempted to access core setting from external request'
12
+ accessCoreSettingFromExtReq: 'Attempted to access core setting from external request',
13
+ invalidEmail: 'Invalid email address'
13
14
  };
14
15
 
15
16
  class SettingsBREADService {
@@ -22,11 +23,13 @@ class SettingsBREADService {
22
23
  * @param {Object} options.singleUseTokenProvider
23
24
  * @param {Object} options.urlUtils
24
25
  * @param {Object} options.labsService - labs service instance
26
+ * @param {{service: Object}} options.emailAddressService
25
27
  */
26
- constructor({SettingsModel, settingsCache, labsService, mail, singleUseTokenProvider, urlUtils}) {
28
+ constructor({SettingsModel, settingsCache, labsService, mail, singleUseTokenProvider, urlUtils, emailAddressService}) {
27
29
  this.SettingsModel = SettingsModel;
28
30
  this.settingsCache = settingsCache;
29
31
  this.labs = labsService;
32
+ this.emailAddressService = emailAddressService;
30
33
 
31
34
  /* email verification setup */
32
35
 
@@ -323,7 +326,18 @@ class SettingsBREADService {
323
326
  const hasChanged = getSetting(setting).value !== email;
324
327
 
325
328
  if (await this.requiresEmailVerification({email, hasChanged})) {
326
- emailsToVerify.push({email, key});
329
+ const validated = this.emailAddressService.service.validate(email, 'replyTo');
330
+ if (!validated.allowed) {
331
+ throw new ValidationError({
332
+ message: messages.invalidEmail
333
+ });
334
+ }
335
+
336
+ if (validated.verificationEmailRequired) {
337
+ emailsToVerify.push({email, key});
338
+ } else {
339
+ filteredSettings.push(setting);
340
+ }
327
341
  } else {
328
342
  filteredSettings.push(setting);
329
343
  }
@@ -375,6 +389,13 @@ class SettingsBREADService {
375
389
  fromEmail = `no-reply@${toDomain}`;
376
390
  }
377
391
 
392
+ if (this.emailAddressService.service.useNewEmailAddresses) {
393
+ // Gone with the old logic: always use the default email address here
394
+ // We don't need to validate the FROM address, only the to address
395
+ // Also because we are not only validating FROM addresses, but also possible REPLY-TO addresses, which we won't send FROM
396
+ fromEmail = this.emailAddressService.service.defaultFromAddress;
397
+ }
398
+
378
399
  const {ghostMailer} = this;
379
400
 
380
401
  this.magicLinkService.transporter = {
@@ -15,6 +15,7 @@ const urlUtils = require('../../../shared/url-utils');
15
15
 
16
16
  const ObjectId = require('bson-objectid').default;
17
17
  const settingsHelpers = require('../settings-helpers');
18
+ const emailAddressService = require('../email-address');
18
19
 
19
20
  const MAGIC_LINK_TOKEN_VALIDITY = 24 * 60 * 60 * 1000;
20
21
  const MAGIC_LINK_TOKEN_VALIDITY_AFTER_USAGE = 10 * 60 * 1000;
@@ -35,7 +36,8 @@ const getSettingsBREADServiceInstance = () => {
35
36
  validityPeriodAfterUsage: MAGIC_LINK_TOKEN_VALIDITY_AFTER_USAGE,
36
37
  maxUsageCount: MAGIC_LINK_TOKEN_MAX_USAGE_COUNT
37
38
  }),
38
- urlUtils
39
+ urlUtils,
40
+ emailAddressService: emailAddressService
39
41
  });
40
42
  };
41
43
 
@@ -42,5 +42,7 @@ module.exports = {
42
42
  portal_button: 'portal_button',
43
43
  comments_enabled: 'comments_enabled',
44
44
  recommendations_enabled: 'recommendations_enabled',
45
- outbound_link_tagging: 'outbound_link_tagging'
45
+ outbound_link_tagging: 'outbound_link_tagging',
46
+ default_email_address: 'default_email_address',
47
+ support_email_address: 'support_email_address'
46
48
  };