ghost 4.47.4 → 5.0.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 (664) hide show
  1. package/Gruntfile.js +24 -24
  2. package/README.md +3 -2
  3. package/content/themes/casper/assets/built/global.css +1 -1
  4. package/content/themes/casper/assets/built/global.css.map +1 -1
  5. package/content/themes/casper/assets/built/screen.css +1 -1
  6. package/content/themes/casper/assets/built/screen.css.map +1 -1
  7. package/content/themes/casper/assets/css/global.css +2 -2
  8. package/content/themes/casper/assets/css/screen.css +412 -664
  9. package/content/themes/casper/author.hbs +48 -35
  10. package/content/themes/casper/default.hbs +5 -23
  11. package/content/themes/casper/error-404.hbs +1 -1
  12. package/content/themes/casper/index.hbs +29 -22
  13. package/content/themes/casper/package.json +25 -37
  14. package/content/themes/casper/page.hbs +12 -12
  15. package/content/themes/casper/partials/icons/facebook.hbs +1 -1
  16. package/content/themes/casper/partials/icons/twitter.hbs +1 -1
  17. package/content/themes/casper/partials/post-card.hbs +26 -40
  18. package/content/themes/casper/post.hbs +54 -50
  19. package/content/themes/casper/tag.hbs +42 -47
  20. package/core/boot.js +18 -15
  21. package/core/bridge.js +24 -25
  22. package/core/built/assets/ghost-dark-b6e3268bcae976a8675b0d9ae54540f2.css +1 -0
  23. package/core/built/assets/{ghost.min-a2a47979b0b61d15a3914042a7b1cd20.js → ghost.min-2cc3688ea6600a54e0cd83107a8577e8.js} +1138 -1212
  24. package/core/built/assets/ghost.min-a40c7b301c702bd84c2fae19366ab5d7.css +1 -0
  25. package/core/built/assets/icons/analytics.svg +14 -0
  26. package/core/built/assets/icons/calendar.svg +4 -1
  27. package/core/built/assets/icons/email-at.svg +1 -1
  28. package/core/built/assets/icons/email-name.svg +1 -1
  29. package/core/built/assets/icons/info.svg +1 -1
  30. package/core/built/assets/icons/twitter-logo.svg +3 -0
  31. package/core/built/assets/{vendor.min-97fd438f4772c5ec6bb30ad779b8530e.js → vendor.min-2bca41946dea27dc292428db605d466d.js} +99 -93
  32. package/core/cli/README.md +88 -0
  33. package/core/cli/command.js +129 -0
  34. package/core/cli/repl.js +32 -0
  35. package/core/cli/timetravel.js +87 -0
  36. package/core/frontend/apps/amp/lib/helpers/amp_content.js +10 -12
  37. package/core/frontend/apps/amp/lib/router.js +2 -3
  38. package/core/frontend/helpers/body_class.js +2 -2
  39. package/core/frontend/helpers/excerpt.js +0 -2
  40. package/core/frontend/helpers/get.js +23 -24
  41. package/core/frontend/helpers/ghost_head.js +104 -108
  42. package/core/frontend/helpers/navigation.js +0 -2
  43. package/core/frontend/helpers/prev_post.js +20 -26
  44. package/core/frontend/helpers/price.js +2 -2
  45. package/core/frontend/meta/author-url.js +2 -2
  46. package/core/frontend/meta/description.js +3 -3
  47. package/core/frontend/meta/excerpt.js +1 -2
  48. package/core/frontend/meta/generate-excerpt.js +2 -11
  49. package/core/frontend/meta/paginated-url.js +1 -1
  50. package/core/frontend/meta/rss-url.js +0 -1
  51. package/core/frontend/meta/url.js +4 -4
  52. package/core/frontend/services/data/entry-lookup.js +1 -1
  53. package/core/frontend/services/data/fetch-data.js +1 -1
  54. package/core/frontend/services/helpers/handlebars.js +11 -12
  55. package/core/frontend/services/proxy.js +11 -1
  56. package/core/frontend/services/rendering/context.js +1 -5
  57. package/core/frontend/services/rendering/format-response.js +9 -2
  58. package/core/frontend/services/rendering/index.js +0 -4
  59. package/core/frontend/services/rendering/render-entry.js +1 -1
  60. package/core/frontend/services/rendering/templates.js +15 -5
  61. package/core/frontend/services/routing/CollectionRouter.js +2 -2
  62. package/core/frontend/services/routing/EmailRouter.js +2 -2
  63. package/core/frontend/services/routing/ParentRouter.js +1 -1
  64. package/core/frontend/services/routing/PreviewRouter.js +3 -3
  65. package/core/frontend/services/routing/{config/v4.js → config.js} +3 -5
  66. package/core/frontend/services/routing/controllers/channel.js +0 -10
  67. package/core/frontend/services/routing/controllers/collection.js +0 -9
  68. package/core/frontend/services/routing/controllers/email-post.js +2 -7
  69. package/core/frontend/services/routing/controllers/entry.js +1 -3
  70. package/core/frontend/services/routing/controllers/index.js +2 -2
  71. package/core/frontend/services/routing/controllers/{preview.js → previews.js} +3 -8
  72. package/core/frontend/services/routing/controllers/static.js +1 -6
  73. package/core/frontend/services/routing/router-manager.js +38 -20
  74. package/core/frontend/services/rss/generate-feed.js +7 -9
  75. package/core/frontend/services/theme-engine/active.js +0 -8
  76. package/core/frontend/services/theme-engine/config/defaults.json +1 -3
  77. package/core/frontend/services/theme-engine/middleware/index.js +0 -1
  78. package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +0 -69
  79. package/core/frontend/services/theme-engine/middleware/update-local-template-options.js +3 -6
  80. package/core/frontend/web/middleware/static-theme.js +14 -6
  81. package/core/frontend/web/routes.js +9 -9
  82. package/core/frontend/web/site.js +15 -18
  83. package/core/server/adapters/scheduling/post-scheduling/index.js +1 -1
  84. package/core/server/api/README.md +2 -6
  85. package/core/server/api/canary/authentication.js +4 -3
  86. package/core/server/api/canary/{email-preview.js → email-previews.js} +9 -8
  87. package/core/server/api/canary/index.js +14 -18
  88. package/core/server/api/canary/members.js +4 -24
  89. package/core/server/api/{v3/actions.js → canary/newsletters-public.js} +6 -6
  90. package/core/server/api/canary/newsletters.js +1 -13
  91. package/core/server/api/canary/notifications.js +17 -22
  92. package/core/server/api/canary/offers-public.js +28 -0
  93. package/core/server/api/canary/pages.js +1 -1
  94. package/core/server/api/canary/posts.js +4 -8
  95. package/core/server/api/canary/{preview.js → previews.js} +1 -1
  96. package/core/server/api/canary/schedules.js +1 -1
  97. package/core/server/api/canary/session.js +1 -1
  98. package/core/server/api/canary/settings-public.js +3 -1
  99. package/core/server/api/canary/settings.js +30 -16
  100. package/core/server/api/canary/utils/index.js +2 -4
  101. package/core/server/api/canary/utils/serializers/input/index.js +0 -4
  102. package/core/server/api/canary/utils/serializers/input/members.js +46 -17
  103. package/core/server/api/canary/utils/serializers/input/pages.js +0 -17
  104. package/core/server/api/canary/utils/serializers/input/posts.js +1 -28
  105. package/core/server/api/canary/utils/serializers/input/settings.js +61 -142
  106. package/core/server/api/canary/utils/serializers/input/tiers.js +56 -12
  107. package/core/server/api/canary/utils/serializers/output/authentication.js +2 -6
  108. package/core/server/api/canary/utils/serializers/output/index.js +2 -10
  109. package/core/server/api/canary/utils/serializers/output/mappers/index.js +1 -0
  110. package/core/server/api/canary/utils/serializers/output/mappers/newsletters.js +24 -0
  111. package/core/server/api/canary/utils/serializers/output/mappers/pages.js +1 -1
  112. package/core/server/api/canary/utils/serializers/output/mappers/posts.js +9 -7
  113. package/core/server/api/canary/utils/serializers/output/mappers/settings.js +5 -31
  114. package/core/server/api/canary/utils/serializers/output/members.js +21 -11
  115. package/core/server/api/canary/utils/serializers/output/offers.js +9 -1
  116. package/core/server/api/canary/utils/serializers/output/{preview.js → previews.js} +2 -2
  117. package/core/server/api/canary/utils/serializers/output/settings.js +6 -14
  118. package/core/server/api/canary/utils/serializers/output/site.js +0 -1
  119. package/core/server/api/canary/utils/serializers/output/tiers.js +35 -75
  120. package/core/server/api/canary/utils/serializers/output/utils/clean.js +5 -10
  121. package/core/server/api/canary/utils/serializers/output/utils/extra-attrs.js +0 -126
  122. package/core/server/api/canary/utils/serializers/output/utils/post-gating.js +1 -1
  123. package/core/server/api/canary/utils/serializers/output/utils/url.js +0 -5
  124. package/core/server/api/canary/utils/validators/input/index.js +2 -2
  125. package/core/server/api/canary/utils/validators/input/{passwordreset.js → password_reset.js} +2 -2
  126. package/core/server/api/canary/utils/validators/input/settings.js +2 -23
  127. package/core/server/api/canary/utils/validators/utils/json-schema.js +1 -2
  128. package/core/server/api/index.js +1 -7
  129. package/core/server/api/shared/serializers/input/utils/settings-key-group-mapper.js +2 -2
  130. package/core/server/api/shared/serializers/input/utils/settings-key-type-mapper.js +2 -4
  131. package/core/server/data/db/connection.js +0 -13
  132. package/core/server/data/exporter/index.js +4 -1
  133. package/core/server/data/exporter/table-lists.js +13 -15
  134. package/core/server/data/importer/importers/data/base.js +16 -7
  135. package/core/server/data/importer/importers/data/data-importer.js +38 -1
  136. package/core/server/data/importer/importers/data/newsletters.js +45 -0
  137. package/core/server/data/importer/importers/data/posts.js +40 -12
  138. package/core/server/data/importer/importers/data/products.js +68 -0
  139. package/core/server/data/importer/importers/data/settings.js +10 -10
  140. package/core/server/data/importer/importers/data/stripe-prices.js +59 -0
  141. package/core/server/data/importer/importers/data/stripe-products.js +61 -0
  142. package/core/server/data/migrations/utils/constants.js +3 -0
  143. package/core/server/data/migrations/utils/index.js +10 -0
  144. package/core/server/data/migrations/utils/migrations.js +156 -0
  145. package/core/server/data/migrations/utils/permissions.js +291 -0
  146. package/core/server/data/migrations/utils/schema.js +158 -0
  147. package/core/server/data/migrations/utils/settings.js +59 -0
  148. package/core/server/data/migrations/utils/tables.js +94 -0
  149. package/core/server/data/migrations/versions/1.25/01-final-v1.js +2 -0
  150. package/core/server/data/migrations/versions/1.25/02-noop.js +6 -0
  151. package/core/server/data/migrations/versions/2.37/01-final-v2.js +2 -0
  152. package/core/server/data/migrations/versions/3.41/01-final-v3.js +2 -0
  153. package/core/server/data/migrations/versions/4.0/22-solve-orphaned-webhooks.js +3 -9
  154. package/core/server/data/migrations/versions/4.0/23-regenerate-posts-html.js +2 -11
  155. package/core/server/data/migrations/versions/4.11/02-add-email-verification-required-setting.js +1 -1
  156. package/core/server/data/migrations/versions/4.12/02-fix-member-statuses.js +1 -1
  157. package/core/server/data/migrations/versions/4.14/02-fix-free-members-status-events.js +1 -1
  158. package/core/server/data/migrations/versions/4.22/01-add-is-launch-complete-setting.js +1 -1
  159. package/core/server/data/migrations/versions/4.22/02-update-launch-complete-setting-from-user-data.js +1 -1
  160. package/core/server/data/migrations/versions/4.35/2022-02-02-10-38-add-default-content-visibility-tiers-setting.js +1 -1
  161. package/core/server/data/migrations/versions/4.45/2022-04-21-02-55-add-notifications-key-entry-to-settings-table.js +1 -1
  162. package/core/server/data/migrations/versions/4.6/01-remove-comped-status.js +1 -1
  163. package/core/server/data/migrations/versions/4.7/03-add-labs-setting.js +1 -1
  164. package/core/server/data/migrations/versions/4.9/05-fix-missed-mobiledoc-url-transforms.js +1 -1
  165. package/core/server/data/migrations/versions/4.9/06-add-comped-status.js +1 -1
  166. package/core/server/data/migrations/versions/4.9/07-update-comped-members-status-events.js +1 -1
  167. package/core/server/data/migrations/versions/5.0/2022-03-14-12-33-delete-duplicate-offer-redemptions.js +36 -0
  168. package/core/server/data/migrations/versions/5.0/2022-03-28-15-25-backfill-mrr-adjustments-for-offers.js +108 -0
  169. package/core/server/data/migrations/versions/5.0/2022-04-25-10-32-backfill-mrr-for-discounted-subscriptions.js +44 -0
  170. package/core/server/data/migrations/versions/5.0/2022-04-26-15-44-backfill-mrr-events-for-canceled-subscriptions.js +73 -0
  171. package/core/server/data/migrations/versions/5.0/2022-04-27-11-26-backfill-mrr-for-canceled-subscriptions.js +31 -0
  172. package/core/server/data/migrations/versions/5.0/2022-04-28-03-26-remove-author-id-column-from-posts-table.js +7 -0
  173. package/core/server/data/migrations/versions/5.0/2022-05-03-09-39-drop-nullable-subscribe-event-newsletter-id.js +4 -0
  174. package/core/server/data/migrations/versions/5.0/2022-05-04-15-24-map-existing-emails-to-default-newsletter.js +44 -0
  175. package/core/server/data/migrations/versions/5.0/2022-05-05-13-13-migrate-legacy-recipient-filters.js +30 -0
  176. package/core/server/data/migrations/versions/5.0/2022-05-05-13-29-add-newsletters-admin-integration-permission-roles.js +20 -0
  177. package/core/server/data/migrations/versions/5.0/2022-05-05-15-17-drop-oauth-table.js +3 -0
  178. package/core/server/data/migrations/versions/5.0/2022-05-06-08-16-cleanup-client-subscriber-permissions.js +68 -0
  179. package/core/server/data/migrations/versions/5.0/2022-05-06-13-22-add-frontend-integration.js +68 -0
  180. package/core/server/data/migrations/versions/5.0/2022-05-09-10-00-drop-members-subscribed-column.js +18 -0
  181. package/core/server/data/migrations/versions/5.0/2022-05-09-14-17-cleanup-invalid-users-status.js +17 -0
  182. package/core/server/data/migrations/versions/5.0/2022-05-10-08-33-drop-members-analytics-table.js +3 -0
  183. package/core/server/data/migrations/versions/5.0/2022-05-10-14-57-cleanup-invalid-posts-status.js +17 -0
  184. package/core/server/data/migrations/versions/5.0/2022-05-11-12-08-drop-webhooks-status-column.js +18 -0
  185. package/core/server/data/migrations/versions/5.0/2022-05-11-13-12-rename-settings.js +51 -0
  186. package/core/server/data/migrations/versions/5.0/2022-05-11-16-36-remove-unused-settings.js +54 -0
  187. package/core/server/data/migrations/versions/5.0/2022-05-12-10-29-add-newsletter-permissions-for-editors-and-authors.js +20 -0
  188. package/core/server/data/migrations/versions/5.0/2022-05-12-13-51-add-label-permissions-for-authors.js +12 -0
  189. package/core/server/data/migrations/versions/5.0/2022-05-13-11-38-drop-none-email-recipient-filter.js +28 -0
  190. package/core/server/data/migrations/versions/5.0/2022-05-21-00-00-regenerate-posts-html.js +70 -0
  191. package/core/server/data/schema/commands.js +35 -3
  192. package/core/server/data/schema/default-settings/default-settings.json +2 -159
  193. package/core/server/data/schema/fixtures/fixture-manager.js +11 -2
  194. package/core/server/data/schema/fixtures/fixtures.json +16 -7
  195. package/core/server/data/schema/schema.js +26 -38
  196. package/core/server/data/schema/validator.js +2 -0
  197. package/core/server/ghost-server.js +34 -64
  198. package/core/server/lib/image/gravatar.js +25 -9
  199. package/core/server/models/api-key.js +3 -26
  200. package/core/server/models/base/plugins/bulk-operations.js +14 -6
  201. package/core/server/models/integration.js +17 -0
  202. package/core/server/models/member.js +8 -4
  203. package/core/server/models/newsletter.js +27 -0
  204. package/core/server/models/post.js +30 -32
  205. package/core/server/models/relations/authors.js +74 -100
  206. package/core/server/models/settings.js +6 -2
  207. package/core/server/models/webhook.js +2 -1
  208. package/core/server/run-update-check.js +1 -1
  209. package/core/server/services/api-version-compatibility/index.js +24 -18
  210. package/core/server/services/api-version-compatibility/legacy-api-path-match.js +23 -0
  211. package/core/server/services/api-version-compatibility/mw-version-rewrites.js +36 -0
  212. package/core/server/services/auth/api-key/admin.js +8 -7
  213. package/core/server/services/auth/passwordreset.js +3 -3
  214. package/core/server/services/auth/session/express-session.js +1 -1
  215. package/core/server/services/auth/session/index.js +1 -1
  216. package/core/server/services/auth/setup.js +8 -8
  217. package/core/server/services/bulk-email/bulk-email-processor.js +5 -1
  218. package/core/server/services/email-analytics/lib/event-processor.js +25 -14
  219. package/core/server/services/frontend-data-service/frontend-data-service.js +27 -0
  220. package/core/server/services/frontend-data-service/index.js +6 -0
  221. package/core/server/services/mail/index.js +14 -1
  222. package/core/server/services/mega/email-preview.js +14 -15
  223. package/core/server/services/mega/mega.js +37 -52
  224. package/core/server/services/mega/post-email-serializer.js +18 -28
  225. package/core/server/services/members/api.js +0 -3
  226. package/core/server/services/members/config.js +0 -49
  227. package/core/server/services/members/exporter/query.js +88 -0
  228. package/core/server/services/members/middleware.js +3 -135
  229. package/core/server/services/members/service.js +2 -29
  230. package/core/server/services/members/settings.js +3 -9
  231. package/core/server/services/newsletters/service.js +78 -10
  232. package/core/server/services/posts/post-scheduling-service.js +5 -17
  233. package/core/server/services/posts/posts-service.js +15 -62
  234. package/core/server/services/public-config/site.js +0 -6
  235. package/core/server/services/route-settings/index.js +0 -3
  236. package/core/server/services/route-settings/settings-loader.js +10 -34
  237. package/core/server/services/route-settings/validate.js +1 -7
  238. package/core/server/services/settings/index.js +1 -77
  239. package/core/server/services/settings/settings-service.js +184 -0
  240. package/core/server/services/themes/validate.js +1 -1
  241. package/core/server/services/url/Resources.js +1 -3
  242. package/core/server/services/url/UrlGenerator.js +1 -1
  243. package/core/server/services/url/UrlService.js +6 -20
  244. package/core/server/services/url/{configs/v2.js → config.js} +0 -0
  245. package/core/server/services/users.js +2 -2
  246. package/core/server/services/webhooks/listen.js +5 -2
  247. package/core/server/services/webhooks/serialize.js +6 -7
  248. package/core/server/services/webhooks/trigger.js +62 -47
  249. package/core/server/update-check.js +1 -1
  250. package/core/server/web/admin/app.js +1 -1
  251. package/core/server/web/admin/views/default-prod.html +4 -4
  252. package/core/server/web/admin/views/default.html +4 -4
  253. package/core/server/web/api/app.js +3 -15
  254. package/core/server/web/api/canary/admin/app.js +1 -1
  255. package/core/server/web/api/canary/admin/middleware.js +3 -1
  256. package/core/server/web/api/canary/admin/routes.js +7 -23
  257. package/core/server/web/api/canary/content/app.js +2 -3
  258. package/core/server/web/api/canary/content/routes.js +5 -4
  259. package/core/server/web/members/app.js +5 -4
  260. package/core/server/web/parent/backend.js +0 -1
  261. package/core/server/web/parent/frontend.js +5 -6
  262. package/core/server/web/parent/middleware/ghost-locals.js +0 -3
  263. package/core/server/web/well-known.js +14 -1
  264. package/core/shared/config/defaults.json +5 -2
  265. package/core/shared/config/overrides.json +1 -27
  266. package/core/shared/html-to-plaintext.js +78 -10
  267. package/core/shared/labs.js +4 -8
  268. package/core/shared/settings-cache/cache.js +38 -4
  269. package/core/shared/settings-cache/public.js +13 -7
  270. package/core/shared/url-utils.js +0 -2
  271. package/ghost.js +6 -0
  272. package/package.json +66 -64
  273. package/yarn.lock +765 -1300
  274. package/core/built/assets/ghost-dark-c94ae212747200ca4bafc37cfb0714d8.css +0 -1
  275. package/core/built/assets/ghost.min-4084931bc22e794fe3722139050a80b3.css +0 -1
  276. package/core/frontend/helpers/author.js +0 -41
  277. package/core/frontend/helpers/products.js +0 -65
  278. package/core/frontend/services/rendering/secure.js +0 -19
  279. package/core/frontend/services/routing/config/canary.js +0 -61
  280. package/core/frontend/services/routing/config/v2.js +0 -54
  281. package/core/frontend/services/routing/config/v3.js +0 -54
  282. package/core/frontend/services/theme-engine/engines/create.js +0 -45
  283. package/core/frontend/services/theme-engine/engines/index.js +0 -5
  284. package/core/frontend/services/theme-engine/middleware/update-local-template-data.js +0 -9
  285. package/core/server/api/canary/products-public.js +0 -34
  286. package/core/server/api/canary/products.js +0 -116
  287. package/core/server/api/canary/utils/serializers/input/products.js +0 -28
  288. package/core/server/api/canary/utils/serializers/output/email-previews.js +0 -7
  289. package/core/server/api/canary/utils/serializers/output/products.js +0 -213
  290. package/core/server/api/v2/actions.js +0 -38
  291. package/core/server/api/v2/authentication.js +0 -191
  292. package/core/server/api/v2/authors-public.js +0 -69
  293. package/core/server/api/v2/config.js +0 -12
  294. package/core/server/api/v2/db.js +0 -120
  295. package/core/server/api/v2/images.js +0 -20
  296. package/core/server/api/v2/index.js +0 -147
  297. package/core/server/api/v2/integrations.js +0 -144
  298. package/core/server/api/v2/invites.js +0 -126
  299. package/core/server/api/v2/mail.js +0 -66
  300. package/core/server/api/v2/notifications.js +0 -96
  301. package/core/server/api/v2/oembed.js +0 -186
  302. package/core/server/api/v2/pages-public.js +0 -78
  303. package/core/server/api/v2/pages.js +0 -197
  304. package/core/server/api/v2/posts-public.js +0 -78
  305. package/core/server/api/v2/posts.js +0 -192
  306. package/core/server/api/v2/preview.js +0 -46
  307. package/core/server/api/v2/redirects.js +0 -28
  308. package/core/server/api/v2/roles.js +0 -19
  309. package/core/server/api/v2/schedules.js +0 -77
  310. package/core/server/api/v2/session.js +0 -70
  311. package/core/server/api/v2/settings-public.js +0 -17
  312. package/core/server/api/v2/settings.js +0 -195
  313. package/core/server/api/v2/site.js +0 -14
  314. package/core/server/api/v2/slack.js +0 -12
  315. package/core/server/api/v2/slugs.js +0 -51
  316. package/core/server/api/v2/tags-public.js +0 -71
  317. package/core/server/api/v2/tags.js +0 -159
  318. package/core/server/api/v2/themes.js +0 -133
  319. package/core/server/api/v2/users.js +0 -179
  320. package/core/server/api/v2/utils/index.js +0 -34
  321. package/core/server/api/v2/utils/permissions.js +0 -112
  322. package/core/server/api/v2/utils/serializers/index.js +0 -9
  323. package/core/server/api/v2/utils/serializers/input/db.js +0 -20
  324. package/core/server/api/v2/utils/serializers/input/index.js +0 -33
  325. package/core/server/api/v2/utils/serializers/input/integrations.js +0 -33
  326. package/core/server/api/v2/utils/serializers/input/pages.js +0 -203
  327. package/core/server/api/v2/utils/serializers/input/posts.js +0 -218
  328. package/core/server/api/v2/utils/serializers/input/settings.js +0 -152
  329. package/core/server/api/v2/utils/serializers/input/tags.js +0 -35
  330. package/core/server/api/v2/utils/serializers/input/users.js +0 -26
  331. package/core/server/api/v2/utils/serializers/input/utils/url.js +0 -71
  332. package/core/server/api/v2/utils/serializers/input/webhooks.js +0 -12
  333. package/core/server/api/v2/utils/serializers/output/actions.js +0 -13
  334. package/core/server/api/v2/utils/serializers/output/all.js +0 -25
  335. package/core/server/api/v2/utils/serializers/output/authentication.js +0 -68
  336. package/core/server/api/v2/utils/serializers/output/authors.js +0 -21
  337. package/core/server/api/v2/utils/serializers/output/config.js +0 -21
  338. package/core/server/api/v2/utils/serializers/output/db.js +0 -40
  339. package/core/server/api/v2/utils/serializers/output/images.js +0 -19
  340. package/core/server/api/v2/utils/serializers/output/index.js +0 -107
  341. package/core/server/api/v2/utils/serializers/output/integrations.js +0 -35
  342. package/core/server/api/v2/utils/serializers/output/invites.js +0 -24
  343. package/core/server/api/v2/utils/serializers/output/mail.js +0 -19
  344. package/core/server/api/v2/utils/serializers/output/notifications.js +0 -29
  345. package/core/server/api/v2/utils/serializers/output/oembed.js +0 -8
  346. package/core/server/api/v2/utils/serializers/output/pages.js +0 -26
  347. package/core/server/api/v2/utils/serializers/output/posts.js +0 -26
  348. package/core/server/api/v2/utils/serializers/output/preview.js +0 -9
  349. package/core/server/api/v2/utils/serializers/output/redirects.js +0 -5
  350. package/core/server/api/v2/utils/serializers/output/roles.js +0 -29
  351. package/core/server/api/v2/utils/serializers/output/schedules.js +0 -5
  352. package/core/server/api/v2/utils/serializers/output/settings.js +0 -61
  353. package/core/server/api/v2/utils/serializers/output/site.js +0 -16
  354. package/core/server/api/v2/utils/serializers/output/slugs.js +0 -11
  355. package/core/server/api/v2/utils/serializers/output/tags.js +0 -25
  356. package/core/server/api/v2/utils/serializers/output/themes.js +0 -25
  357. package/core/server/api/v2/utils/serializers/output/users.js +0 -45
  358. package/core/server/api/v2/utils/serializers/output/utils/clean.js +0 -174
  359. package/core/server/api/v2/utils/serializers/output/utils/date.js +0 -21
  360. package/core/server/api/v2/utils/serializers/output/utils/extra-attrs.js +0 -161
  361. package/core/server/api/v2/utils/serializers/output/utils/mapper.js +0 -136
  362. package/core/server/api/v2/utils/serializers/output/utils/post-gating.js +0 -29
  363. package/core/server/api/v2/utils/serializers/output/utils/settings-type-group-mapper.js +0 -24
  364. package/core/server/api/v2/utils/serializers/output/utils/url.js +0 -67
  365. package/core/server/api/v2/utils/serializers/output/webhooks.js +0 -15
  366. package/core/server/api/v2/utils/validators/index.js +0 -9
  367. package/core/server/api/v2/utils/validators/input/images.js +0 -85
  368. package/core/server/api/v2/utils/validators/input/index.js +0 -45
  369. package/core/server/api/v2/utils/validators/input/invitations.js +0 -49
  370. package/core/server/api/v2/utils/validators/input/invites.js +0 -21
  371. package/core/server/api/v2/utils/validators/input/oembed.js +0 -17
  372. package/core/server/api/v2/utils/validators/input/pages.js +0 -46
  373. package/core/server/api/v2/utils/validators/input/passwordreset.js +0 -36
  374. package/core/server/api/v2/utils/validators/input/posts.js +0 -46
  375. package/core/server/api/v2/utils/validators/input/settings.js +0 -79
  376. package/core/server/api/v2/utils/validators/input/setup.js +0 -17
  377. package/core/server/api/v2/utils/validators/input/tags.js +0 -6
  378. package/core/server/api/v2/utils/validators/input/users.js +0 -21
  379. package/core/server/api/v2/utils/validators/output/index.js +0 -1
  380. package/core/server/api/v2/utils/validators/utils/json-schema.js +0 -17
  381. package/core/server/api/v2/webhooks.js +0 -163
  382. package/core/server/api/v3/authentication.js +0 -192
  383. package/core/server/api/v3/authors-public.js +0 -69
  384. package/core/server/api/v3/config.js +0 -12
  385. package/core/server/api/v3/db.js +0 -131
  386. package/core/server/api/v3/email-preview.js +0 -74
  387. package/core/server/api/v3/email.js +0 -65
  388. package/core/server/api/v3/identities.js +0 -36
  389. package/core/server/api/v3/images.js +0 -20
  390. package/core/server/api/v3/index.js +0 -179
  391. package/core/server/api/v3/integrations.js +0 -150
  392. package/core/server/api/v3/invites.js +0 -125
  393. package/core/server/api/v3/labels.js +0 -162
  394. package/core/server/api/v3/mail.js +0 -66
  395. package/core/server/api/v3/memberSigninUrls.js +0 -33
  396. package/core/server/api/v3/members.js +0 -412
  397. package/core/server/api/v3/membersStripeConnect.js +0 -29
  398. package/core/server/api/v3/notifications.js +0 -96
  399. package/core/server/api/v3/oembed.js +0 -23
  400. package/core/server/api/v3/pages-public.js +0 -77
  401. package/core/server/api/v3/pages.js +0 -199
  402. package/core/server/api/v3/posts-public.js +0 -76
  403. package/core/server/api/v3/posts.js +0 -200
  404. package/core/server/api/v3/preview.js +0 -44
  405. package/core/server/api/v3/redirects.js +0 -47
  406. package/core/server/api/v3/roles.js +0 -19
  407. package/core/server/api/v3/schedules.js +0 -77
  408. package/core/server/api/v3/session.js +0 -70
  409. package/core/server/api/v3/settings-public.js +0 -17
  410. package/core/server/api/v3/settings.js +0 -224
  411. package/core/server/api/v3/site.js +0 -14
  412. package/core/server/api/v3/slack.js +0 -12
  413. package/core/server/api/v3/slugs.js +0 -48
  414. package/core/server/api/v3/snippets.js +0 -115
  415. package/core/server/api/v3/tags-public.js +0 -71
  416. package/core/server/api/v3/tags.js +0 -159
  417. package/core/server/api/v3/themes.js +0 -131
  418. package/core/server/api/v3/users.js +0 -242
  419. package/core/server/api/v3/utils/index.js +0 -34
  420. package/core/server/api/v3/utils/permissions.js +0 -116
  421. package/core/server/api/v3/utils/serializers/index.js +0 -9
  422. package/core/server/api/v3/utils/serializers/input/authors.js +0 -31
  423. package/core/server/api/v3/utils/serializers/input/db.js +0 -20
  424. package/core/server/api/v3/utils/serializers/input/index.js +0 -41
  425. package/core/server/api/v3/utils/serializers/input/integrations.js +0 -33
  426. package/core/server/api/v3/utils/serializers/input/members.js +0 -62
  427. package/core/server/api/v3/utils/serializers/input/pages.js +0 -208
  428. package/core/server/api/v3/utils/serializers/input/posts.js +0 -242
  429. package/core/server/api/v3/utils/serializers/input/settings.js +0 -168
  430. package/core/server/api/v3/utils/serializers/input/tags.js +0 -42
  431. package/core/server/api/v3/utils/serializers/input/users.js +0 -26
  432. package/core/server/api/v3/utils/serializers/input/utils/slug-filter-order.js +0 -18
  433. package/core/server/api/v3/utils/serializers/input/utils/url.js +0 -71
  434. package/core/server/api/v3/utils/serializers/input/webhooks.js +0 -12
  435. package/core/server/api/v3/utils/serializers/output/actions.js +0 -13
  436. package/core/server/api/v3/utils/serializers/output/all.js +0 -25
  437. package/core/server/api/v3/utils/serializers/output/authentication.js +0 -69
  438. package/core/server/api/v3/utils/serializers/output/authors.js +0 -21
  439. package/core/server/api/v3/utils/serializers/output/config.js +0 -25
  440. package/core/server/api/v3/utils/serializers/output/db.js +0 -40
  441. package/core/server/api/v3/utils/serializers/output/email-preview.js +0 -7
  442. package/core/server/api/v3/utils/serializers/output/emails.js +0 -13
  443. package/core/server/api/v3/utils/serializers/output/identities.js +0 -7
  444. package/core/server/api/v3/utils/serializers/output/images.js +0 -19
  445. package/core/server/api/v3/utils/serializers/output/index.js +0 -135
  446. package/core/server/api/v3/utils/serializers/output/integrations.js +0 -35
  447. package/core/server/api/v3/utils/serializers/output/invites.js +0 -24
  448. package/core/server/api/v3/utils/serializers/output/labels.js +0 -25
  449. package/core/server/api/v3/utils/serializers/output/mail.js +0 -19
  450. package/core/server/api/v3/utils/serializers/output/member-signin_urls.js +0 -7
  451. package/core/server/api/v3/utils/serializers/output/members.js +0 -228
  452. package/core/server/api/v3/utils/serializers/output/notifications.js +0 -29
  453. package/core/server/api/v3/utils/serializers/output/oembed.js +0 -8
  454. package/core/server/api/v3/utils/serializers/output/pages.js +0 -26
  455. package/core/server/api/v3/utils/serializers/output/posts.js +0 -26
  456. package/core/server/api/v3/utils/serializers/output/preview.js +0 -10
  457. package/core/server/api/v3/utils/serializers/output/redirects.js +0 -5
  458. package/core/server/api/v3/utils/serializers/output/roles.js +0 -29
  459. package/core/server/api/v3/utils/serializers/output/schedules.js +0 -5
  460. package/core/server/api/v3/utils/serializers/output/settings.js +0 -65
  461. package/core/server/api/v3/utils/serializers/output/site.js +0 -19
  462. package/core/server/api/v3/utils/serializers/output/slugs.js +0 -11
  463. package/core/server/api/v3/utils/serializers/output/snippets.js +0 -97
  464. package/core/server/api/v3/utils/serializers/output/tags.js +0 -25
  465. package/core/server/api/v3/utils/serializers/output/themes.js +0 -25
  466. package/core/server/api/v3/utils/serializers/output/users.js +0 -74
  467. package/core/server/api/v3/utils/serializers/output/utils/clean.js +0 -166
  468. package/core/server/api/v3/utils/serializers/output/utils/date.js +0 -21
  469. package/core/server/api/v3/utils/serializers/output/utils/extra-attrs.js +0 -174
  470. package/core/server/api/v3/utils/serializers/output/utils/mapper.js +0 -197
  471. package/core/server/api/v3/utils/serializers/output/utils/post-gating.js +0 -39
  472. package/core/server/api/v3/utils/serializers/output/utils/settings-type-group-mapper.js +0 -24
  473. package/core/server/api/v3/utils/serializers/output/utils/url.js +0 -67
  474. package/core/server/api/v3/utils/serializers/output/webhooks.js +0 -15
  475. package/core/server/api/v3/utils/validators/index.js +0 -9
  476. package/core/server/api/v3/utils/validators/input/images.js +0 -85
  477. package/core/server/api/v3/utils/validators/input/index.js +0 -61
  478. package/core/server/api/v3/utils/validators/input/invitations.js +0 -49
  479. package/core/server/api/v3/utils/validators/input/invites.js +0 -21
  480. package/core/server/api/v3/utils/validators/input/labels.js +0 -6
  481. package/core/server/api/v3/utils/validators/input/members.js +0 -6
  482. package/core/server/api/v3/utils/validators/input/oembed.js +0 -17
  483. package/core/server/api/v3/utils/validators/input/pages.js +0 -46
  484. package/core/server/api/v3/utils/validators/input/passwordreset.js +0 -36
  485. package/core/server/api/v3/utils/validators/input/posts.js +0 -46
  486. package/core/server/api/v3/utils/validators/input/settings.js +0 -89
  487. package/core/server/api/v3/utils/validators/input/setup.js +0 -17
  488. package/core/server/api/v3/utils/validators/input/snippets.js +0 -6
  489. package/core/server/api/v3/utils/validators/input/tags.js +0 -6
  490. package/core/server/api/v3/utils/validators/input/users.js +0 -22
  491. package/core/server/api/v3/utils/validators/input/webhooks.js +0 -27
  492. package/core/server/api/v3/utils/validators/output/index.js +0 -1
  493. package/core/server/api/v3/utils/validators/utils/json-schema.js +0 -17
  494. package/core/server/api/v3/webhooks.js +0 -130
  495. package/core/server/data/migrations/utils.js +0 -571
  496. package/core/server/data/migrations/versions/1.13/1-custom-template-post.js +0 -7
  497. package/core/server/data/migrations/versions/1.13/2-theme-permissions.js +0 -58
  498. package/core/server/data/migrations/versions/1.18/1-add-webhooks-table.js +0 -2
  499. package/core/server/data/migrations/versions/1.19/1-webhook-permissions.js +0 -31
  500. package/core/server/data/migrations/versions/1.20/1-remove-settings-keys.js +0 -65
  501. package/core/server/data/migrations/versions/1.21/1-add-contributor-role.js +0 -58
  502. package/core/server/data/migrations/versions/1.22/1-multiple-authors-DDL.js +0 -2
  503. package/core/server/data/migrations/versions/1.22/1-multiple-authors-DML.js +0 -63
  504. package/core/server/data/migrations/versions/1.25/1-update-koenig-beta-html.js +0 -70
  505. package/core/server/data/migrations/versions/1.25/2-demo-post.js +0 -55
  506. package/core/server/data/migrations/versions/1.3/1-post-excerpt.js +0 -7
  507. package/core/server/data/migrations/versions/1.4/1-codeinjection-post.js +0 -14
  508. package/core/server/data/migrations/versions/1.5/1-og-twitter-post.js +0 -34
  509. package/core/server/data/migrations/versions/1.7/1-add-backup-client.js +0 -10
  510. package/core/server/data/migrations/versions/1.9/1-add-permissions-redirect.js +0 -23
  511. package/core/server/data/migrations/versions/2.0/1-rename-amp-column.js +0 -44
  512. package/core/server/data/migrations/versions/2.0/2-update-posts.js +0 -7
  513. package/core/server/data/migrations/versions/2.0/3-remove-koenig-labs.js +0 -42
  514. package/core/server/data/migrations/versions/2.0/4-permalink-setting.js +0 -85
  515. package/core/server/data/migrations/versions/2.0/5-remove-demo-post.js +0 -85
  516. package/core/server/data/migrations/versions/2.0/6-replace-fixture-posts.js +0 -10
  517. package/core/server/data/migrations/versions/2.13/1-remove-empty-strings.js +0 -5
  518. package/core/server/data/migrations/versions/2.14/1-add-actions-table.js +0 -2
  519. package/core/server/data/migrations/versions/2.14/2-add-actions-permissions.js +0 -12
  520. package/core/server/data/migrations/versions/2.15/1-add-type-column-to-integrations.js +0 -8
  521. package/core/server/data/migrations/versions/2.15/2-insert-zapier-integration.js +0 -69
  522. package/core/server/data/migrations/versions/2.16/1-add-members-perrmissions.js +0 -1
  523. package/core/server/data/migrations/versions/2.17/1-normalize-settings.js +0 -74
  524. package/core/server/data/migrations/versions/2.17/2-posts-add-canonical-url.js +0 -7
  525. package/core/server/data/migrations/versions/2.18/1-restore-settings-from-backup.js +0 -134
  526. package/core/server/data/migrations/versions/2.2/1-add-sessions-table.js +0 -2
  527. package/core/server/data/migrations/versions/2.2/2-add-integrations-and-api-key-tables.js +0 -6
  528. package/core/server/data/migrations/versions/2.2/3-insert-admin-integration-role.js +0 -83
  529. package/core/server/data/migrations/versions/2.2/4-insert-integration-and-api-key-permissions.js +0 -77
  530. package/core/server/data/migrations/versions/2.2/5-add-mobiledoc-revisions-table.js +0 -2
  531. package/core/server/data/migrations/versions/2.21/1-update-editor-permissions.js +0 -28
  532. package/core/server/data/migrations/versions/2.22/1-add-member-permissions-to-roles.js +0 -47
  533. package/core/server/data/migrations/versions/2.27/1-insert-ghost-db-backup-role.js +0 -83
  534. package/core/server/data/migrations/versions/2.27/2-insert-db-backup-integration.js +0 -69
  535. package/core/server/data/migrations/versions/2.27/3-add-subdirectory-to-relative-canonical-urls.js +0 -100
  536. package/core/server/data/migrations/versions/2.28/1-add-db-backup-content-permission.js +0 -9
  537. package/core/server/data/migrations/versions/2.28/2-add-db-backup-content-permission-to-roles.js +0 -15
  538. package/core/server/data/migrations/versions/2.28/3-insert-ghost-scheduler-role.js +0 -84
  539. package/core/server/data/migrations/versions/2.28/4-insert-scheduler-integration.js +0 -69
  540. package/core/server/data/migrations/versions/2.28/5-add-scheduler-permission-to-roles.js +0 -23
  541. package/core/server/data/migrations/versions/2.28/6-add-type-column.js +0 -6
  542. package/core/server/data/migrations/versions/2.28/7-populate-type-column.js +0 -6
  543. package/core/server/data/migrations/versions/2.28/8-remove-page-column.js +0 -6
  544. package/core/server/data/migrations/versions/2.29/1-add-post-page-column.js +0 -20
  545. package/core/server/data/migrations/versions/2.29/2-populate-post-page-column.js +0 -98
  546. package/core/server/data/migrations/versions/2.29/3-remove-page-type-column.js +0 -15
  547. package/core/server/data/migrations/versions/2.3/1-add-webhook-columns.js +0 -45
  548. package/core/server/data/migrations/versions/2.3/2-add-webhook-edit-permission.js +0 -9
  549. package/core/server/data/migrations/versions/2.31/1-remove-name-and-password-from-members-table.js +0 -15
  550. package/core/server/data/migrations/versions/2.32/01-add-members-stripe-customers-table.js +0 -4
  551. package/core/server/data/migrations/versions/2.32/02-add-name-to-members-table.js +0 -7
  552. package/core/server/data/migrations/versions/2.33/01-correct-members-stripe-customers-table.js +0 -37
  553. package/core/server/data/migrations/versions/2.34/01-add-stripe-customers-subscriptions-table.js +0 -2
  554. package/core/server/data/migrations/versions/2.34/02-add-email-to-members-stripe-customers-table.js +0 -7
  555. package/core/server/data/migrations/versions/2.34/03-add-name-to-members-stripe-customers-table.js +0 -7
  556. package/core/server/data/migrations/versions/2.35/01-add-note-to-members-table.js +0 -7
  557. package/core/server/data/migrations/versions/2.37/01-add-self-signup-and-from address-to-members-settings.js +0 -67
  558. package/core/server/data/migrations/versions/2.6/1-add-webhook-permission-roles.js +0 -31
  559. package/core/server/data/migrations/versions/2.8/1-add-members-table.js +0 -2
  560. package/core/server/data/migrations/versions/3.0/01-remove-user-ghost-auth-columns.js +0 -14
  561. package/core/server/data/migrations/versions/3.0/02-drop-token-auth-tables.js +0 -31
  562. package/core/server/data/migrations/versions/3.0/03-drop-client-auth-tables.js +0 -35
  563. package/core/server/data/migrations/versions/3.0/04-add-posts-meta-table.js +0 -2
  564. package/core/server/data/migrations/versions/3.0/05-populate-posts-meta-table.js +0 -83
  565. package/core/server/data/migrations/versions/3.0/06-remove-posts-meta-columns.js +0 -44
  566. package/core/server/data/migrations/versions/3.0/07-add-posts-type-column.js +0 -8
  567. package/core/server/data/migrations/versions/3.0/08-populate-posts-type-column.js +0 -94
  568. package/core/server/data/migrations/versions/3.0/09-remove-posts-page-column.js +0 -7
  569. package/core/server/data/migrations/versions/3.0/10-remove-empty-strings.js +0 -81
  570. package/core/server/data/migrations/versions/3.0/11-update-posts-html.js +0 -7
  571. package/core/server/data/migrations/versions/3.0/12-populate-members-table-from-subscribers.js +0 -54
  572. package/core/server/data/migrations/versions/3.0/13-drop-subscribers-table.js +0 -34
  573. package/core/server/data/migrations/versions/3.0/14-remove-subscribers-flag.js +0 -24
  574. package/core/server/data/migrations/versions/3.1/01-add-send-email-when-published-to-posts.js +0 -7
  575. package/core/server/data/migrations/versions/3.1/02-add-email-subject-to-posts-meta.js +0 -7
  576. package/core/server/data/migrations/versions/3.1/03-add-email-preview-permissions.js +0 -18
  577. package/core/server/data/migrations/versions/3.1/04-add-subscribed-flag-to-members.js +0 -7
  578. package/core/server/data/migrations/versions/3.1/05-add-emails-table.js +0 -2
  579. package/core/server/data/migrations/versions/3.1/06-add-email-permissions.js +0 -15
  580. package/core/server/data/migrations/versions/3.1/07-add-uuid-field-to-members.js +0 -8
  581. package/core/server/data/migrations/versions/3.1/08-add-uuid-values-to-members.js +0 -23
  582. package/core/server/data/migrations/versions/3.1/09-add-further-email-permissions.js +0 -25
  583. package/core/server/data/migrations/versions/3.1/10-add-email-error-data-column.js +0 -8
  584. package/core/server/data/migrations/versions/3.11/01-remove-broken-complimentary-plan-from-members-settings.js +0 -68
  585. package/core/server/data/migrations/versions/3.12/01-add-identity-permission.js +0 -7
  586. package/core/server/data/migrations/versions/3.12/02-remove-legacy-is-paid-flag-from-settings.js +0 -93
  587. package/core/server/data/migrations/versions/3.18/01-add-email-preview-permissions-to-roles.js +0 -39
  588. package/core/server/data/migrations/versions/3.18/02-add-members_stripe_connect-auth-permissions.js +0 -7
  589. package/core/server/data/migrations/versions/3.19/01-update-member-from-email-address.js +0 -91
  590. package/core/server/data/migrations/versions/3.2/01-add-cancel-at-period-end-to-subscriptions.js +0 -7
  591. package/core/server/data/migrations/versions/3.22/01-removed-legacy-values-from-settings-table.js +0 -65
  592. package/core/server/data/migrations/versions/3.22/02-settings-key-renames.js +0 -90
  593. package/core/server/data/migrations/versions/3.22/03-add-group-and-flags-to-settings.js +0 -15
  594. package/core/server/data/migrations/versions/3.22/04-populate-settings-groups-and-flags.js +0 -194
  595. package/core/server/data/migrations/versions/3.22/05-migrate-members-subscription-settings.js +0 -182
  596. package/core/server/data/migrations/versions/3.22/06-migrate-stripe-connect-settings.js +0 -132
  597. package/core/server/data/migrations/versions/3.22/07-update-type-for-settings.js +0 -137
  598. package/core/server/data/migrations/versions/3.23/01-migrate-bulk-email-settings.js +0 -65
  599. package/core/server/data/migrations/versions/3.23/02-remove-bulk-email-settings.js +0 -48
  600. package/core/server/data/migrations/versions/3.23/03-update-portal-button-setting.js +0 -24
  601. package/core/server/data/migrations/versions/3.23/04-add-meta-columns-to-tags-table.js +0 -54
  602. package/core/server/data/migrations/versions/3.24/01-populate-group-for-new-portal-settings.js +0 -38
  603. package/core/server/data/migrations/versions/3.25/01-add-members-stripe-webhook-settings.js +0 -22
  604. package/core/server/data/migrations/versions/3.26/01-add-amp-gtag-id-setting.js +0 -20
  605. package/core/server/data/migrations/versions/3.29/01-remove-duplicate-subscriptions.js +0 -53
  606. package/core/server/data/migrations/versions/3.29/02-remove-duplicate-customers.js +0 -53
  607. package/core/server/data/migrations/versions/3.29/03-remove-orphaned-customers.js +0 -35
  608. package/core/server/data/migrations/versions/3.29/04-remove-orphaned-subscriptions.js +0 -35
  609. package/core/server/data/migrations/versions/3.29/05-add-member-constraints.js +0 -177
  610. package/core/server/data/migrations/versions/3.30/01-add-member-signin-url-permission-roles.js +0 -8
  611. package/core/server/data/migrations/versions/3.32/01-add-member-support-address-setting.js +0 -27
  612. package/core/server/data/migrations/versions/3.32/02-add-member-reply-address-setting.js +0 -20
  613. package/core/server/data/migrations/versions/3.32/03-add-routes-hash-setting.js +0 -20
  614. package/core/server/data/migrations/versions/3.33/01-add-email-recipients-tables.js +0 -8
  615. package/core/server/data/migrations/versions/3.34/01-add-tokens-table.js +0 -2
  616. package/core/server/data/migrations/versions/3.35/01-add-address-columns-to-emails-table.js +0 -14
  617. package/core/server/data/migrations/versions/3.36/01-add-snippets-table.js +0 -2
  618. package/core/server/data/migrations/versions/3.36/02-add-snippets-permissions.js +0 -56
  619. package/core/server/data/migrations/versions/3.37/01-update-portal-button-setting.js +0 -30
  620. package/core/server/data/migrations/versions/3.38/01-add-email-recipient-filter-column.js +0 -8
  621. package/core/server/data/migrations/versions/3.38/02-populate-email-recipient-filter-column.js +0 -34
  622. package/core/server/data/migrations/versions/3.38/03-add-recipient-filter-column.js +0 -8
  623. package/core/server/data/migrations/versions/3.38/04-populate-recipient-filter-column.js +0 -49
  624. package/core/server/data/migrations/versions/3.38/05-add-emails-track-opens-column.js +0 -7
  625. package/core/server/data/migrations/versions/3.38/06-add-newsletter-settings.js +0 -16
  626. package/core/server/data/migrations/versions/3.38/07-migrate-newsletter-settings-from-config.js +0 -48
  627. package/core/server/data/migrations/versions/3.38/08-repopulate-send-email-when-published-down-migration.js +0 -25
  628. package/core/server/data/migrations/versions/3.38/09-remove-send-email-when-published-column.js +0 -7
  629. package/core/server/data/migrations/versions/3.39/01-add-members-signup-redirect-settings.js +0 -16
  630. package/core/server/data/migrations/versions/3.39/02-add-user-id-to-api-keys-table.js +0 -7
  631. package/core/server/data/migrations/versions/3.39/03-add-email-track-opens-setting.js +0 -16
  632. package/core/server/data/migrations/versions/3.39/04-add-cancellation-reason-column.js +0 -7
  633. package/core/server/data/migrations/versions/3.39/05-remove-unused-columns-on-emails.js +0 -14
  634. package/core/server/data/migrations/versions/3.39/06-add-email-recipient-index.js +0 -58
  635. package/core/server/data/migrations/versions/3.39/07-add-email-recipients-event-timestamps.js +0 -19
  636. package/core/server/data/migrations/versions/3.39/08-add-email-stats-columns.js +0 -22
  637. package/core/server/data/migrations/versions/3.40/01-add-members-email-open-rate-column.js +0 -8
  638. package/core/server/data/migrations/versions/3.40/02-add members-email-aggregation-columns.js +0 -16
  639. package/core/server/data/migrations/versions/3.40/03-populate-members-email-counts.js +0 -15
  640. package/core/server/data/migrations/versions/3.41/01-add-firstpromoter-settings.js +0 -16
  641. package/core/server/data/migrations/versions/3.6/1-add-labels-table.js +0 -2
  642. package/core/server/data/migrations/versions/3.6/2-add-members-labels-table.js +0 -2
  643. package/core/server/data/migrations/versions/3.6/3-add-labels-permissions.js +0 -47
  644. package/core/server/data/migrations/versions/3.7/01-fix-incorrect-member-labels-foreign-keys.js +0 -46
  645. package/core/server/data/migrations/versions/3.8/01-add-geolocation-to-members.js +0 -7
  646. package/core/server/data/migrations/versions/3.9/01-add-member-sigin-url-permissions.js +0 -7
  647. package/core/server/services/mail/utils.js +0 -34
  648. package/core/server/services/url/configs/canary.js +0 -143
  649. package/core/server/services/url/configs/v3.js +0 -141
  650. package/core/server/services/url/configs/v4.js +0 -143
  651. package/core/server/web/api/v2/admin/app.js +0 -43
  652. package/core/server/web/api/v2/admin/middleware.js +0 -85
  653. package/core/server/web/api/v2/admin/routes.js +0 -200
  654. package/core/server/web/api/v2/content/app.js +0 -38
  655. package/core/server/web/api/v2/content/middleware.js +0 -23
  656. package/core/server/web/api/v2/content/routes.js +0 -37
  657. package/core/server/web/api/v3/admin/app.js +0 -43
  658. package/core/server/web/api/v3/admin/middleware.js +0 -89
  659. package/core/server/web/api/v3/admin/routes.js +0 -267
  660. package/core/server/web/api/v3/content/app.js +0 -38
  661. package/core/server/web/api/v3/content/middleware.js +0 -23
  662. package/core/server/web/api/v3/content/routes.js +0 -37
  663. package/core/server/web/oauth/app.js +0 -153
  664. package/core/server/web/oauth/index.js +0 -1
@@ -1,5 +1,6 @@
1
1
  const Promise = require('bluebird');
2
2
  const crypto = require('crypto');
3
+ const tpl = require('@tryghost/tpl');
3
4
 
4
5
  class Gravatar {
5
6
  constructor({config, request}) {
@@ -7,21 +8,36 @@ class Gravatar {
7
8
  this.request = request;
8
9
  }
9
10
 
11
+ url(email, options) {
12
+ if (options.default) {
13
+ // tpl errors on token `{default}` so we use `{_default}` instead
14
+ // but still allow the option to be passed as `default`
15
+ options._default = options.default;
16
+ }
17
+ const defaultOptions = {
18
+ size: 250,
19
+ _default: 'blank',
20
+ rating: 'g'
21
+ };
22
+ const emailHash = crypto.createHash('md5').update(email.toLowerCase().trim()).digest('hex');
23
+ const gravatarUrl = this.config.get('gravatar').url;
24
+ return tpl(gravatarUrl, Object.assign(defaultOptions, options, {hash: emailHash}));
25
+ }
26
+
10
27
  lookup(userData, timeout) {
11
- let gravatarUrl = '//www.gravatar.com/avatar/' +
12
- crypto.createHash('md5').update(userData.email.toLowerCase().trim()).digest('hex') +
13
- '?s=250';
14
-
15
28
  if (this.config.isPrivacyDisabled('useGravatar')) {
16
29
  return Promise.resolve();
17
30
  }
18
-
19
- return Promise.resolve(this.request('https:' + gravatarUrl + '&d=404&r=x', {timeout: timeout || 2 * 1000}))
31
+
32
+ // test existence using a default 404, but return a different default
33
+ // so we still have a fallback if the image gets removed from Gravatar
34
+ const testUrl = this.url(userData.email, {default: 404, rating: 'x'});
35
+ const imageUrl = this.url(userData.email, {default: 'mp', rating: 'x'});
36
+
37
+ return Promise.resolve(this.request(testUrl, {timeout: timeout || 2 * 1000}))
20
38
  .then(function () {
21
- gravatarUrl += '&d=mm&r=x';
22
-
23
39
  return {
24
- image: gravatarUrl
40
+ image: imageUrl
25
41
  };
26
42
  })
27
43
  .catch({statusCode: 404}, function () {
@@ -1,36 +1,13 @@
1
1
  const omit = require('lodash/omit');
2
- const crypto = require('crypto');
2
+ const security = require('@tryghost/security');
3
3
  const ghostBookshelf = require('./base');
4
4
  const {Role} = require('./role');
5
5
 
6
- /*
7
- * Uses birthday problem estimation to calculate chance of collision
8
- * d = 16^26 // 26 char hex string
9
- * n = 10,000,000 // 10 million
10
- *
11
- * (-n x (n-1)) / 2d
12
- * 1 - e^
13
- *
14
- *
15
- * 17
16
- * ~= 4 x 10^
17
- *
18
- * ref: https://medium.freecodecamp.org/how-long-should-i-make-my-api-key-833ebf2dc26f
19
- * ref: https://en.wikipedia.org/wiki/Birthday_problem#Approximations
20
- *
21
- * 26 char hex string = 13 bytes
22
- * 64 char hex string JWT secret = 32 bytes
23
- */
24
- const createSecret = (type) => {
25
- const bytes = type === 'content' ? 13 : 32;
26
- return crypto.randomBytes(bytes).toString('hex');
27
- };
28
-
29
6
  const ApiKey = ghostBookshelf.Model.extend({
30
7
  tableName: 'api_keys',
31
8
 
32
9
  defaults() {
33
- const secret = createSecret(this.get('type'));
10
+ const secret = security.secret.create(this.get('type'));
34
11
 
35
12
  return {
36
13
  secret
@@ -97,7 +74,7 @@ const ApiKey = ghostBookshelf.Model.extend({
97
74
  }
98
75
  }, {
99
76
  refreshSecret(data, options) {
100
- const secret = createSecret(data.type);
77
+ const secret = security.secret.create(data.type);
101
78
  return this.edit(Object.assign({}, data, {secret}), options);
102
79
  }
103
80
  });
@@ -52,9 +52,9 @@ async function editMultiple(knex, table, chunk, options) {
52
52
  await knex(table).whereIn('id', chunk).update(options.data);
53
53
  }
54
54
 
55
- async function delSingle(knex, table, id) {
55
+ async function delSingle(knex, table, id, options) {
56
56
  try {
57
- await knex(table).where('id', id).del();
57
+ await knex(table).where(options.column ?? 'id', id).del();
58
58
  } catch (err) {
59
59
  const importError = new errors.DataImportError({
60
60
  message: `Failed to remove entry from ${table}`,
@@ -66,8 +66,8 @@ async function delSingle(knex, table, id) {
66
66
  }
67
67
  }
68
68
 
69
- async function delMultiple(knex, table, chunk) {
70
- await knex(table).whereIn('id', chunk).del();
69
+ async function delMultiple(knex, table, chunk, options) {
70
+ await knex(table).whereIn(options.column ?? 'id', chunk).del();
71
71
  }
72
72
 
73
73
  const insert = createBulkOperation(insertSingle, insertMultiple);
@@ -91,10 +91,18 @@ module.exports = function (Bookshelf) {
91
91
  return edit(Bookshelf.knex, tableName, data, options);
92
92
  },
93
93
 
94
- bulkDestroy: function bulkDestroy(data, tableName) {
94
+ /**
95
+ *
96
+ * @param {string[]} data List of ids to delete
97
+ * @param {*} tableName
98
+ * @param {Object} [options]
99
+ * @param {string} [options.column] Delete the rows where this column equals the ids in `data` (defaults to 'id')
100
+ * @returns
101
+ */
102
+ bulkDestroy: function bulkDestroy(data, tableName, options = {}) {
95
103
  tableName = tableName || this.prototype.tableName;
96
104
 
97
- return del(Bookshelf.knex, tableName, data);
105
+ return del(Bookshelf.knex, tableName, data, options);
98
106
  }
99
107
  });
100
108
  };
@@ -1,3 +1,4 @@
1
+ const _ = require('lodash');
1
2
  const limitService = require('../services/limits');
2
3
  const ghostBookshelf = require('./base');
3
4
  const {NoPermissionError} = require('@tryghost/errors');
@@ -64,6 +65,14 @@ const Integration = ghostBookshelf.Model.extend({
64
65
  return options;
65
66
  },
66
67
 
68
+ defaultRelations: function defaultRelations(methodName, options) {
69
+ if (['edit', 'add', 'destroy'].indexOf(methodName) !== -1) {
70
+ options.withRelated = _.union(['api_keys'], options.withRelated || []);
71
+ }
72
+
73
+ return options;
74
+ },
75
+
67
76
  async permissible(integrationModel, action, context, attrs, loadedPerms, hasUserPermission, hasApiKeyPermission) {
68
77
  const isAdd = (action === 'add');
69
78
 
@@ -76,6 +85,14 @@ const Integration = ghostBookshelf.Model.extend({
76
85
  if (!hasUserPermission || !hasApiKeyPermission) {
77
86
  throw new NoPermissionError();
78
87
  }
88
+ },
89
+
90
+ async getInternalFrontendKey(options) {
91
+ options = options || {};
92
+
93
+ options.withRelated = ['api_keys'];
94
+
95
+ return this.findOne({slug: 'ghost-internal-frontend'}, options);
79
96
  }
80
97
  });
81
98
 
@@ -2,7 +2,7 @@ const ghostBookshelf = require('./base');
2
2
  const uuid = require('uuid');
3
3
  const _ = require('lodash');
4
4
  const config = require('../../shared/config');
5
- const crypto = require('crypto');
5
+ const {gravatar} = require('../lib/image');
6
6
 
7
7
  const Member = ghostBookshelf.Model.extend({
8
8
  tableName: 'members',
@@ -10,7 +10,6 @@ const Member = ghostBookshelf.Model.extend({
10
10
  defaults() {
11
11
  return {
12
12
  status: 'free',
13
- subscribed: true,
14
13
  uuid: uuid.v4(),
15
14
  email_count: 0,
16
15
  email_opened_count: 0
@@ -30,6 +29,12 @@ const Member = ghostBookshelf.Model.extend({
30
29
  }, {
31
30
  key: 'products',
32
31
  replacement: 'products.slug'
32
+ }, {
33
+ key: 'tier',
34
+ replacement: 'products.slug'
35
+ }, {
36
+ key: 'tiers',
37
+ replacement: 'products.slug'
33
38
  }, {
34
39
  key: 'newsletters',
35
40
  replacement: 'newsletters.slug'
@@ -311,8 +316,7 @@ const Member = ghostBookshelf.Model.extend({
311
316
  // Will not use gravatar if privacy.useGravatar is false in config
312
317
  attrs.avatar_image = null;
313
318
  if (attrs.email && !config.isPrivacyDisabled('useGravatar')) {
314
- const emailHash = crypto.createHash('md5').update(attrs.email.toLowerCase().trim()).digest('hex');
315
- attrs.avatar_image = `https://gravatar.com/avatar/${emailHash}?s=250&d=blank`;
319
+ attrs.avatar_image = gravatar.url(attrs.email, {size: 250, default: 'blank'});
316
320
  }
317
321
 
318
322
  return attrs;
@@ -38,6 +38,11 @@ const Newsletter = ghostBookshelf.Model.extend({
38
38
  return this.hasMany('Post');
39
39
  },
40
40
 
41
+ // Force active newsletters for content API
42
+ enforcedFilters: function enforcedFilters(options) {
43
+ return (options.context && options.context.public) ? 'status:active' : null;
44
+ },
45
+
41
46
  async onSaving(model, _attr, options) {
42
47
  ghostBookshelf.Model.prototype.onSaving.apply(this, arguments);
43
48
 
@@ -99,6 +104,28 @@ const Newsletter = ghostBookshelf.Model.extend({
99
104
  return attrs;
100
105
  }
101
106
  }, {
107
+ /**
108
+ * Returns an array of keys permitted in a method's `options` hash, depending on the current method.
109
+ * @param {String} methodName The name of the method to check valid options for.
110
+ * @return {Array} Keys allowed in the `options` hash of the model's method.
111
+ */
112
+ permittedOptions: function permittedOptions(methodName) {
113
+ let options = ghostBookshelf.Model.permittedOptions.call(this, methodName);
114
+
115
+ // allowlists for the `options` hash argument on methods, by method name.
116
+ // these are the only options that can be passed to Bookshelf / Knex.
117
+ const validOptions = {
118
+ findOne: ['filter'],
119
+ findAll: ['filter']
120
+ };
121
+
122
+ if (validOptions[methodName]) {
123
+ options = options.concat(validOptions[methodName]);
124
+ }
125
+
126
+ return options;
127
+ },
128
+
102
129
  orderDefaultRaw: function () {
103
130
  return 'sort_order ASC, created_at ASC, id ASC';
104
131
  },
@@ -16,12 +16,16 @@ const mobiledocLib = require('../lib/mobiledoc');
16
16
  const relations = require('./relations');
17
17
  const urlUtils = require('../../shared/url-utils');
18
18
  const {Tag} = require('./tag');
19
+ const {Newsletter} = require('./newsletter');
20
+ const {BadRequestError} = require('@tryghost/errors');
19
21
 
20
22
  const messages = {
21
23
  isAlreadyPublished: 'Your post is already published, please reload your page.',
22
24
  valueCannotBeBlank: 'Value in {key} cannot be blank.',
23
25
  expectedPublishedAtInFuture: 'Date must be at least {cannotScheduleAPostBeforeInMinutes} minutes in the future.',
24
- untitled: '(Untitled)'
26
+ untitled: '(Untitled)',
27
+ notEnoughPermission: 'You do not have permission to perform this action',
28
+ invalidNewsletter: 'The newsletter parameter doesn\'t match any active newsletter.'
25
29
  };
26
30
 
27
31
  const MOBILEDOC_REVISIONS_COUNT = 10;
@@ -78,7 +82,7 @@ Post = ghostBookshelf.Model.extend({
78
82
  type: 'post',
79
83
  tiers,
80
84
  visibility: visibility,
81
- email_recipient_filter: 'none'
85
+ email_recipient_filter: 'all'
82
86
  };
83
87
  },
84
88
 
@@ -135,14 +139,6 @@ Post = ghostBookshelf.Model.extend({
135
139
  }
136
140
  });
137
141
 
138
- // update legacy email_recipient_filter values to proper NQL
139
- if (attrs.email_recipient_filter === 'free') {
140
- attrs.email_recipient_filter = 'status:free';
141
- }
142
- if (attrs.email_recipient_filter === 'paid') {
143
- attrs.email_recipient_filter = 'status:-free';
144
- }
145
-
146
142
  return attrs;
147
143
  },
148
144
 
@@ -186,14 +182,6 @@ Post = ghostBookshelf.Model.extend({
186
182
  }
187
183
  });
188
184
 
189
- // update legacy email_recipient_filter values to proper NQL
190
- if (attrs.email_recipient_filter === 'free') {
191
- attrs.email_recipient_filter = 'status:free';
192
- }
193
- if (attrs.email_recipient_filter === 'paid') {
194
- attrs.email_recipient_filter = 'status:-free';
195
- }
196
-
197
185
  // transform visibility NQL queries to special-case values where necessary
198
186
  // ensures checks against special-case values such as `{{#has visibility="paid"}}` continue working
199
187
  if (attrs.visibility && !['public', 'members', 'paid', 'tiers'].includes(attrs.visibility)) {
@@ -638,7 +626,7 @@ Post = ghostBookshelf.Model.extend({
638
626
  if (this.get('html') === null) {
639
627
  plaintext = null;
640
628
  } else {
641
- plaintext = htmlToPlaintext(this.get('html'));
629
+ plaintext = htmlToPlaintext.excerpt(this.get('html'));
642
630
  }
643
631
 
644
632
  // CASE: html is e.g. <p></p>
@@ -674,20 +662,30 @@ Post = ghostBookshelf.Model.extend({
674
662
  }
675
663
  }
676
664
 
677
- // newsletter_id is read-only and should only be set using a query param when publishing/scheduling
678
- if (options.newsletter_id
665
+ // newsletter_id is read-only and should only be set using the newsletter param when publishing/scheduling
666
+ if (options.newsletter
679
667
  && !this.get('newsletter_id')
680
668
  && this.hasChanged('status')
681
669
  && (newStatus === 'published' || newStatus === 'scheduled')) {
682
- this.set('newsletter_id', options.newsletter_id);
683
- }
670
+ // Map the passed slug to the id + validate the passed newsletter
671
+ ops.push(async () => {
672
+ const newsletter = await Newsletter.findOne({slug: options.newsletter}, {transacting: options.transacting, filter: 'status:active'});
673
+ if (!newsletter) {
674
+ throw new BadRequestError({
675
+ message: messages.invalidNewsletter
676
+ });
677
+ }
678
+ this.set('newsletter_id', newsletter.id);
679
+ });
684
680
 
685
- // email_recipient_filter is read-only and should only be set using a query param when publishing/scheduling
686
- if (options.email_recipient_filter
687
- && (options.email_recipient_filter !== 'none')
688
- && this.hasChanged('status')
689
- && (newStatus === 'published' || newStatus === 'scheduled')) {
690
- this.set('email_recipient_filter', options.email_recipient_filter);
681
+ // If the `email_segment` isn't passed at the same time, reset it to be 100% sure that they can only be used together
682
+ this.set('email_recipient_filter', 'all');
683
+
684
+ // email_segment is read-only and should only be set using a query param when publishing/scheduling
685
+ // we can't set it if we don't pass newsletter
686
+ if (options.email_segment) {
687
+ this.set('email_recipient_filter', options.email_segment);
688
+ }
691
689
  }
692
690
 
693
691
  // ensure draft posts have the email_recipient_filter reset unless an email has already been sent
@@ -695,7 +693,7 @@ Post = ghostBookshelf.Model.extend({
695
693
  ops.push(function ensureSendEmailWhenPublishedIsUnchanged() {
696
694
  return self.related('email').fetch({transacting: options.transacting}).then((email) => {
697
695
  if (!email) {
698
- self.set('email_recipient_filter', 'none');
696
+ self.set('email_recipient_filter', 'all');
699
697
  self.set('newsletter_id', null);
700
698
  }
701
699
  });
@@ -862,7 +860,7 @@ Post = ghostBookshelf.Model.extend({
862
860
  * This is protected by the fn `permittedOptions`.
863
861
  */
864
862
  defaultColumnsToFetch: function defaultColumnsToFetch() {
865
- return ['id', 'published_at', 'slug', 'author_id'];
863
+ return ['id', 'published_at', 'slug'];
866
864
  },
867
865
  /**
868
866
  * If the `formats` option is not used, we return `html` be default.
@@ -1029,7 +1027,7 @@ Post = ghostBookshelf.Model.extend({
1029
1027
  findPage: ['status'],
1030
1028
  findAll: ['columns', 'filter'],
1031
1029
  destroy: ['destroyAll', 'destroyBy'],
1032
- edit: ['filter', 'email_recipient_filter', 'force_rerender', 'newsletter_id']
1030
+ edit: ['filter', 'email_segment', 'force_rerender', 'newsletter']
1033
1031
  };
1034
1032
 
1035
1033
  // The post model additionally supports having a formats option
@@ -17,13 +17,7 @@ const messages = {
17
17
  * We fetch the `authors` relations when you either request `withRelated=['authors']` or `withRelated=['author`].
18
18
  * The old `author` relation was removed, but we still have to support this case.
19
19
  *
20
- * # CASE 2
21
- * We fetch when editing a post.
22
- * Imagine you change `author_id` and you have 3 existing `posts_authors`.
23
- * We now need to set `author_id` as primary author `post.authors[0]`.
24
- * Furthermore, we now longer have a `author` relationship.
25
- *
26
- * # CASE 3:
20
+ * # CASE 2:
27
21
  * If you request `include=author`, we have to fill this object with `post.authors[0]`.
28
22
  * Otherwise we can't return `post.author = User`.
29
23
  *
@@ -85,19 +79,10 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
85
79
  return proto.onFetchingCollection.call(this, collection, attrs, options);
86
80
  },
87
81
 
88
- // NOTE: sending `post.author = {}` was always ignored [unsupported]
89
82
  onCreating: function onCreating(model, attrs, options) {
90
- if (!model.get('author_id')) {
91
- if (model.get('authors')) {
92
- model.set('author_id', model.get('authors')[0].id);
93
- } else {
94
- model.set('author_id', this.contextUser(options));
95
- }
96
- }
97
-
98
83
  if (!model.get('authors')) {
99
84
  model.set('authors', [{
100
- id: model.get('author_id')
85
+ id: this.contextUser(options)
101
86
  }]);
102
87
  }
103
88
 
@@ -141,44 +126,6 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
141
126
  }
142
127
 
143
128
  ops.push(() => {
144
- // CASE: `post.author_id` has changed
145
- if (model.hasChanged('author_id')) {
146
- // CASE: you don't send `post.authors`
147
- // SOLUTION: we have to update the primary author
148
- if (!model.get('authors')) {
149
- let existingAuthors = model.related('authors').toJSON();
150
-
151
- // CASE: override primary author
152
- existingAuthors[0] = {
153
- id: model.get('author_id')
154
- };
155
-
156
- model.set('authors', existingAuthors);
157
- } else {
158
- // CASE: you send `post.authors` next to `post.author_id`
159
- if (model.get('authors')[0].id !== model.get('author_id')) {
160
- model.set('author_id', model.get('authors')[0].id);
161
- }
162
- }
163
- }
164
-
165
- // CASE: if you change `post.author_id`, we have to update the primary author
166
- // CASE: if the `author_id` has change and you pass `posts.authors`, we already check above that
167
- // the primary author id must be equal
168
- if (model.hasChanged('author_id') && !model.get('authors')) {
169
- let existingAuthors = model.related('authors').toJSON();
170
-
171
- // CASE: override primary author
172
- existingAuthors[0] = {
173
- id: model.get('author_id')
174
- };
175
-
176
- model.set('authors', existingAuthors);
177
- } else if (model.get('authors') && model.get('authors').length) {
178
- // ensure we update the primary author id
179
- model.set('author_id', model.get('authors')[0].id);
180
- }
181
-
182
129
  return proto.onSaving.call(this, model, attrs, options);
183
130
  });
184
131
 
@@ -207,14 +154,6 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
207
154
  }
208
155
 
209
156
  attrs.author = attrs.authors[0];
210
- delete attrs.author_id;
211
- } else {
212
- // CASE: we return `post.author=id` with or without requested columns.
213
- // @NOTE: this serialization should be moved into api layer, it's not being moved as it's deprecated
214
- if (!options.columns || (options.columns && options.columns.indexOf('author') !== -1)) {
215
- attrs.author = attrs.author_id;
216
- delete attrs.author_id;
217
- }
218
157
  }
219
158
 
220
159
  // CASE: `posts.authors` was not requested, but fetched in specific cases (see top)
@@ -294,12 +233,14 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
294
233
  }
295
234
  }, {
296
235
  /**
297
- * ### destroyByAuthor
298
- * @param {[type]} options has context and id. Context is the user doing the destroy, id is the user to destroy
236
+ * ### reassignByAuthor
237
+ * @param {Object} unfilteredOptions has context and id. Context is the user doing the destroy, id is the user to destroy
238
+ * @param {string} unfilteredOptions.id
239
+ * @param {Object} unfilteredOptions.context
240
+ * @param {Object} unfilteredOptions.transacting
299
241
  */
300
- destroyByAuthor: function destroyByAuthor(unfilteredOptions) {
301
- let options = this.filterOptions(unfilteredOptions, 'destroyByAuthor', {extraAllowedProperties: ['id']});
302
- let postCollection = Posts.forge();
242
+ reassignByAuthor: async function reassignByAuthor(unfilteredOptions) {
243
+ let options = this.filterOptions(unfilteredOptions, 'reassignByAuthor', {extraAllowedProperties: ['id']});
303
244
  let authorId = options.id;
304
245
 
305
246
  if (!authorId) {
@@ -308,34 +249,76 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
308
249
  }));
309
250
  }
310
251
 
311
- // CASE: if you are the primary author of a post, the whole post and it's relations get's deleted.
312
- // `posts_authors` are automatically removed (bookshelf-relations)
313
- // CASE: if you are the secondary author of a post, you are just deleted as author.
314
- // must happen manually
315
- const destroyPost = (() => {
316
- return postCollection
317
- .query('where', 'author_id', '=', authorId)
318
- .fetch(options)
319
- .call('invokeThen', 'destroy', options)
320
- .then(function (response) {
321
- return (options.transacting || ghostBookshelf.knex)('posts_authors')
322
- .where('author_id', authorId)
323
- .del()
324
- .then(() => response);
325
- })
326
- .catch((err) => {
327
- throw new errors.InternalServerError({err: err});
328
- });
252
+ const reassignPost = (async () => {
253
+ let trx = options.transacting;
254
+ let knex = ghostBookshelf.knex;
255
+
256
+ try {
257
+ // There's only one possible owner per Ghost instance
258
+ const ownerUser = await knex('roles')
259
+ .transacting(trx)
260
+ .join('roles_users', 'roles.id', '=', 'roles_users.role_id')
261
+ .where('roles.name', 'Owner')
262
+ .select('roles_users.user_id');
263
+ const ownerId = ownerUser[0].user_id;
264
+
265
+ const authorsPosts = await knex('posts_authors')
266
+ .transacting(trx)
267
+ .where('author_id', authorId)
268
+ .select('post_id', 'sort_order');
269
+
270
+ const ownersPosts = await knex('posts_authors')
271
+ .transacting(trx)
272
+ .where('author_id', ownerId)
273
+ .select('post_id');
274
+
275
+ const authorsPrimaryPosts = authorsPosts.filter(ap => ap.sort_order === 0);
276
+ const primaryPostsWithOwnerCoauthor = _.intersectionBy(authorsPrimaryPosts, ownersPosts, 'post_id');
277
+ const primaryPostsWithOwnerCoauthorIds = primaryPostsWithOwnerCoauthor.map(post => post.post_id);
278
+
279
+ // remove author and bump owner's sort_order to 0 to make them a primary author
280
+ // remove author from posts
281
+ await knex('posts_authors')
282
+ .transacting(trx)
283
+ .whereIn('post_id', primaryPostsWithOwnerCoauthorIds)
284
+ .where('author_id', authorId)
285
+ .del();
286
+
287
+ // make the owner a primary author
288
+ await knex('posts_authors')
289
+ .transacting(trx)
290
+ .whereIn('post_id', primaryPostsWithOwnerCoauthorIds)
291
+ .where('author_id', ownerId)
292
+ .update('sort_order', 0);
293
+
294
+ const primaryPostsWithoutOwnerCoauthor = _.differenceBy(authorsPrimaryPosts, primaryPostsWithOwnerCoauthor, 'post_id');
295
+ const postsWithoutOwnerCoauthorIds = primaryPostsWithoutOwnerCoauthor.map(post => post.post_id);
296
+
297
+ // swap out current author with the owner
298
+ await knex('posts_authors')
299
+ .transacting(trx)
300
+ .whereIn('post_id', postsWithoutOwnerCoauthorIds)
301
+ .where('author_id', authorId)
302
+ .update('author_id', ownerId);
303
+
304
+ // remove author as secondary author from any other posts
305
+ await knex('posts_authors')
306
+ .transacting(trx)
307
+ .where('author_id', authorId)
308
+ .del();
309
+ } catch (err) {
310
+ throw new errors.InternalServerError({err: err});
311
+ }
329
312
  });
330
313
 
331
314
  if (!options.transacting) {
332
315
  return ghostBookshelf.transaction((transacting) => {
333
316
  options.transacting = transacting;
334
- return destroyPost();
317
+ return reassignPost();
335
318
  });
336
319
  }
337
320
 
338
- return destroyPost();
321
+ return reassignPost();
339
322
  },
340
323
 
341
324
  permissible: function permissible(postModelOrId, action, context, unsafeAttrs, loadedPermissions, hasUserPermission, hasApiKeyPermission) {
@@ -375,10 +358,6 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
375
358
  isAdd = (action === 'add');
376
359
  isDestroy = (action === 'destroy');
377
360
 
378
- function isChanging(attr) {
379
- return unsafeAttrs[attr] && unsafeAttrs[attr] !== postModel.get(attr);
380
- }
381
-
382
361
  function isChangingAuthors() {
383
362
  if (!unsafeAttrs.authors) {
384
363
  return false;
@@ -394,14 +373,10 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
394
373
  function isOwner() {
395
374
  let isCorrectOwner = true;
396
375
 
397
- if (!unsafeAttrs.author_id && !unsafeAttrs.authors) {
376
+ if (!unsafeAttrs.authors) {
398
377
  return false;
399
378
  }
400
379
 
401
- if (unsafeAttrs.author_id) {
402
- isCorrectOwner = unsafeAttrs.author_id && unsafeAttrs.author_id === context.user;
403
- }
404
-
405
380
  if (unsafeAttrs.authors) {
406
381
  isCorrectOwner = isCorrectOwner && unsafeAttrs.authors.length && unsafeAttrs.authors[0].id === context.user;
407
382
  }
@@ -418,13 +393,13 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
418
393
  }
419
394
 
420
395
  if (isContributor && isEdit) {
421
- hasUserPermission = !isChanging('author_id') && !isChangingAuthors() && isCoAuthor();
396
+ hasUserPermission = !isChangingAuthors() && isCoAuthor();
422
397
  } else if (isContributor && isAdd) {
423
398
  hasUserPermission = isOwner();
424
399
  } else if (isContributor && isDestroy) {
425
400
  hasUserPermission = isPrimaryAuthor();
426
401
  } else if (isAuthor && isEdit) {
427
- hasUserPermission = isCoAuthor() && !isChanging('author_id') && !isChangingAuthors();
402
+ hasUserPermission = isCoAuthor() && !isChangingAuthors();
428
403
  } else if (isAuthor && isAdd) {
429
404
  hasUserPermission = isOwner();
430
405
  } else if (postModel) {
@@ -444,7 +419,6 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
444
419
  // @TODO: we need a concept for making a diff between incoming authors and existing authors
445
420
  // @TODO: for now we simply re-use the new concept of `excludedAttrs`
446
421
  // We only check the primary author of `authors`, any other change will be ignored.
447
- // By this we can deprecate `author_id` more easily.
448
422
  if (isContributor || isAuthor) {
449
423
  return {
450
424
  excludedAttrs: ['authors'].concat(excludedAttrs)