ghost 5.2.2 → 5.3.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 (259) hide show
  1. package/content/themes/casper/assets/built/screen.css +1 -1
  2. package/content/themes/casper/assets/built/screen.css.map +1 -1
  3. package/content/themes/casper/assets/css/screen.css +31 -1
  4. package/content/themes/casper/default.hbs +1 -0
  5. package/content/themes/casper/package.json +1 -1
  6. package/content/themes/casper/partials/icons/search.hbs +1 -0
  7. package/core/boot.js +3 -1
  8. package/core/bridge.js +7 -0
  9. package/core/built/assets/codemirror/{codemirror-d25c379b87ec8b33d54ac7149bc0b6ae.js → codemirror-30201ab2cff61db847193fc9f5ed922d.js} +1 -1
  10. package/core/built/assets/ghost-dark-9e5d1f0dfae41232e5e34e4d0df53ae0.css +1 -0
  11. package/core/built/assets/ghost.min-e7cfbd1800f8e99b9158f74f1e39cd76.css +1 -0
  12. package/core/built/assets/{ghost.min-971a0ff706bbf9e24f0b0a5770c8fc41.js → ghost.min-f4bba3a2a5ef256b82641345505d4f0f.js} +69 -66
  13. package/core/built/assets/icons/activity-placeholder.svg +3 -0
  14. package/core/built/assets/simplemde/{simplemde-3ffc0ec9e9fecf29b9a499db678c9e65.js → simplemde-fb4527da6e489b34dc24b28ea870b286.js} +1 -1
  15. package/core/built/assets/{vendor.min-ea369e6487643585f35409d474b06789.js → vendor.min-4076498ccd6c8412365f43b156084ed8.js} +119 -117
  16. package/core/built/assets/{vendor.min-ba66b98f7c24fa40e061c7ffc94f4e23.css → vendor.min-4a6661c574707ceca220aa2e76558995.css} +2 -1
  17. package/core/frontend/helpers/comment_count.js +25 -0
  18. package/core/frontend/helpers/comments.js +67 -0
  19. package/core/frontend/helpers/date.js +3 -1
  20. package/core/frontend/helpers/ghost_head.js +13 -0
  21. package/core/frontend/services/admin-auth-assets/index.js +4 -0
  22. package/core/frontend/services/admin-auth-assets/service.js +93 -0
  23. package/core/frontend/services/comment-counts-assets/index.js +4 -0
  24. package/core/frontend/services/comment-counts-assets/service.js +59 -0
  25. package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +5 -1
  26. package/core/frontend/src/admin-auth/index.html +5 -0
  27. package/core/frontend/src/admin-auth/message-handler.js +75 -0
  28. package/core/frontend/src/comment-counts/js/comment-counts.js +71 -0
  29. package/core/frontend/web/site.js +3 -0
  30. package/core/server/api/{canary → endpoints}/actions.js +0 -0
  31. package/core/server/api/{canary → endpoints}/authentication.js +0 -0
  32. package/core/server/api/{canary → endpoints}/authors-public.js +0 -0
  33. package/core/server/api/endpoints/comments-comments.js +247 -0
  34. package/core/server/api/endpoints/comments.js +25 -0
  35. package/core/server/api/{canary → endpoints}/config.js +0 -0
  36. package/core/server/api/{canary → endpoints}/custom-theme-settings.js +0 -0
  37. package/core/server/api/{canary → endpoints}/db.js +0 -0
  38. package/core/server/api/{canary → endpoints}/email-post.js +0 -0
  39. package/core/server/api/{canary → endpoints}/email-previews.js +0 -0
  40. package/core/server/api/{canary → endpoints}/emails.js +0 -0
  41. package/core/server/api/endpoints/explore.js +12 -0
  42. package/core/server/api/{canary → endpoints}/files.js +0 -0
  43. package/core/server/api/{canary → endpoints}/identities.js +0 -0
  44. package/core/server/api/{canary → endpoints}/images.js +0 -0
  45. package/core/server/api/{canary → endpoints}/index.js +16 -0
  46. package/core/server/api/{canary → endpoints}/integrations.js +0 -0
  47. package/core/server/api/{canary → endpoints}/invites.js +0 -0
  48. package/core/server/api/{canary → endpoints}/labels.js +0 -0
  49. package/core/server/api/{canary → endpoints}/mail.js +0 -0
  50. package/core/server/api/{canary → endpoints}/media.js +0 -0
  51. package/core/server/api/{canary → endpoints}/member-signin-urls.js +0 -0
  52. package/core/server/api/{canary → endpoints}/members-stripe-connect.js +0 -0
  53. package/core/server/api/{canary → endpoints}/members.js +0 -0
  54. package/core/server/api/{canary → endpoints}/newsletters-public.js +0 -0
  55. package/core/server/api/{canary → endpoints}/newsletters.js +0 -0
  56. package/core/server/api/{canary → endpoints}/notifications.js +0 -0
  57. package/core/server/api/{canary → endpoints}/oembed.js +0 -0
  58. package/core/server/api/{canary → endpoints}/offers-public.js +0 -0
  59. package/core/server/api/{canary → endpoints}/offers.js +0 -0
  60. package/core/server/api/{canary → endpoints}/pages-public.js +0 -0
  61. package/core/server/api/{canary → endpoints}/pages.js +0 -0
  62. package/core/server/api/{canary → endpoints}/posts-public.js +0 -0
  63. package/core/server/api/{canary → endpoints}/posts.js +0 -0
  64. package/core/server/api/{canary → endpoints}/previews.js +0 -0
  65. package/core/server/api/{canary → endpoints}/redirects.js +0 -0
  66. package/core/server/api/{canary → endpoints}/roles.js +0 -0
  67. package/core/server/api/{canary → endpoints}/schedules.js +0 -0
  68. package/core/server/api/{canary → endpoints}/session.js +0 -0
  69. package/core/server/api/{canary → endpoints}/settings-public.js +0 -0
  70. package/core/server/api/{canary → endpoints}/settings.js +0 -0
  71. package/core/server/api/{canary → endpoints}/site.js +0 -0
  72. package/core/server/api/{canary → endpoints}/slack.js +0 -0
  73. package/core/server/api/{canary → endpoints}/slugs.js +0 -0
  74. package/core/server/api/{canary → endpoints}/snippets.js +0 -0
  75. package/core/server/api/{canary → endpoints}/stats.js +0 -0
  76. package/core/server/api/{canary → endpoints}/tags-public.js +0 -0
  77. package/core/server/api/{canary → endpoints}/tags.js +0 -0
  78. package/core/server/api/{canary → endpoints}/themes.js +0 -0
  79. package/core/server/api/{canary → endpoints}/tiers-public.js +0 -0
  80. package/core/server/api/{canary → endpoints}/tiers.js +0 -0
  81. package/core/server/api/{canary → endpoints}/users.js +0 -0
  82. package/core/server/api/{canary → endpoints}/utils/index.js +0 -0
  83. package/core/server/api/{canary → endpoints}/utils/permissions.js +3 -3
  84. package/core/server/api/{canary → endpoints}/utils/serializers/index.js +0 -0
  85. package/core/server/api/{canary → endpoints}/utils/serializers/input/authors.js +1 -1
  86. package/core/server/api/{canary → endpoints}/utils/serializers/input/db.js +1 -1
  87. package/core/server/api/{canary → endpoints}/utils/serializers/input/index.js +0 -0
  88. package/core/server/api/{canary → endpoints}/utils/serializers/input/integrations.js +1 -1
  89. package/core/server/api/{canary → endpoints}/utils/serializers/input/media.js +0 -0
  90. package/core/server/api/{canary → endpoints}/utils/serializers/input/members.js +1 -1
  91. package/core/server/api/{canary → endpoints}/utils/serializers/input/pages.js +1 -1
  92. package/core/server/api/{canary → endpoints}/utils/serializers/input/posts.js +1 -1
  93. package/core/server/api/{canary → endpoints}/utils/serializers/input/settings.js +2 -1
  94. package/core/server/api/{canary → endpoints}/utils/serializers/input/tags.js +1 -1
  95. package/core/server/api/{canary → endpoints}/utils/serializers/input/tiers.js +0 -0
  96. package/core/server/api/{canary → endpoints}/utils/serializers/input/users.js +1 -1
  97. package/core/server/api/{canary → endpoints}/utils/serializers/input/utils/slug-filter-order.js +0 -0
  98. package/core/server/api/{canary → endpoints}/utils/serializers/input/utils/url.js +0 -0
  99. package/core/server/api/{canary → endpoints}/utils/serializers/input/webhooks.js +1 -1
  100. package/core/server/api/{canary → endpoints}/utils/serializers/output/all.js +1 -1
  101. package/core/server/api/{canary → endpoints}/utils/serializers/output/authentication.js +1 -1
  102. package/core/server/api/endpoints/utils/serializers/output/comments.js +5 -0
  103. package/core/server/api/{canary → endpoints}/utils/serializers/output/config.js +1 -1
  104. package/core/server/api/{canary → endpoints}/utils/serializers/output/custom-theme-settings.js +0 -0
  105. package/core/server/api/{canary → endpoints}/utils/serializers/output/db.js +1 -1
  106. package/core/server/api/{canary → endpoints}/utils/serializers/output/default.js +1 -1
  107. package/core/server/api/{canary → endpoints}/utils/serializers/output/email-posts.js +0 -0
  108. package/core/server/api/endpoints/utils/serializers/output/explore.js +11 -0
  109. package/core/server/api/{canary → endpoints}/utils/serializers/output/files.js +0 -0
  110. package/core/server/api/{canary → endpoints}/utils/serializers/output/images.js +1 -1
  111. package/core/server/api/{canary → endpoints}/utils/serializers/output/index.js +8 -0
  112. package/core/server/api/{canary → endpoints}/utils/serializers/output/mail.js +1 -1
  113. package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/actions.js +0 -0
  114. package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/authors.js +0 -0
  115. package/core/server/api/endpoints/utils/serializers/output/mappers/comments.js +50 -0
  116. package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/emails.js +0 -0
  117. package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/images.js +0 -0
  118. package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/index.js +1 -0
  119. package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/integrations.js +0 -0
  120. package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/newsletters.js +0 -0
  121. package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/pages.js +0 -0
  122. package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/posts.js +0 -0
  123. package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/settings.js +0 -0
  124. package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/snippets.js +0 -0
  125. package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/tags.js +0 -0
  126. package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/users.js +0 -0
  127. package/core/server/api/{canary → endpoints}/utils/serializers/output/media.js +0 -0
  128. package/core/server/api/{canary → endpoints}/utils/serializers/output/members-stripe-connect.js +0 -0
  129. package/core/server/api/{canary → endpoints}/utils/serializers/output/members.js +1 -1
  130. package/core/server/api/{canary → endpoints}/utils/serializers/output/notifications.js +1 -1
  131. package/core/server/api/{canary → endpoints}/utils/serializers/output/oembed.js +1 -1
  132. package/core/server/api/{canary → endpoints}/utils/serializers/output/offers.js +1 -1
  133. package/core/server/api/{canary → endpoints}/utils/serializers/output/pages.js +1 -1
  134. package/core/server/api/{canary → endpoints}/utils/serializers/output/posts.js +1 -1
  135. package/core/server/api/{canary → endpoints}/utils/serializers/output/previews.js +0 -0
  136. package/core/server/api/{canary → endpoints}/utils/serializers/output/redirects.js +0 -0
  137. package/core/server/api/{canary → endpoints}/utils/serializers/output/roles.js +1 -1
  138. package/core/server/api/{canary → endpoints}/utils/serializers/output/schedules.js +0 -0
  139. package/core/server/api/{canary → endpoints}/utils/serializers/output/session.js +1 -1
  140. package/core/server/api/{canary → endpoints}/utils/serializers/output/settings.js +0 -0
  141. package/core/server/api/{canary → endpoints}/utils/serializers/output/site.js +1 -1
  142. package/core/server/api/{canary → endpoints}/utils/serializers/output/slack.js +1 -1
  143. package/core/server/api/{canary → endpoints}/utils/serializers/output/slugs.js +1 -1
  144. package/core/server/api/{canary → endpoints}/utils/serializers/output/themes.js +1 -1
  145. package/core/server/api/{canary → endpoints}/utils/serializers/output/tiers.js +1 -1
  146. package/core/server/api/{canary → endpoints}/utils/serializers/output/users.js +1 -1
  147. package/core/server/api/{canary → endpoints}/utils/serializers/output/utils/clean.js +2 -1
  148. package/core/server/api/{canary → endpoints}/utils/serializers/output/utils/date.js +0 -0
  149. package/core/server/api/endpoints/utils/serializers/output/utils/extra-attrs.js +67 -0
  150. package/core/server/api/{canary → endpoints}/utils/serializers/output/utils/post-gating.js +0 -0
  151. package/core/server/api/{canary → endpoints}/utils/serializers/output/utils/url.js +1 -1
  152. package/core/server/api/{canary → endpoints}/utils/validators/index.js +0 -0
  153. package/core/server/api/{canary → endpoints}/utils/validators/input/files.js +0 -0
  154. package/core/server/api/{canary → endpoints}/utils/validators/input/images.js +0 -0
  155. package/core/server/api/{canary → endpoints}/utils/validators/input/index.js +0 -0
  156. package/core/server/api/{canary → endpoints}/utils/validators/input/invitations.js +1 -1
  157. package/core/server/api/{canary → endpoints}/utils/validators/input/invites.js +0 -0
  158. package/core/server/api/{canary → endpoints}/utils/validators/input/labels.js +0 -0
  159. package/core/server/api/{canary → endpoints}/utils/validators/input/media.js +0 -0
  160. package/core/server/api/{canary → endpoints}/utils/validators/input/members.js +0 -0
  161. package/core/server/api/{canary → endpoints}/utils/validators/input/oembed.js +0 -0
  162. package/core/server/api/{canary → endpoints}/utils/validators/input/pages.js +0 -0
  163. package/core/server/api/{canary → endpoints}/utils/validators/input/password_reset.js +1 -1
  164. package/core/server/api/{canary → endpoints}/utils/validators/input/posts.js +0 -0
  165. package/core/server/api/{canary → endpoints}/utils/validators/input/settings.js +0 -0
  166. package/core/server/api/{canary → endpoints}/utils/validators/input/setup.js +1 -1
  167. package/core/server/api/{canary → endpoints}/utils/validators/input/snippets.js +0 -0
  168. package/core/server/api/{canary → endpoints}/utils/validators/input/tags.js +0 -0
  169. package/core/server/api/{canary → endpoints}/utils/validators/input/tiers.js +0 -0
  170. package/core/server/api/{canary → endpoints}/utils/validators/input/users.js +1 -1
  171. package/core/server/api/{canary → endpoints}/utils/validators/input/webhooks.js +0 -0
  172. package/core/server/api/{canary → endpoints}/utils/validators/output/index.js +0 -0
  173. package/core/server/api/{canary → endpoints}/utils/validators/utils/json-schema.js +0 -0
  174. package/core/server/api/{canary → endpoints}/webhooks.js +0 -0
  175. package/core/server/api/index.js +1 -1
  176. package/core/server/data/exporter/table-lists.js +4 -2
  177. package/core/server/data/migrations/versions/5.3/2022-07-04-13-49-add-comments-table.js +13 -0
  178. package/core/server/data/migrations/versions/5.3/2022-07-05-09-36-add-comments-likes-table.js +9 -0
  179. package/core/server/data/migrations/versions/5.3/2022-07-05-09-47-add-comments-reports-table.js +10 -0
  180. package/core/server/data/migrations/versions/5.3/2022-07-05-10-00-add-comment-related-fields-to-members.js +21 -0
  181. package/core/server/data/migrations/versions/5.3/2022-07-05-12-55-add-comments-crud-permissions.js +68 -0
  182. package/core/server/data/migrations/versions/5.3/2022-07-05-15-35-add-comment-notifications-field-to-users-table.js +7 -0
  183. package/core/server/data/migrations/versions/5.3/2022-07-06-07-26-add-comments-enabled-setting.js +8 -0
  184. package/core/server/data/migrations/versions/5.3/2022-07-06-07-58-add-ghost-explore-integration-role.js +31 -0
  185. package/core/server/data/migrations/versions/5.3/2022-07-06-09-13-add-ghost-explore-integration-role-permissions.js +11 -0
  186. package/core/server/data/migrations/versions/5.3/2022-07-06-09-17-add-ghost-explore-integration.js +38 -0
  187. package/core/server/data/migrations/versions/5.3/2022-07-06-09-26-add-ghost-explore-integration-api-key.js +73 -0
  188. package/core/server/data/schema/default-settings/default-settings.json +14 -0
  189. package/core/server/data/schema/fixtures/fixtures.json +65 -2
  190. package/core/server/data/schema/schema.js +31 -1
  191. package/core/server/models/base/plugins/crud.js +15 -0
  192. package/core/server/models/comment-like.js +34 -0
  193. package/core/server/models/comment.js +163 -0
  194. package/core/server/models/member.js +2 -1
  195. package/core/server/models/user.js +2 -1
  196. package/core/server/services/auth/session/express-session.js +1 -1
  197. package/core/server/services/comments/email-templates/new-comment-reply.hbs +199 -0
  198. package/core/server/services/comments/email-templates/new-comment-reply.txt.js +14 -0
  199. package/core/server/services/comments/email-templates/new-comment.hbs +199 -0
  200. package/core/server/services/comments/email-templates/new-comment.txt.js +14 -0
  201. package/core/server/services/comments/emails.js +164 -0
  202. package/core/server/services/comments/index.js +26 -0
  203. package/core/server/services/comments/service.js +24 -0
  204. package/core/server/services/explore/index.js +18 -0
  205. package/core/server/services/explore/service.js +55 -0
  206. package/core/server/services/members/middleware.js +4 -4
  207. package/core/server/services/members/utils.js +2 -1
  208. package/core/server/services/permissions/can-this.js +18 -5
  209. package/core/server/services/permissions/parse-context.js +5 -0
  210. package/core/server/services/permissions/providers.js +17 -1
  211. package/core/server/services/posts/posts-service.js +14 -0
  212. package/core/server/services/users.js +84 -1
  213. package/core/server/web/admin/app.js +4 -0
  214. package/core/server/web/admin/views/default-prod.html +5 -5
  215. package/core/server/web/admin/views/default.html +5 -5
  216. package/core/server/web/api/app.js +2 -2
  217. package/core/server/web/api/{canary → endpoints}/admin/app.js +4 -4
  218. package/core/server/web/api/{canary → endpoints}/admin/middleware.js +1 -0
  219. package/core/server/web/api/{canary → endpoints}/admin/routes.js +6 -1
  220. package/core/server/web/api/{canary → endpoints}/content/app.js +4 -4
  221. package/core/server/web/api/{canary → endpoints}/content/middleware.js +0 -0
  222. package/core/server/web/api/{canary → endpoints}/content/routes.js +1 -1
  223. package/core/server/web/api/testmode/routes.js +1 -1
  224. package/core/server/web/comments/index.js +1 -0
  225. package/core/server/web/comments/routes.js +28 -0
  226. package/core/server/web/members/app.js +5 -0
  227. package/core/server/web/parent/frontend.js +1 -0
  228. package/core/shared/config/defaults.json +16 -6
  229. package/core/shared/config/env/config.testing.json +4 -0
  230. package/core/shared/config/overrides.json +1 -0
  231. package/core/shared/labs.js +2 -1
  232. package/core/shared/settings-cache/public.js +2 -1
  233. package/package.json +20 -20
  234. package/yarn.lock +425 -275
  235. package/Gruntfile.js +0 -384
  236. package/core/built/assets/ghost-dark-923c90399aa560625a983a6ae9abb38c.css +0 -1
  237. package/core/built/assets/ghost.min-c74f50609022cebf13ad28810def68b6.css +0 -1
  238. package/core/built/assets/img/contributors/AileenCGN-bf8b9ffbb34c0fd93beb8136af07771b.jpeg +0 -0
  239. package/core/built/assets/img/contributors/ErisDS-c958ccb9e3597320dee745a42f478569.jpeg +0 -0
  240. package/core/built/assets/img/contributors/GeorginaLusby-6cea5defddee3c4ea7320e580521e832.jpeg +0 -0
  241. package/core/built/assets/img/contributors/JohnONolan-47041b80c35c6341b9b929b03139aecc.jpeg +0 -0
  242. package/core/built/assets/img/contributors/acburdine-d9777fe2601dc215afb6723315829c89.jpeg +0 -0
  243. package/core/built/assets/img/contributors/bnookala-5896fcdd2f477495323e420efe890657.jpeg +0 -0
  244. package/core/built/assets/img/contributors/cobbspur-07ded67009757d12517621fc856eba62.jpeg +0 -0
  245. package/core/built/assets/img/contributors/dbalders-452347a406c2ca23657daea9100878f3.jpeg +0 -0
  246. package/core/built/assets/img/contributors/disordinary-b9997e5debb59b7aadc79ba90955b662.jpeg +0 -0
  247. package/core/built/assets/img/contributors/felixrieseberg-ecf29e8eadc58fab999c507049f898cf.jpeg +0 -0
  248. package/core/built/assets/img/contributors/frantzypants-637b03f85dff89700a661fde79daea5c.jpeg +0 -0
  249. package/core/built/assets/img/contributors/halfdan-00d6783e5fba2900ee1380939297d8ee.jpeg +0 -0
  250. package/core/built/assets/img/contributors/jaswilli-8cc9a8d2539ca03239d113dfb25ff5c2.jpeg +0 -0
  251. package/core/built/assets/img/contributors/kevinansfield-925606c55bc2f3f2f05c0fa58b953ad1.jpeg +0 -0
  252. package/core/built/assets/img/contributors/kevinkucharczyk-3c7dfe2a103a83737b9d5ee8e19d67f8.jpeg +0 -0
  253. package/core/built/assets/img/contributors/kirrg001-79823418f2ca21e81719653f0286f95b.jpeg +0 -0
  254. package/core/built/assets/img/contributors/mixonic-1ff87736dd02cfa080ae109b45131aa6.png +0 -0
  255. package/core/built/assets/img/contributors/rwjblue-5c7cc009cda45baca2d45f0d1ed19e48.jpeg +0 -0
  256. package/core/built/assets/img/contributors/sebgie-0fb02df00ee7834dbcc8beba84aec81e.png +0 -0
  257. package/core/built/assets/img/contributors/tgriesser-d871cbf74a871c0fb6d855e76a893f7e.png +0 -0
  258. package/core/server/api/canary/utils/serializers/output/utils/extra-attrs.js +0 -33
  259. package/urls.json +0 -597
@@ -13,6 +13,10 @@ module.exports = {
13
13
  return require('./default');
14
14
  },
15
15
 
16
+ get comments() {
17
+ return require('./comments');
18
+ },
19
+
16
20
  get authentication() {
17
21
  return require('./authentication');
18
22
  },
@@ -21,6 +25,10 @@ module.exports = {
21
25
  return require('./db');
22
26
  },
23
27
 
28
+ get explore() {
29
+ return require('./explore');
30
+ },
31
+
24
32
  get pages() {
25
33
  return require('./pages');
26
34
  },
@@ -1,5 +1,5 @@
1
1
  const _ = require('lodash');
2
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:mail');
2
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:mail');
3
3
 
4
4
  module.exports = {
5
5
  all(response, apiConfig, frame) {
@@ -0,0 +1,50 @@
1
+ const _ = require('lodash');
2
+
3
+ const commentFields = [
4
+ 'id',
5
+ 'status',
6
+ 'html',
7
+ 'created_at',
8
+ 'edited_at'
9
+ ];
10
+
11
+ const memberFields = [
12
+ 'id',
13
+ 'uuid',
14
+ 'name',
15
+ 'bio',
16
+ 'avatar_image'
17
+ ];
18
+
19
+ const commentMapper = (model, frame) => {
20
+ const jsonModel = model.toJSON ? model.toJSON(frame.options) : model;
21
+
22
+ const response = _.pick(jsonModel, commentFields);
23
+
24
+ if (jsonModel.member) {
25
+ response.member = _.pick(jsonModel.member, memberFields);
26
+ } else {
27
+ response.member = null;
28
+ }
29
+
30
+ if (jsonModel.likes) {
31
+ response.likes_count = jsonModel.likes.length;
32
+ } else {
33
+ response.likes_count = 0;
34
+ }
35
+
36
+ if (jsonModel.replies) {
37
+ response.replies = jsonModel.replies.map(reply => commentMapper(reply, frame));
38
+ }
39
+
40
+ // todo
41
+ response.liked = false;
42
+ if (jsonModel.likes && frame.original.context.member && frame.original.context.member.id) {
43
+ const id = frame.original.context.member.id;
44
+ response.liked = !!jsonModel.likes.find(l => l.member_id === id);
45
+ }
46
+
47
+ return response;
48
+ };
49
+
50
+ module.exports = commentMapper;
@@ -1,6 +1,7 @@
1
1
  module.exports = {
2
2
  actions: require('./actions'),
3
3
  authors: require('./authors'),
4
+ comments: require('./comments'),
4
5
  emails: require('./emails'),
5
6
  images: require('./images'),
6
7
  integrations: require('./integrations'),
@@ -1,5 +1,5 @@
1
1
  //@ts-check
2
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:members');
2
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:members');
3
3
  const {unparse} = require('@tryghost/members-csv');
4
4
 
5
5
  module.exports = {
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:notifications');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:notifications');
2
2
 
3
3
  module.exports = {
4
4
  all(response, apiConfig, frame) {
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:oembed');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:oembed');
2
2
 
3
3
  module.exports = {
4
4
  all(data, apiConfig, frame) {
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:offers');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:offers');
2
2
  const utils = require('../../index');
3
3
 
4
4
  module.exports = {
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:pages');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:pages');
2
2
  const mappers = require('./mappers');
3
3
  const membersService = require('../../../../../services/members');
4
4
 
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:posts');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:posts');
2
2
  const mappers = require('./mappers');
3
3
  const membersService = require('../../../../../services/members');
4
4
 
@@ -1,5 +1,5 @@
1
1
  const Promise = require('bluebird');
2
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:roles');
2
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:roles');
3
3
  const canThis = require('../../../../../services/permissions').canThis;
4
4
 
5
5
  module.exports = {
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:session');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:session');
2
2
 
3
3
  module.exports = {
4
4
  all(data, apiConfig, frame) {
@@ -1,5 +1,5 @@
1
1
  const _ = require('lodash');
2
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:site');
2
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:site');
3
3
 
4
4
  module.exports = {
5
5
  read(data, apiConfig, frame) {
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:slack');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:slack');
2
2
 
3
3
  module.exports = {
4
4
  all(data, apiConfig, frame) {
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:slugs');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:slugs');
2
2
 
3
3
  module.exports = {
4
4
  all(slug, apiConfig, frame) {
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:themes');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:themes');
2
2
 
3
3
  module.exports = {
4
4
  all(data, apiConfig, frame) {
@@ -1,5 +1,5 @@
1
1
  //@ts-check
2
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:tiers');
2
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:tiers');
3
3
 
4
4
  const allowedIncludes = ['monthly_price', 'yearly_price'];
5
5
  const localUtils = require('../../index');
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:users');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:users');
2
2
  const tpl = require('@tryghost/tpl');
3
3
 
4
4
  const messages = {
@@ -31,11 +31,12 @@ const author = (attrs, frame) => {
31
31
  delete attrs.last_seen;
32
32
  delete attrs.status;
33
33
  delete attrs.email;
34
+ delete attrs.comment_notifications;
34
35
 
35
36
  // @NOTE: used for night shift
36
37
  delete attrs.accessibility;
37
38
 
38
- // Extra properties removed from canary
39
+ // Extra properties removed from current API
39
40
  delete attrs.tour;
40
41
 
41
42
  // We are standardising on returning null from the Content API for any empty values
@@ -0,0 +1,67 @@
1
+ const readingMinutes = require('@tryghost/helpers').utils.readingMinutes;
2
+
3
+ module.exports.forPost = (frame, model, attrs) => {
4
+ const _ = require('lodash');
5
+ // This function is split up in 3 conditions for 3 different purposes:
6
+ // 1. Gets excerpt from post's plaintext. If custom_excerpt exists, it overrides the excerpt but the key remains excerpt.
7
+ if (Object.prototype.hasOwnProperty.call(frame.options, 'columns') || _.includes(frame.options.columns, 'excerpt') || _.includes(frame.options.columns, 'excerpt') && frame.options.formats && frame.options.formats.includes('plaintext')) {
8
+ if (_.includes(frame.options.columns, 'excerpt')) {
9
+ if (!attrs.custom_excerpt || attrs.custom_excerpt === null) {
10
+ let plaintext = model.get('plaintext');
11
+ if (plaintext) {
12
+ attrs.excerpt = plaintext.substring(0, 500);
13
+ } else {
14
+ attrs.excerpt = null;
15
+ }
16
+ if (!frame.options.columns.includes('custom_excerpt')) {
17
+ delete attrs.custom_excerpt;
18
+ }
19
+ } else {
20
+ attrs.excerpt = attrs.custom_excerpt;
21
+ if (!_.includes(frame.options.columns, 'custom_excerpt')) {
22
+ delete attrs.custom_excerpt;
23
+ }
24
+ }
25
+ }
26
+ }
27
+ // 2. Displays plaintext if requested by user as a field. Also works if used as format.
28
+ if (_.includes(frame.options.columns, 'plaintext') || frame.options.formats && frame.options.formats.includes('plaintext')) {
29
+ let plaintext = model.get('plaintext');
30
+ if (plaintext){
31
+ attrs.plaintext = plaintext;
32
+ } else {
33
+ delete attrs.plaintext;
34
+ }
35
+ }
36
+
37
+ // 3. Displays excerpt if no columns was requested - specifically needed for the Admin Posts API.
38
+
39
+ if (!Object.prototype.hasOwnProperty.call(frame.options, 'columns')) {
40
+ let plaintext = model.get('plaintext');
41
+ let customExcerpt = model.get('custom_excerpt');
42
+
43
+ if (customExcerpt !== null){
44
+ attrs.excerpt = customExcerpt;
45
+ } else {
46
+ if (plaintext) {
47
+ attrs.excerpt = plaintext.substring(0, 500);
48
+ } else {
49
+ attrs.excerpt = null;
50
+ }
51
+ }
52
+ }
53
+
54
+ // reading_time still only works when used along with formats=html.
55
+
56
+ if (!Object.prototype.hasOwnProperty.call(frame.options, 'columns') ||
57
+ (frame.options.columns.includes('reading_time'))) {
58
+ if (attrs.html) {
59
+ let additionalImages = 0;
60
+
61
+ if (attrs.feature_image) {
62
+ additionalImages += 1;
63
+ }
64
+ attrs.reading_time = readingMinutes(attrs.html, additionalImages);
65
+ }
66
+ }
67
+ };
@@ -14,7 +14,7 @@ const forPost = (id, attrs, frame) => {
14
14
  *
15
15
  * Imagine the site won't be part of core and core does not serve urls anymore.
16
16
  * Core needs to offer a preview API, which returns draft posts.
17
- * That means the url is no longer /p/:uuid, it's e.g. GET /api/canary/content/preview/:uuid/.
17
+ * That means the url is no longer /p/:uuid, it's e.g. GET /api/content/preview/:uuid/.
18
18
  * /p/ is a concept of the site, not of core.
19
19
  *
20
20
  * The site is not aware of existing drafts. It won't be able to get the uuid.
@@ -1,6 +1,6 @@
1
1
  const Promise = require('bluebird');
2
2
  const validator = require('@tryghost/validator');
3
- const debug = require('@tryghost/debug')('api:canary:utils:validators:input:invitation');
3
+ const debug = require('@tryghost/debug')('api:endpoints:utils:validators:input:invitation');
4
4
  const tpl = require('@tryghost/tpl');
5
5
  const errors = require('@tryghost/errors');
6
6
 
@@ -1,6 +1,6 @@
1
1
  const Promise = require('bluebird');
2
2
  const validator = require('@tryghost/validator');
3
- const debug = require('@tryghost/debug')('api:canary:utils:validators:input:passwordreset');
3
+ const debug = require('@tryghost/debug')('api:endpoints:utils:validators:input:passwordreset');
4
4
  const tpl = require('@tryghost/tpl');
5
5
  const errors = require('@tryghost/errors');
6
6
 
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:validators:input:updateSetup');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:validators:input:updateSetup');
2
2
  const tpl = require('@tryghost/tpl');
3
3
  const errors = require('@tryghost/errors');
4
4
 
@@ -1,5 +1,5 @@
1
1
  const Promise = require('bluebird');
2
- const debug = require('@tryghost/debug')('api:canary:utils:validators:input:users');
2
+ const debug = require('@tryghost/debug')('api:endpoints:utils:validators:input:users');
3
3
  const tpl = require('@tryghost/tpl');
4
4
  const errors = require('@tryghost/errors');
5
5
 
@@ -1,3 +1,3 @@
1
- module.exports.endpoints = require('./canary');
1
+ module.exports.endpoints = require('./endpoints');
2
2
 
3
3
  module.exports.shared = require('./shared');
@@ -31,8 +31,10 @@ const BACKUP_TABLES = [
31
31
  'members_paid_subscription_events',
32
32
  'members_subscribe_events',
33
33
  'members_product_events',
34
- 'members_newsletters'
35
-
34
+ 'members_newsletters',
35
+ 'comments',
36
+ 'comment_likes',
37
+ 'comment_reports'
36
38
  ];
37
39
 
38
40
  // NOTE: exposing only tables which are going to be included in a "default" export file
@@ -0,0 +1,13 @@
1
+ const {addTable} = require('../../utils');
2
+
3
+ module.exports = addTable('comments', {
4
+ id: {type: 'string', maxlength: 24, nullable: false, primary: true},
5
+ post_id: {type: 'string', maxlength: 24, nullable: false, unique: false, references: 'posts.id', cascadeDelete: true},
6
+ member_id: {type: 'string', maxlength: 24, nullable: true, unique: false, references: 'members.id'},
7
+ parent_id: {type: 'string', maxlength: 24, nullable: true, unique: false, references: 'comments.id'},
8
+ status: {type: 'string', maxlength: 50, nullable: false, defaultTo: 'published', validations: {isIn: [['published', 'hidden', 'deleted']]}},
9
+ html: {type: 'text', maxlength: 1000000000, fieldtype: 'long', nullable: true},
10
+ edited_at: {type: 'dateTime', nullable: true},
11
+ created_at: {type: 'dateTime', nullable: false},
12
+ updated_at: {type: 'dateTime', nullable: false}
13
+ });
@@ -0,0 +1,9 @@
1
+ const {addTable} = require('../../utils');
2
+
3
+ module.exports = addTable('comment_likes', {
4
+ id: {type: 'string', maxlength: 24, nullable: false, primary: true},
5
+ comment_id: {type: 'string', maxlength: 24, nullable: false, unique: false, references: 'comments.id', cascadeDelete: true},
6
+ member_id: {type: 'string', maxlength: 24, nullable: true, unique: false, references: 'members.id'},
7
+ created_at: {type: 'dateTime', nullable: false},
8
+ updated_at: {type: 'dateTime', nullable: false}
9
+ });
@@ -0,0 +1,10 @@
1
+ const {addTable} = require('../../utils');
2
+
3
+ module.exports = addTable('comment_reports', {
4
+ id: {type: 'string', maxlength: 24, nullable: false, primary: true},
5
+ comment_id: {type: 'string', maxlength: 24, nullable: false, unique: false, references: 'comments.id', cascadeDelete: true},
6
+ member_id: {type: 'string', maxlength: 24, nullable: true, unique: false, references: 'members.id'},
7
+ reason: {type: 'text', maxlength: 65535, nullable: false},
8
+ created_at: {type: 'dateTime', nullable: false},
9
+ updated_at: {type: 'dateTime', nullable: false}
10
+ });
@@ -0,0 +1,21 @@
1
+ const {createAddColumnMigration, combineNonTransactionalMigrations} = require('../../utils');
2
+
3
+ module.exports = combineNonTransactionalMigrations(
4
+ createAddColumnMigration('members', 'last_commented_at', {
5
+ type: 'dateTime',
6
+ nullable: true
7
+ }),
8
+
9
+ createAddColumnMigration('members', 'bio', {
10
+ type: 'string',
11
+ nullable: true,
12
+ maxlength: 191,
13
+ validations: {isLength: {max: 50}}
14
+ }),
15
+
16
+ createAddColumnMigration('members', 'enable_comment_notifications', {
17
+ type: 'boolean',
18
+ nullable: false,
19
+ defaultTo: true
20
+ })
21
+ );
@@ -0,0 +1,68 @@
1
+ const {combineTransactionalMigrations, addPermissionWithRoles} = require('../../utils');
2
+
3
+ module.exports = combineTransactionalMigrations(
4
+ addPermissionWithRoles({
5
+ name: 'Browse comments',
6
+ action: 'browse',
7
+ object: 'comment'
8
+ }, [
9
+ 'Administrator',
10
+ 'Admin Integration'
11
+ ]),
12
+ addPermissionWithRoles({
13
+ name: 'Read comments',
14
+ action: 'read',
15
+ object: 'comment'
16
+ }, [
17
+ 'Administrator',
18
+ 'Admin Integration'
19
+ ]),
20
+ addPermissionWithRoles({
21
+ name: 'Edit comments',
22
+ action: 'edit',
23
+ object: 'comment'
24
+ }, [
25
+ 'Administrator',
26
+ 'Admin Integration'
27
+ ]),
28
+ addPermissionWithRoles({
29
+ name: 'Add comments',
30
+ action: 'add',
31
+ object: 'comment'
32
+ }, [
33
+ 'Administrator',
34
+ 'Admin Integration'
35
+ ]),
36
+ addPermissionWithRoles({
37
+ name: 'Delete comments',
38
+ action: 'destroy',
39
+ object: 'comment'
40
+ }, [
41
+ 'Administrator',
42
+ 'Admin Integration'
43
+ ]),
44
+ addPermissionWithRoles({
45
+ name: 'Moderate comments',
46
+ action: 'moderate',
47
+ object: 'comment'
48
+ }, [
49
+ 'Administrator',
50
+ 'Admin Integration'
51
+ ]),
52
+ addPermissionWithRoles({
53
+ name: 'Like comments',
54
+ action: 'like',
55
+ object: 'comment'
56
+ }, [
57
+ 'Administrator',
58
+ 'Admin Integration'
59
+ ]),
60
+ addPermissionWithRoles({
61
+ name: 'Unlike comments',
62
+ action: 'unlike',
63
+ object: 'comment'
64
+ }, [
65
+ 'Administrator',
66
+ 'Admin Integration'
67
+ ])
68
+ );
@@ -0,0 +1,7 @@
1
+ const {createAddColumnMigration} = require('../../utils');
2
+
3
+ module.exports = createAddColumnMigration('users', 'comment_notifications', {
4
+ type: 'boolean',
5
+ nullable: false,
6
+ defaultTo: true
7
+ });
@@ -0,0 +1,8 @@
1
+ const {addSetting} = require('../../utils');
2
+
3
+ module.exports = addSetting({
4
+ key: 'comments_enabled',
5
+ value: 'off',
6
+ type: 'string',
7
+ group: 'comments'
8
+ });
@@ -0,0 +1,31 @@
1
+ const logging = require('@tryghost/logging');
2
+ const {default: ObjectID} = require('bson-objectid');
3
+ const {createTransactionalMigration, meta} = require('../../utils');
4
+
5
+ module.exports = createTransactionalMigration(
6
+ async function up(knex) {
7
+ logging.info('Creating "Ghost Explore Integration" role');
8
+ const existingRole = await knex('roles').where({
9
+ name: 'Ghost Explore Integration'
10
+ }).first();
11
+
12
+ if (existingRole) {
13
+ logging.warn('"Ghost Explore Integration" role already exists, skipping');
14
+ return;
15
+ }
16
+
17
+ await knex('roles').insert({
18
+ id: (new ObjectID()).toHexString(),
19
+ name: 'Ghost Explore Integration',
20
+ description: 'Internal Integration for the Ghost Explore directory',
21
+ created_by: meta.MIGRATION_USER,
22
+ created_at: knex.raw('current_timestamp')
23
+ });
24
+ },
25
+ async function down(knex) {
26
+ logging.info('Deleting role "Ghost Explore Integration"');
27
+ await knex('roles').where({
28
+ name: 'Ghost Explore Integration'
29
+ }).del();
30
+ }
31
+ );