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
@@ -0,0 +1,247 @@
1
+ const Promise = require('bluebird');
2
+ const tpl = require('@tryghost/tpl');
3
+ const errors = require('@tryghost/errors');
4
+ const models = require('../../models');
5
+ const db = require('../../data/db');
6
+ const ALLOWED_INCLUDES = ['post', 'member', 'likes', 'replies'];
7
+ const UNSAFE_ATTRS = ['status'];
8
+
9
+ const messages = {
10
+ commentNotFound: 'Comment could not be found',
11
+ memberNotFound: 'Unable to find member',
12
+ likeNotFound: 'Unable to find like',
13
+ alreadyLiked: 'This comment was liked already'
14
+ };
15
+
16
+ module.exports = {
17
+ docName: 'comments',
18
+
19
+ browse: {
20
+ options: [
21
+ 'include',
22
+ 'page',
23
+ 'limit',
24
+ 'fields',
25
+ 'filter',
26
+ 'order',
27
+ 'debug'
28
+ ],
29
+ validation: {
30
+ options: {
31
+ include: ALLOWED_INCLUDES
32
+ }
33
+ },
34
+ permissions: true,
35
+ query(frame) {
36
+ return models.Comment.findPage(frame.options);
37
+ }
38
+ },
39
+
40
+ read: {
41
+ options: [
42
+ 'include'
43
+ ],
44
+ data: [
45
+ 'id',
46
+ 'email'
47
+ ],
48
+ validation: {
49
+ options: {
50
+ include: ALLOWED_INCLUDES
51
+ }
52
+ },
53
+ permissions: true,
54
+ query(frame) {
55
+ return models.Comment.findOne(frame.data, frame.options)
56
+ .then((model) => {
57
+ if (!model) {
58
+ return Promise.reject(new errors.NotFoundError({
59
+ message: tpl(messages.commentNotFound)
60
+ }));
61
+ }
62
+
63
+ return model;
64
+ });
65
+ }
66
+ },
67
+
68
+ edit: {
69
+ headers: {},
70
+ options: [
71
+ 'id',
72
+ 'include'
73
+ ],
74
+ validation: {
75
+ options: {
76
+ include: {
77
+ values: ALLOWED_INCLUDES
78
+ },
79
+ id: {
80
+ required: true
81
+ }
82
+ }
83
+ },
84
+ permissions: true,
85
+ query(frame) {
86
+ return models.Comment.edit(frame.data.comments[0], frame.options)
87
+ .then((model) => {
88
+ if (!model) {
89
+ return Promise.reject(new errors.NotFoundError({
90
+ message: tpl(messages.commentNotFound)
91
+ }));
92
+ }
93
+
94
+ return model;
95
+ });
96
+ }
97
+ },
98
+
99
+ add: {
100
+ statusCode: 201,
101
+ options: [
102
+ 'include'
103
+
104
+ ],
105
+ validation: {
106
+ options: {
107
+ include: ALLOWED_INCLUDES
108
+ },
109
+ data: {
110
+ post_id: {
111
+ required: true
112
+ }
113
+ }
114
+ },
115
+ permissions: {
116
+ unsafeAttrs: UNSAFE_ATTRS
117
+ },
118
+ query(frame) {
119
+ // TODO: move to comment service
120
+ const data = frame.data.comments[0];
121
+
122
+ if (frame.options?.context?.member?.id) {
123
+ data.member_id = frame.options.context.member.id;
124
+
125
+ // todo: add validation that the parent comment is on the same post, and not deleted
126
+ return models.Comment.add(data, frame.options);
127
+ } else {
128
+ return Promise.reject(new errors.NotFoundError({
129
+ message: tpl(messages.memberNotFound)
130
+ }));
131
+ }
132
+ }
133
+ },
134
+
135
+ destroy: {
136
+ statusCode: 204,
137
+ options: [
138
+ 'include',
139
+ 'id'
140
+ ],
141
+ validation: {
142
+ options: {
143
+ include: ALLOWED_INCLUDES
144
+ }
145
+ },
146
+ permissions: true,
147
+ query(frame) {
148
+ frame.options.require = true;
149
+
150
+ return models.Comment.destroy(frame.options)
151
+ .then(() => null)
152
+ .catch(models.Comment.NotFoundError, () => {
153
+ return Promise.reject(new errors.NotFoundError({
154
+ message: tpl(messages.commentNotFound)
155
+ }));
156
+ });
157
+ }
158
+ },
159
+
160
+ counts: {
161
+ permissions: false,
162
+ async query(frame) {
163
+ const query = db.knex('comments')
164
+ .select(db.knex.raw(`COUNT(*) AS count, post_id`))
165
+ .groupBy('post_id');
166
+
167
+ if (Array.isArray(frame?.data?.ids)) {
168
+ query.whereIn('post_id', frame.data.ids);
169
+ }
170
+
171
+ const results = await query;
172
+
173
+ const counts = {};
174
+
175
+ for (const row of results) {
176
+ counts[row.post_id] = row.count;
177
+ }
178
+
179
+ return counts;
180
+ }
181
+ },
182
+
183
+ like: {
184
+ statusCode: 204,
185
+ options: [
186
+ 'id'
187
+ ],
188
+ validation: {
189
+ },
190
+ permissions: true,
191
+ async query(frame) {
192
+ // TODO: move to likes service
193
+ if (frame.options?.context?.member?.id) {
194
+ const data = {
195
+ member_id: frame.options.context.member.id,
196
+ comment_id: frame.options.id
197
+ };
198
+
199
+ const existing = await models.CommentLike.findOne(data, frame.options);
200
+
201
+ if (existing) {
202
+ throw new errors.BadRequestError({
203
+ message: tpl(messages.alreadyLiked)
204
+ });
205
+ }
206
+
207
+ return await models.CommentLike.add(data, frame.options);
208
+ } else {
209
+ throw new errors.NotFoundError({
210
+ message: tpl(messages.memberNotFound)
211
+ });
212
+ }
213
+ }
214
+ },
215
+
216
+ unlike: {
217
+ statusCode: 204,
218
+ options: [
219
+ 'id'
220
+ ],
221
+ validation: {},
222
+ permissions: true,
223
+ query(frame) {
224
+ frame.options.require = true;
225
+
226
+ // TODO: move to likes service
227
+ if (frame.options?.context?.member?.id) {
228
+ return models.CommentLike.destroy({
229
+ ...frame.options,
230
+ destroyBy: {
231
+ member_id: frame.options.context.member.id,
232
+ comment_id: frame.options.id
233
+ }
234
+ }).then(() => null)
235
+ .catch(models.CommentLike.NotFoundError, () => {
236
+ return Promise.reject(new errors.NotFoundError({
237
+ message: tpl(messages.likeNotFound)
238
+ }));
239
+ });
240
+ } else {
241
+ return Promise.reject(new errors.NotFoundError({
242
+ message: tpl(messages.memberNotFound)
243
+ }));
244
+ }
245
+ }
246
+ }
247
+ };
@@ -0,0 +1,25 @@
1
+ const models = require('../../models');
2
+
3
+ module.exports = {
4
+ docName: 'comments',
5
+
6
+ edit: {
7
+ options: [
8
+ 'id'
9
+ ],
10
+ validation: {
11
+ options: {
12
+ id: {
13
+ required: true
14
+ }
15
+ }
16
+ },
17
+ permissions: true,
18
+ query(frame) {
19
+ return models.Comment.edit({
20
+ id: frame.data.comments[0].id,
21
+ status: frame.data.comments[0].status
22
+ }, frame.options);
23
+ }
24
+ }
25
+ };
File without changes
File without changes
File without changes
@@ -0,0 +1,12 @@
1
+ const exploreService = require('../../services/explore');
2
+
3
+ module.exports = {
4
+ docName: 'explore',
5
+
6
+ read: {
7
+ permissions: true,
8
+ query() {
9
+ return exploreService.fetchData();
10
+ }
11
+ }
12
+ };
File without changes
File without changes
@@ -137,6 +137,10 @@ module.exports = {
137
137
  return shared.pipeline(require('./config'), localUtils);
138
138
  },
139
139
 
140
+ get explore() {
141
+ return shared.pipeline(require('./explore'), localUtils);
142
+ },
143
+
140
144
  get themes() {
141
145
  return shared.pipeline(require('./themes'), localUtils);
142
146
  },
@@ -177,6 +181,10 @@ module.exports = {
177
181
  return shared.pipeline(require('./newsletters'), localUtils);
178
182
  },
179
183
 
184
+ get comments() {
185
+ return shared.pipeline(require('./comments'), localUtils);
186
+ },
187
+
180
188
  /**
181
189
  * Content API Controllers
182
190
  *
@@ -215,5 +223,13 @@ module.exports = {
215
223
 
216
224
  get offersPublic() {
217
225
  return shared.pipeline(require('./offers-public'), localUtils, 'content');
226
+ },
227
+
228
+ /**
229
+ * Comment API
230
+ */
231
+
232
+ get commentsComments() {
233
+ return shared.pipeline(require('./comments-comments'), localUtils, 'comments');
218
234
  }
219
235
  };
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:permissions');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:permissions');
2
2
  const Promise = require('bluebird');
3
3
  const _ = require('lodash');
4
4
  const permissions = require('../../../services/permissions');
@@ -79,7 +79,7 @@ const nonePublicAuth = (apiConfig, frame) => {
79
79
  // @TODO: https://github.com/TryGhost/Ghost/issues/10735
80
80
  module.exports = {
81
81
  /**
82
- * @description Handle permission stage for canary API.
82
+ * @description Handle permission stage for API.
83
83
  *
84
84
  * @param {Object} apiConfig - Docname & method of target ctrl.
85
85
  * @param {Object} frame
@@ -92,7 +92,7 @@ module.exports = {
92
92
  frame.options.context = permissions.parseContext(frame.options.context);
93
93
 
94
94
  // CASE: Content API access
95
- if (frame.options.context.public) {
95
+ if (frame.options.context.public && frame.apiType !== 'comments') {
96
96
  debug('check content permissions');
97
97
 
98
98
  // @TODO: Remove when we drop v0.1
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:input:authors');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:input:authors');
2
2
  const slugFilterOrder = require('./utils/slug-filter-order');
3
3
  const utils = require('../../index');
4
4
 
@@ -1,5 +1,5 @@
1
1
  const _ = require('lodash');
2
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:input:db');
2
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:input:db');
3
3
  const optionsUtil = require('../../../../shared/utils/options');
4
4
 
5
5
  const INTERNAL_OPTIONS = ['transacting', 'forUpdate'];
@@ -1,5 +1,5 @@
1
1
  const _ = require('lodash');
2
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:input:integrations');
2
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:input:integrations');
3
3
 
4
4
  function setDefaultFilter(frame) {
5
5
  if (frame.options.filter) {
@@ -1,5 +1,5 @@
1
1
  const _ = require('lodash');
2
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:input:members');
2
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:input:members');
3
3
  const mapNQLKeyValues = require('@tryghost/nql').utils.mapKeyValues;
4
4
 
5
5
  function defaultRelations(frame) {
@@ -1,5 +1,5 @@
1
1
  const _ = require('lodash');
2
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:input:pages');
2
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:input:pages');
3
3
  const mobiledoc = require('../../../../../lib/mobiledoc');
4
4
  const url = require('./utils/url');
5
5
  const slugFilterOrder = require('./utils/slug-filter-order');
@@ -1,5 +1,5 @@
1
1
  const _ = require('lodash');
2
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:input:posts');
2
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:input:posts');
3
3
  const url = require('./utils/url');
4
4
  const slugFilterOrder = require('./utils/slug-filter-order');
5
5
  const localUtils = require('../../index');
@@ -55,7 +55,8 @@ const EDITABLE_SETTINGS = [
55
55
  'accent_color',
56
56
  'editor_default_email_recipients',
57
57
  'editor_default_email_recipients_filter',
58
- 'labs'
58
+ 'labs',
59
+ 'comments_enabled'
59
60
  ];
60
61
 
61
62
  module.exports = {
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:input:tags');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:input:tags');
2
2
  const url = require('./utils/url');
3
3
  const slugFilterOrder = require('./utils/slug-filter-order');
4
4
  const utils = require('../../index');
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:input:users');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:input:users');
2
2
  const url = require('./utils/url');
3
3
 
4
4
  module.exports = {
@@ -1,5 +1,5 @@
1
1
  const _ = require('lodash');
2
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:input:webhooks');
2
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:input:webhooks');
3
3
 
4
4
  module.exports = {
5
5
  add(apiConfig, frame) {
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:all');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:all');
2
2
  const _ = require('lodash');
3
3
 
4
4
  const removeXBY = (object) => {
@@ -1,6 +1,6 @@
1
1
  const tpl = require('@tryghost/tpl');
2
2
  const mappers = require('./mappers');
3
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:authentication');
3
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:authentication');
4
4
 
5
5
  const messages = {
6
6
  checkEmailForInstructions: 'Check your email for further instructions.',
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ counts(response, apiConfig, frame) {
3
+ frame.response = response;
4
+ }
5
+ };
@@ -1,5 +1,5 @@
1
1
  const _ = require('lodash');
2
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:config');
2
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:config');
3
3
 
4
4
  module.exports = {
5
5
  all(data, apiConfig, frame) {
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:db');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:db');
2
2
 
3
3
  module.exports = {
4
4
  backupContent(filename, apiConfig, frame) {
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:default');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:default');
2
2
  const mappers = require('./mappers');
3
3
 
4
4
  const mapResponse = (docName, mappable, frame) => {
@@ -0,0 +1,11 @@
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:explore');
2
+
3
+ module.exports = {
4
+ all(data, apiConfig, frame) {
5
+ debug('all');
6
+
7
+ frame.response = {
8
+ explore: data
9
+ };
10
+ }
11
+ };
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:images');
1
+ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:images');
2
2
  const mappers = require('./mappers');
3
3
 
4
4
  module.exports = {