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.
- package/content/themes/casper/assets/built/screen.css +1 -1
- package/content/themes/casper/assets/built/screen.css.map +1 -1
- package/content/themes/casper/assets/css/screen.css +31 -1
- package/content/themes/casper/default.hbs +1 -0
- package/content/themes/casper/package.json +1 -1
- package/content/themes/casper/partials/icons/search.hbs +1 -0
- package/core/boot.js +3 -1
- package/core/bridge.js +7 -0
- package/core/built/assets/codemirror/{codemirror-d25c379b87ec8b33d54ac7149bc0b6ae.js → codemirror-30201ab2cff61db847193fc9f5ed922d.js} +1 -1
- package/core/built/assets/ghost-dark-9e5d1f0dfae41232e5e34e4d0df53ae0.css +1 -0
- package/core/built/assets/ghost.min-e7cfbd1800f8e99b9158f74f1e39cd76.css +1 -0
- package/core/built/assets/{ghost.min-971a0ff706bbf9e24f0b0a5770c8fc41.js → ghost.min-f4bba3a2a5ef256b82641345505d4f0f.js} +69 -66
- package/core/built/assets/icons/activity-placeholder.svg +3 -0
- package/core/built/assets/simplemde/{simplemde-3ffc0ec9e9fecf29b9a499db678c9e65.js → simplemde-fb4527da6e489b34dc24b28ea870b286.js} +1 -1
- package/core/built/assets/{vendor.min-ea369e6487643585f35409d474b06789.js → vendor.min-4076498ccd6c8412365f43b156084ed8.js} +119 -117
- package/core/built/assets/{vendor.min-ba66b98f7c24fa40e061c7ffc94f4e23.css → vendor.min-4a6661c574707ceca220aa2e76558995.css} +2 -1
- package/core/frontend/helpers/comment_count.js +25 -0
- package/core/frontend/helpers/comments.js +67 -0
- package/core/frontend/helpers/date.js +3 -1
- package/core/frontend/helpers/ghost_head.js +13 -0
- package/core/frontend/services/admin-auth-assets/index.js +4 -0
- package/core/frontend/services/admin-auth-assets/service.js +93 -0
- package/core/frontend/services/comment-counts-assets/index.js +4 -0
- package/core/frontend/services/comment-counts-assets/service.js +59 -0
- package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +5 -1
- package/core/frontend/src/admin-auth/index.html +5 -0
- package/core/frontend/src/admin-auth/message-handler.js +75 -0
- package/core/frontend/src/comment-counts/js/comment-counts.js +71 -0
- package/core/frontend/web/site.js +3 -0
- package/core/server/api/{canary → endpoints}/actions.js +0 -0
- package/core/server/api/{canary → endpoints}/authentication.js +0 -0
- package/core/server/api/{canary → endpoints}/authors-public.js +0 -0
- package/core/server/api/endpoints/comments-comments.js +247 -0
- package/core/server/api/endpoints/comments.js +25 -0
- package/core/server/api/{canary → endpoints}/config.js +0 -0
- package/core/server/api/{canary → endpoints}/custom-theme-settings.js +0 -0
- package/core/server/api/{canary → endpoints}/db.js +0 -0
- package/core/server/api/{canary → endpoints}/email-post.js +0 -0
- package/core/server/api/{canary → endpoints}/email-previews.js +0 -0
- package/core/server/api/{canary → endpoints}/emails.js +0 -0
- package/core/server/api/endpoints/explore.js +12 -0
- package/core/server/api/{canary → endpoints}/files.js +0 -0
- package/core/server/api/{canary → endpoints}/identities.js +0 -0
- package/core/server/api/{canary → endpoints}/images.js +0 -0
- package/core/server/api/{canary → endpoints}/index.js +16 -0
- package/core/server/api/{canary → endpoints}/integrations.js +0 -0
- package/core/server/api/{canary → endpoints}/invites.js +0 -0
- package/core/server/api/{canary → endpoints}/labels.js +0 -0
- package/core/server/api/{canary → endpoints}/mail.js +0 -0
- package/core/server/api/{canary → endpoints}/media.js +0 -0
- package/core/server/api/{canary → endpoints}/member-signin-urls.js +0 -0
- package/core/server/api/{canary → endpoints}/members-stripe-connect.js +0 -0
- package/core/server/api/{canary → endpoints}/members.js +0 -0
- package/core/server/api/{canary → endpoints}/newsletters-public.js +0 -0
- package/core/server/api/{canary → endpoints}/newsletters.js +0 -0
- package/core/server/api/{canary → endpoints}/notifications.js +0 -0
- package/core/server/api/{canary → endpoints}/oembed.js +0 -0
- package/core/server/api/{canary → endpoints}/offers-public.js +0 -0
- package/core/server/api/{canary → endpoints}/offers.js +0 -0
- package/core/server/api/{canary → endpoints}/pages-public.js +0 -0
- package/core/server/api/{canary → endpoints}/pages.js +0 -0
- package/core/server/api/{canary → endpoints}/posts-public.js +0 -0
- package/core/server/api/{canary → endpoints}/posts.js +0 -0
- package/core/server/api/{canary → endpoints}/previews.js +0 -0
- package/core/server/api/{canary → endpoints}/redirects.js +0 -0
- package/core/server/api/{canary → endpoints}/roles.js +0 -0
- package/core/server/api/{canary → endpoints}/schedules.js +0 -0
- package/core/server/api/{canary → endpoints}/session.js +0 -0
- package/core/server/api/{canary → endpoints}/settings-public.js +0 -0
- package/core/server/api/{canary → endpoints}/settings.js +0 -0
- package/core/server/api/{canary → endpoints}/site.js +0 -0
- package/core/server/api/{canary → endpoints}/slack.js +0 -0
- package/core/server/api/{canary → endpoints}/slugs.js +0 -0
- package/core/server/api/{canary → endpoints}/snippets.js +0 -0
- package/core/server/api/{canary → endpoints}/stats.js +0 -0
- package/core/server/api/{canary → endpoints}/tags-public.js +0 -0
- package/core/server/api/{canary → endpoints}/tags.js +0 -0
- package/core/server/api/{canary → endpoints}/themes.js +0 -0
- package/core/server/api/{canary → endpoints}/tiers-public.js +0 -0
- package/core/server/api/{canary → endpoints}/tiers.js +0 -0
- package/core/server/api/{canary → endpoints}/users.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/index.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/permissions.js +3 -3
- package/core/server/api/{canary → endpoints}/utils/serializers/index.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/input/authors.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/db.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/index.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/input/integrations.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/media.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/input/members.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/pages.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/posts.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/settings.js +2 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/tags.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/tiers.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/input/users.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/utils/slug-filter-order.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/input/utils/url.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/input/webhooks.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/all.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/authentication.js +1 -1
- package/core/server/api/endpoints/utils/serializers/output/comments.js +5 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/config.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/custom-theme-settings.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/db.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/default.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/email-posts.js +0 -0
- package/core/server/api/endpoints/utils/serializers/output/explore.js +11 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/files.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/images.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/index.js +8 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mail.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/actions.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/authors.js +0 -0
- package/core/server/api/endpoints/utils/serializers/output/mappers/comments.js +50 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/emails.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/images.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/index.js +1 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/integrations.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/newsletters.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/pages.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/posts.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/settings.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/snippets.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/tags.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/users.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/media.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/members-stripe-connect.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/members.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/notifications.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/oembed.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/offers.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/pages.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/posts.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/previews.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/redirects.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/roles.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/schedules.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/session.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/settings.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/site.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/slack.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/slugs.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/themes.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/tiers.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/users.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/utils/clean.js +2 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/utils/date.js +0 -0
- package/core/server/api/endpoints/utils/serializers/output/utils/extra-attrs.js +67 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/utils/post-gating.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/utils/url.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/validators/index.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/files.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/images.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/index.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/invitations.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/validators/input/invites.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/labels.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/media.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/members.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/oembed.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/pages.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/password_reset.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/validators/input/posts.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/settings.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/setup.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/validators/input/snippets.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/tags.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/tiers.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/users.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/validators/input/webhooks.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/output/index.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/utils/json-schema.js +0 -0
- package/core/server/api/{canary → endpoints}/webhooks.js +0 -0
- package/core/server/api/index.js +1 -1
- package/core/server/data/exporter/table-lists.js +4 -2
- package/core/server/data/migrations/versions/5.3/2022-07-04-13-49-add-comments-table.js +13 -0
- package/core/server/data/migrations/versions/5.3/2022-07-05-09-36-add-comments-likes-table.js +9 -0
- package/core/server/data/migrations/versions/5.3/2022-07-05-09-47-add-comments-reports-table.js +10 -0
- package/core/server/data/migrations/versions/5.3/2022-07-05-10-00-add-comment-related-fields-to-members.js +21 -0
- package/core/server/data/migrations/versions/5.3/2022-07-05-12-55-add-comments-crud-permissions.js +68 -0
- package/core/server/data/migrations/versions/5.3/2022-07-05-15-35-add-comment-notifications-field-to-users-table.js +7 -0
- package/core/server/data/migrations/versions/5.3/2022-07-06-07-26-add-comments-enabled-setting.js +8 -0
- package/core/server/data/migrations/versions/5.3/2022-07-06-07-58-add-ghost-explore-integration-role.js +31 -0
- package/core/server/data/migrations/versions/5.3/2022-07-06-09-13-add-ghost-explore-integration-role-permissions.js +11 -0
- package/core/server/data/migrations/versions/5.3/2022-07-06-09-17-add-ghost-explore-integration.js +38 -0
- package/core/server/data/migrations/versions/5.3/2022-07-06-09-26-add-ghost-explore-integration-api-key.js +73 -0
- package/core/server/data/schema/default-settings/default-settings.json +14 -0
- package/core/server/data/schema/fixtures/fixtures.json +65 -2
- package/core/server/data/schema/schema.js +31 -1
- package/core/server/models/base/plugins/crud.js +15 -0
- package/core/server/models/comment-like.js +34 -0
- package/core/server/models/comment.js +163 -0
- package/core/server/models/member.js +2 -1
- package/core/server/models/user.js +2 -1
- package/core/server/services/auth/session/express-session.js +1 -1
- package/core/server/services/comments/email-templates/new-comment-reply.hbs +199 -0
- package/core/server/services/comments/email-templates/new-comment-reply.txt.js +14 -0
- package/core/server/services/comments/email-templates/new-comment.hbs +199 -0
- package/core/server/services/comments/email-templates/new-comment.txt.js +14 -0
- package/core/server/services/comments/emails.js +164 -0
- package/core/server/services/comments/index.js +26 -0
- package/core/server/services/comments/service.js +24 -0
- package/core/server/services/explore/index.js +18 -0
- package/core/server/services/explore/service.js +55 -0
- package/core/server/services/members/middleware.js +4 -4
- package/core/server/services/members/utils.js +2 -1
- package/core/server/services/permissions/can-this.js +18 -5
- package/core/server/services/permissions/parse-context.js +5 -0
- package/core/server/services/permissions/providers.js +17 -1
- package/core/server/services/posts/posts-service.js +14 -0
- package/core/server/services/users.js +84 -1
- package/core/server/web/admin/app.js +4 -0
- package/core/server/web/admin/views/default-prod.html +5 -5
- package/core/server/web/admin/views/default.html +5 -5
- package/core/server/web/api/app.js +2 -2
- package/core/server/web/api/{canary → endpoints}/admin/app.js +4 -4
- package/core/server/web/api/{canary → endpoints}/admin/middleware.js +1 -0
- package/core/server/web/api/{canary → endpoints}/admin/routes.js +6 -1
- package/core/server/web/api/{canary → endpoints}/content/app.js +4 -4
- package/core/server/web/api/{canary → endpoints}/content/middleware.js +0 -0
- package/core/server/web/api/{canary → endpoints}/content/routes.js +1 -1
- package/core/server/web/api/testmode/routes.js +1 -1
- package/core/server/web/comments/index.js +1 -0
- package/core/server/web/comments/routes.js +28 -0
- package/core/server/web/members/app.js +5 -0
- package/core/server/web/parent/frontend.js +1 -0
- package/core/shared/config/defaults.json +16 -6
- package/core/shared/config/env/config.testing.json +4 -0
- package/core/shared/config/overrides.json +1 -0
- package/core/shared/labs.js +2 -1
- package/core/shared/settings-cache/public.js +2 -1
- package/package.json +20 -20
- package/yarn.lock +425 -275
- package/Gruntfile.js +0 -384
- package/core/built/assets/ghost-dark-923c90399aa560625a983a6ae9abb38c.css +0 -1
- package/core/built/assets/ghost.min-c74f50609022cebf13ad28810def68b6.css +0 -1
- package/core/built/assets/img/contributors/AileenCGN-bf8b9ffbb34c0fd93beb8136af07771b.jpeg +0 -0
- package/core/built/assets/img/contributors/ErisDS-c958ccb9e3597320dee745a42f478569.jpeg +0 -0
- package/core/built/assets/img/contributors/GeorginaLusby-6cea5defddee3c4ea7320e580521e832.jpeg +0 -0
- package/core/built/assets/img/contributors/JohnONolan-47041b80c35c6341b9b929b03139aecc.jpeg +0 -0
- package/core/built/assets/img/contributors/acburdine-d9777fe2601dc215afb6723315829c89.jpeg +0 -0
- package/core/built/assets/img/contributors/bnookala-5896fcdd2f477495323e420efe890657.jpeg +0 -0
- package/core/built/assets/img/contributors/cobbspur-07ded67009757d12517621fc856eba62.jpeg +0 -0
- package/core/built/assets/img/contributors/dbalders-452347a406c2ca23657daea9100878f3.jpeg +0 -0
- package/core/built/assets/img/contributors/disordinary-b9997e5debb59b7aadc79ba90955b662.jpeg +0 -0
- package/core/built/assets/img/contributors/felixrieseberg-ecf29e8eadc58fab999c507049f898cf.jpeg +0 -0
- package/core/built/assets/img/contributors/frantzypants-637b03f85dff89700a661fde79daea5c.jpeg +0 -0
- package/core/built/assets/img/contributors/halfdan-00d6783e5fba2900ee1380939297d8ee.jpeg +0 -0
- package/core/built/assets/img/contributors/jaswilli-8cc9a8d2539ca03239d113dfb25ff5c2.jpeg +0 -0
- package/core/built/assets/img/contributors/kevinansfield-925606c55bc2f3f2f05c0fa58b953ad1.jpeg +0 -0
- package/core/built/assets/img/contributors/kevinkucharczyk-3c7dfe2a103a83737b9d5ee8e19d67f8.jpeg +0 -0
- package/core/built/assets/img/contributors/kirrg001-79823418f2ca21e81719653f0286f95b.jpeg +0 -0
- package/core/built/assets/img/contributors/mixonic-1ff87736dd02cfa080ae109b45131aa6.png +0 -0
- package/core/built/assets/img/contributors/rwjblue-5c7cc009cda45baca2d45f0d1ed19e48.jpeg +0 -0
- package/core/built/assets/img/contributors/sebgie-0fb02df00ee7834dbcc8beba84aec81e.png +0 -0
- package/core/built/assets/img/contributors/tgriesser-d871cbf74a871c0fb6d855e76a893f7e.png +0 -0
- package/core/server/api/canary/utils/serializers/output/utils/extra-attrs.js +0 -33
- package/urls.json +0 -597
package/core/server/data/migrations/versions/5.3/2022-07-06-09-17-add-ghost-explore-integration.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
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');
|
|
8
|
+
const existingIntegration = await knex('integrations').where({
|
|
9
|
+
type: 'internal',
|
|
10
|
+
name: 'Ghost Explore',
|
|
11
|
+
slug: 'ghost-explore'
|
|
12
|
+
}).first();
|
|
13
|
+
|
|
14
|
+
if (existingIntegration) {
|
|
15
|
+
logging.warn('Integration already exists, skipping');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
await knex('integrations').insert({
|
|
20
|
+
id: (new ObjectID()).toHexString(),
|
|
21
|
+
type: 'internal',
|
|
22
|
+
name: 'Ghost Explore',
|
|
23
|
+
description: 'Internal Integration for the Ghost Explore directory',
|
|
24
|
+
slug: 'ghost-explore',
|
|
25
|
+
created_at: knex.raw('current_timestamp'),
|
|
26
|
+
created_by: meta.MIGRATION_USER
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
async function down(knex) {
|
|
30
|
+
logging.info('Deleting Ghost Explore Integration');
|
|
31
|
+
|
|
32
|
+
await knex('integrations').where({
|
|
33
|
+
type: 'internal',
|
|
34
|
+
name: 'Ghost Explore',
|
|
35
|
+
slug: 'ghost-explore'
|
|
36
|
+
}).del();
|
|
37
|
+
}
|
|
38
|
+
);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const {InternalServerError} = require('@tryghost/errors');
|
|
2
|
+
const logging = require('@tryghost/logging');
|
|
3
|
+
const security = require('@tryghost/security');
|
|
4
|
+
const {default: ObjectID} = require('bson-objectid');
|
|
5
|
+
const {createTransactionalMigration, meta} = require('../../utils');
|
|
6
|
+
|
|
7
|
+
module.exports = createTransactionalMigration(
|
|
8
|
+
async function up(knex) {
|
|
9
|
+
logging.info('Adding Admin API key for Ghost Explore Integration');
|
|
10
|
+
|
|
11
|
+
const integration = await knex('integrations').where({
|
|
12
|
+
slug: 'ghost-explore',
|
|
13
|
+
type: 'internal',
|
|
14
|
+
name: 'Ghost Explore'
|
|
15
|
+
}).first();
|
|
16
|
+
|
|
17
|
+
if (!integration) {
|
|
18
|
+
throw new InternalServerError('Could not find Ghost Explore Integration');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const role = await knex('roles').where({
|
|
22
|
+
name: 'Ghost Explore Integration'
|
|
23
|
+
}).first();
|
|
24
|
+
|
|
25
|
+
if (!role) {
|
|
26
|
+
throw new InternalServerError('Could not find Ghost Explore Integration Role');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const existingKey = await knex('api_keys').where({
|
|
30
|
+
integration_id: integration.id,
|
|
31
|
+
role_id: role.id
|
|
32
|
+
}).first();
|
|
33
|
+
|
|
34
|
+
if (existingKey) {
|
|
35
|
+
logging.warn('Admin API key already exists');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
await knex('api_keys').insert({
|
|
40
|
+
id: (new ObjectID()).toHexString(),
|
|
41
|
+
type: 'admin',
|
|
42
|
+
secret: security.secret.create('admin'),
|
|
43
|
+
role_id: role.id,
|
|
44
|
+
integration_id: integration.id,
|
|
45
|
+
created_at: knex.raw('current_timestamp'),
|
|
46
|
+
created_by: meta.MIGRATION_USER
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
async function down(knex) {
|
|
50
|
+
logging.info('Removing Ghost Explore API key');
|
|
51
|
+
|
|
52
|
+
const integration = await knex('integrations').where({
|
|
53
|
+
slug: 'ghost-explore',
|
|
54
|
+
type: 'internal',
|
|
55
|
+
name: 'Ghost Explore'
|
|
56
|
+
}).first();
|
|
57
|
+
|
|
58
|
+
const role = await knex('roles').where({
|
|
59
|
+
name: 'Ghost Explore Integration'
|
|
60
|
+
}).first();
|
|
61
|
+
|
|
62
|
+
if (!role || !integration) {
|
|
63
|
+
logging.warn('Could not delete API key');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
logging.info('Deleting API Key');
|
|
68
|
+
await knex('api_keys').where({
|
|
69
|
+
integration_id: integration.id,
|
|
70
|
+
role_id: role.id
|
|
71
|
+
}).del();
|
|
72
|
+
}
|
|
73
|
+
);
|
|
@@ -450,5 +450,19 @@
|
|
|
450
450
|
"defaultValue": "all",
|
|
451
451
|
"type": "string"
|
|
452
452
|
}
|
|
453
|
+
},
|
|
454
|
+
"comments": {
|
|
455
|
+
"comments_enabled": {
|
|
456
|
+
"type": "string",
|
|
457
|
+
"defaultValue": "off",
|
|
458
|
+
"validations": {
|
|
459
|
+
"isEmpty": false,
|
|
460
|
+
"isIn": [[
|
|
461
|
+
"off",
|
|
462
|
+
"all",
|
|
463
|
+
"paid"
|
|
464
|
+
]]
|
|
465
|
+
}
|
|
466
|
+
}
|
|
453
467
|
}
|
|
454
468
|
}
|
|
@@ -69,6 +69,10 @@
|
|
|
69
69
|
"name": "Admin Integration",
|
|
70
70
|
"description": "External Apps"
|
|
71
71
|
},
|
|
72
|
+
{
|
|
73
|
+
"name": "Ghost Explore Integration",
|
|
74
|
+
"description": "Internal Integration for the Ghost Explore directory"
|
|
75
|
+
},
|
|
72
76
|
{
|
|
73
77
|
"name": "DB Backup Integration",
|
|
74
78
|
"description": "Internal DB Backup Client"
|
|
@@ -82,6 +86,11 @@
|
|
|
82
86
|
{
|
|
83
87
|
"name": "Permission",
|
|
84
88
|
"entries": [
|
|
89
|
+
{
|
|
90
|
+
"name": "Read explore data",
|
|
91
|
+
"action_type": "read",
|
|
92
|
+
"object_type": "explore"
|
|
93
|
+
},
|
|
85
94
|
{
|
|
86
95
|
"name": "Export database",
|
|
87
96
|
"action_type": "exportContent",
|
|
@@ -561,6 +570,46 @@
|
|
|
561
570
|
"name": "Edit newsletters",
|
|
562
571
|
"action_type": "edit",
|
|
563
572
|
"object_type": "newsletter"
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
"name": "Browse comments",
|
|
576
|
+
"action_type": "browse",
|
|
577
|
+
"object_type": "comment"
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
"name": "Read comments",
|
|
581
|
+
"action_type": "read",
|
|
582
|
+
"object_type": "comment"
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
"name": "Edit comments",
|
|
586
|
+
"action_type": "edit",
|
|
587
|
+
"object_type": "comment"
|
|
588
|
+
},
|
|
589
|
+
{
|
|
590
|
+
"name": "Add comments",
|
|
591
|
+
"action_type": "add",
|
|
592
|
+
"object_type": "comment"
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
"name": "Delete comments",
|
|
596
|
+
"action_type": "destroy",
|
|
597
|
+
"object_type": "comment"
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
"name": "Moderate comments",
|
|
601
|
+
"action_type": "moderate",
|
|
602
|
+
"object_type": "comment"
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
"name": "Like comments",
|
|
606
|
+
"action_type": "like",
|
|
607
|
+
"object_type": "comment"
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
"name": "Unlike comments",
|
|
611
|
+
"action_type": "unlike",
|
|
612
|
+
"object_type": "comment"
|
|
564
613
|
}
|
|
565
614
|
]
|
|
566
615
|
},
|
|
@@ -614,6 +663,13 @@
|
|
|
614
663
|
"type": "builtin",
|
|
615
664
|
"api_keys": [{"type": "admin"}]
|
|
616
665
|
},
|
|
666
|
+
{
|
|
667
|
+
"slug": "ghost-explore",
|
|
668
|
+
"name": "Ghost Explore",
|
|
669
|
+
"description": "Built-in Ghost Explore integration",
|
|
670
|
+
"type": "internal",
|
|
671
|
+
"api_keys": [{"type": "admin", "role": "Ghost Explore Integration"}]
|
|
672
|
+
},
|
|
617
673
|
{
|
|
618
674
|
"slug": "ghost-backup",
|
|
619
675
|
"name": "Ghost Backup",
|
|
@@ -678,7 +734,9 @@
|
|
|
678
734
|
"offer": "all",
|
|
679
735
|
"authentication": "resetAllPasswords",
|
|
680
736
|
"members_stripe_connect": "auth",
|
|
681
|
-
"newsletter": "all"
|
|
737
|
+
"newsletter": "all",
|
|
738
|
+
"explore": "read",
|
|
739
|
+
"comment": "all"
|
|
682
740
|
},
|
|
683
741
|
"DB Backup Integration": {
|
|
684
742
|
"db": "all"
|
|
@@ -686,6 +744,9 @@
|
|
|
686
744
|
"Scheduler Integration": {
|
|
687
745
|
"post": "publish"
|
|
688
746
|
},
|
|
747
|
+
"Ghost Explore Integration": {
|
|
748
|
+
"explore": "read"
|
|
749
|
+
},
|
|
689
750
|
"Admin Integration": {
|
|
690
751
|
"mail": "all",
|
|
691
752
|
"notification": "all",
|
|
@@ -707,7 +768,9 @@
|
|
|
707
768
|
"snippet": "all",
|
|
708
769
|
"product": ["browse", "read", "add", "edit"],
|
|
709
770
|
"offer": ["browse", "read", "add", "edit"],
|
|
710
|
-
"newsletter": ["browse", "read", "add", "edit"]
|
|
771
|
+
"newsletter": ["browse", "read", "add", "edit"],
|
|
772
|
+
"explore": "read",
|
|
773
|
+
"comment": "all"
|
|
711
774
|
},
|
|
712
775
|
"Editor": {
|
|
713
776
|
"notification": "all",
|
|
@@ -148,6 +148,7 @@ module.exports = {
|
|
|
148
148
|
meta_description: {type: 'string', maxlength: 2000, nullable: true, validations: {isLength: {max: 500}}},
|
|
149
149
|
tour: {type: 'text', maxlength: 65535, nullable: true},
|
|
150
150
|
last_seen: {type: 'dateTime', nullable: true},
|
|
151
|
+
comment_notifications: {type: 'boolean', nullable: false, defaultTo: true},
|
|
151
152
|
created_at: {type: 'dateTime', nullable: false},
|
|
152
153
|
created_by: {type: 'string', maxlength: 24, nullable: false},
|
|
153
154
|
updated_at: {type: 'dateTime', nullable: true},
|
|
@@ -392,12 +393,15 @@ module.exports = {
|
|
|
392
393
|
}
|
|
393
394
|
},
|
|
394
395
|
name: {type: 'string', maxlength: 191, nullable: true},
|
|
396
|
+
bio: {type: 'string', maxlength: 191, nullable: true, validations: {isLength: {max: 50}}},
|
|
395
397
|
note: {type: 'string', maxlength: 2000, nullable: true},
|
|
396
398
|
geolocation: {type: 'string', maxlength: 2000, nullable: true},
|
|
399
|
+
enable_comment_notifications: {type: 'boolean', nullable: false, defaultTo: true},
|
|
397
400
|
email_count: {type: 'integer', unsigned: true, nullable: false, defaultTo: 0},
|
|
398
401
|
email_opened_count: {type: 'integer', unsigned: true, nullable: false, defaultTo: 0},
|
|
399
402
|
email_open_rate: {type: 'integer', unsigned: true, nullable: true, index: true},
|
|
400
|
-
last_seen_at: {type: 'dateTime',nullable: true},
|
|
403
|
+
last_seen_at: {type: 'dateTime', nullable: true},
|
|
404
|
+
last_commented_at: {type: 'dateTime', nullable: true},
|
|
401
405
|
created_at: {type: 'dateTime', nullable: false},
|
|
402
406
|
created_by: {type: 'string', maxlength: 24, nullable: false},
|
|
403
407
|
updated_at: {type: 'dateTime', nullable: true},
|
|
@@ -742,5 +746,31 @@ module.exports = {
|
|
|
742
746
|
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
|
743
747
|
member_id: {type: 'string', maxlength: 24, nullable: false, references: 'members.id', cascadeDelete: true},
|
|
744
748
|
newsletter_id: {type: 'string', maxlength: 24, nullable: false, references: 'newsletters.id', cascadeDelete: true}
|
|
749
|
+
},
|
|
750
|
+
comments: {
|
|
751
|
+
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
|
752
|
+
post_id: {type: 'string', maxlength: 24, nullable: false, unique: false, references: 'posts.id', cascadeDelete: true},
|
|
753
|
+
member_id: {type: 'string', maxlength: 24, nullable: true, unique: false, references: 'members.id'},
|
|
754
|
+
parent_id: {type: 'string', maxlength: 24, nullable: true, unique: false, references: 'comments.id'},
|
|
755
|
+
status: {type: 'string', maxlength: 50, nullable: false, defaultTo: 'published', validations: {isIn: [['published', 'hidden', 'deleted']]}},
|
|
756
|
+
html: {type: 'text', maxlength: 1000000000, fieldtype: 'long', nullable: true},
|
|
757
|
+
edited_at: {type: 'dateTime', nullable: true},
|
|
758
|
+
created_at: {type: 'dateTime', nullable: false},
|
|
759
|
+
updated_at: {type: 'dateTime', nullable: false}
|
|
760
|
+
},
|
|
761
|
+
comment_likes: {
|
|
762
|
+
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
|
763
|
+
comment_id: {type: 'string', maxlength: 24, nullable: false, unique: false, references: 'comments.id', cascadeDelete: true},
|
|
764
|
+
member_id: {type: 'string', maxlength: 24, nullable: true, unique: false, references: 'members.id'},
|
|
765
|
+
created_at: {type: 'dateTime', nullable: false},
|
|
766
|
+
updated_at: {type: 'dateTime', nullable: false}
|
|
767
|
+
},
|
|
768
|
+
comment_reports: {
|
|
769
|
+
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
|
770
|
+
comment_id: {type: 'string', maxlength: 24, nullable: false, unique: false, references: 'comments.id', cascadeDelete: true},
|
|
771
|
+
member_id: {type: 'string', maxlength: 24, nullable: true, unique: false, references: 'members.id'},
|
|
772
|
+
reason: {type: 'text', maxlength: 65535, nullable: false},
|
|
773
|
+
created_at: {type: 'dateTime', nullable: false},
|
|
774
|
+
updated_at: {type: 'dateTime', nullable: false}
|
|
745
775
|
}
|
|
746
776
|
};
|
|
@@ -7,6 +7,16 @@ const messages = {
|
|
|
7
7
|
couldNotUnderstandRequest: 'Could not understand request.'
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
+
// If user requested an excerpt we need to ensure plaintext and custom_excerpt is also included so we can include it when we query the database.
|
|
11
|
+
const requiredForExcerpt = (requestedColumns) => {
|
|
12
|
+
if (requestedColumns){
|
|
13
|
+
if (requestedColumns.includes('excerpt') && !requestedColumns.includes('plaintext') && !requestedColumns.includes('plaintext') || !requestedColumns) {
|
|
14
|
+
requestedColumns.push('plaintext');
|
|
15
|
+
requestedColumns.push('custom_excerpt');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
10
20
|
/**
|
|
11
21
|
* @param {Bookshelf} Bookshelf
|
|
12
22
|
*/
|
|
@@ -72,6 +82,8 @@ module.exports = function (Bookshelf) {
|
|
|
72
82
|
const options = this.filterOptions(unfilteredOptions, 'findPage');
|
|
73
83
|
const itemCollection = this.getFilteredCollection(options);
|
|
74
84
|
const requestedColumns = options.columns;
|
|
85
|
+
// make sure we include plaintext and custom_excerpt if excerpt is requested
|
|
86
|
+
requiredForExcerpt(requestedColumns);
|
|
75
87
|
|
|
76
88
|
// Set this to true or pass ?debug=true as an API option to get output
|
|
77
89
|
itemCollection.debug = unfilteredOptions.debug && process.env.NODE_ENV !== 'production';
|
|
@@ -126,6 +138,9 @@ module.exports = function (Bookshelf) {
|
|
|
126
138
|
const options = this.filterOptions(unfilteredOptions, 'findOne');
|
|
127
139
|
data = this.filterData(data);
|
|
128
140
|
const model = this.forge(data);
|
|
141
|
+
const requestedColumns = options.columns;
|
|
142
|
+
// make sure we include plaintext and custom_excerpt if excerpt is requested
|
|
143
|
+
requiredForExcerpt(requestedColumns);
|
|
129
144
|
|
|
130
145
|
// @NOTE: The API layer decides if this option is allowed
|
|
131
146
|
if (options.filter) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const ghostBookshelf = require('./base');
|
|
2
|
+
|
|
3
|
+
const CommentLike = ghostBookshelf.Model.extend({
|
|
4
|
+
tableName: 'comment_likes',
|
|
5
|
+
|
|
6
|
+
defaults: function defaults() {
|
|
7
|
+
return {};
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
comment() {
|
|
11
|
+
return this.belongsTo('Comment', 'comment_id');
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
member() {
|
|
15
|
+
return this.belongsTo('Member', 'member_id');
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
emitChange: function emitChange(event, options) {
|
|
19
|
+
const eventToTrigger = 'comment_like' + '.' + event;
|
|
20
|
+
ghostBookshelf.Model.prototype.emitChange.bind(this)(this, eventToTrigger, options);
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
onCreated: function onCreated(model, options) {
|
|
24
|
+
ghostBookshelf.Model.prototype.onCreated.apply(this, arguments);
|
|
25
|
+
|
|
26
|
+
model.emitChange('added', options);
|
|
27
|
+
}
|
|
28
|
+
}, {
|
|
29
|
+
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
module.exports = {
|
|
33
|
+
CommentLike: ghostBookshelf.model('CommentLike', CommentLike)
|
|
34
|
+
};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
const ghostBookshelf = require('./base');
|
|
2
|
+
const _ = require('lodash');
|
|
3
|
+
const errors = require('@tryghost/errors');
|
|
4
|
+
const tpl = require('@tryghost/tpl');
|
|
5
|
+
const commentsService = require('../services/comments');
|
|
6
|
+
|
|
7
|
+
const messages = {
|
|
8
|
+
commentNotFound: 'Comment could not be found',
|
|
9
|
+
notYourCommentToEdit: 'You may only edit your own comments',
|
|
10
|
+
notYourCommentToDestroy: 'You may only delete your own comments'
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const Comment = ghostBookshelf.Model.extend({
|
|
14
|
+
tableName: 'comments',
|
|
15
|
+
|
|
16
|
+
defaults: function defaults() {
|
|
17
|
+
return {
|
|
18
|
+
status: 'published'
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
post() {
|
|
23
|
+
return this.belongsTo('Post', 'post_id');
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
member() {
|
|
27
|
+
return this.belongsTo('Member', 'member_id');
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
parent() {
|
|
31
|
+
return this.belongsTo('Comment', 'parent_id');
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
likes() {
|
|
35
|
+
return this.hasMany('CommentLike', 'comment_id');
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
replies() {
|
|
39
|
+
return this.hasMany('Comment', 'parent_id');
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
emitChange: function emitChange(event, options) {
|
|
43
|
+
const eventToTrigger = 'comment' + '.' + event;
|
|
44
|
+
ghostBookshelf.Model.prototype.emitChange.bind(this)(this, eventToTrigger, options);
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
onSaving() {
|
|
48
|
+
ghostBookshelf.Model.prototype.onSaving.apply(this, arguments);
|
|
49
|
+
|
|
50
|
+
if (this.hasChanged('html')) {
|
|
51
|
+
const sanitizeHtml = require('sanitize-html');
|
|
52
|
+
|
|
53
|
+
this.set('html', sanitizeHtml(this.get('html'), {
|
|
54
|
+
allowedTags: ['p', 'br', 'a', 'blockquote'],
|
|
55
|
+
allowedAttributes: {
|
|
56
|
+
a: ['href', 'target', 'rel']
|
|
57
|
+
},
|
|
58
|
+
selfClosing: ['br'],
|
|
59
|
+
// Enforce _blank and safe URLs
|
|
60
|
+
transformTags: {
|
|
61
|
+
a: sanitizeHtml.simpleTransform('a', {
|
|
62
|
+
target: '_blank',
|
|
63
|
+
rel: 'ugc noopener noreferrer nofollow'
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
onCreated: function onCreated(model, options) {
|
|
71
|
+
ghostBookshelf.Model.prototype.onCreated.apply(this, arguments);
|
|
72
|
+
|
|
73
|
+
if (!options.context.internal) {
|
|
74
|
+
commentsService.api.sendNewCommentNotifications(model);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
model.emitChange('added', options);
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
enforcedFilters: function enforcedFilters() {
|
|
81
|
+
return 'parent_id:null';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
}, {
|
|
85
|
+
destroy: function destroy(unfilteredOptions) {
|
|
86
|
+
let options = this.filterOptions(unfilteredOptions, 'destroy', {extraAllowedProperties: ['id']});
|
|
87
|
+
|
|
88
|
+
const softDelete = () => {
|
|
89
|
+
return ghostBookshelf.Model.edit.call(this, {status: 'deleted'}, options);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
if (!options.transacting) {
|
|
93
|
+
return ghostBookshelf.transaction((transacting) => {
|
|
94
|
+
options.transacting = transacting;
|
|
95
|
+
return softDelete();
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return softDelete();
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
async permissible(commentModelOrId, action, context, unsafeAttrs, loadedPermissions, hasUserPermission, hasApiKeyPermission, hasMemberPermission) {
|
|
103
|
+
const self = this;
|
|
104
|
+
|
|
105
|
+
if (hasUserPermission) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (_.isString(commentModelOrId)) {
|
|
110
|
+
// Grab the original args without the first one
|
|
111
|
+
const origArgs = _.toArray(arguments).slice(1);
|
|
112
|
+
|
|
113
|
+
// Get the actual comment model
|
|
114
|
+
return this.findOne({
|
|
115
|
+
id: commentModelOrId
|
|
116
|
+
}).then(function then(foundCommentModel) {
|
|
117
|
+
if (!foundCommentModel) {
|
|
118
|
+
throw new errors.NotFoundError({
|
|
119
|
+
message: tpl(messages.commentNotFound)
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Build up the original args but substitute with actual model
|
|
124
|
+
const newArgs = [foundCommentModel].concat(origArgs);
|
|
125
|
+
|
|
126
|
+
return self.permissible.apply(self, newArgs);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (action === 'edit' && commentModelOrId.get('member_id') !== context.member.id) {
|
|
131
|
+
return Promise.reject(new errors.NoPermissionError({
|
|
132
|
+
message: tpl(messages.notYourCommentToEdit)
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (action === 'destroy' && commentModelOrId.get('member_id') !== context.member.id) {
|
|
137
|
+
return Promise.reject(new errors.NoPermissionError({
|
|
138
|
+
message: tpl(messages.notYourCommentToDestroy)
|
|
139
|
+
}));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return hasMemberPermission;
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* We have to ensure consistency. If you listen on model events (e.g. `member.added`), you can expect that you always
|
|
147
|
+
* receive all fields including relations. Otherwise you can't rely on a consistent flow. And we want to avoid
|
|
148
|
+
* that event listeners have to re-fetch a resource. This function is used in the context of inserting
|
|
149
|
+
* and updating resources. We won't return the relations by default for now.
|
|
150
|
+
*/
|
|
151
|
+
defaultRelations: function defaultRelations(methodName, options) {
|
|
152
|
+
// @todo: the default relations are not working for 'add' when we add it below
|
|
153
|
+
if (['findAll', 'findPage', 'edit', 'findOne'].indexOf(methodName) !== -1) {
|
|
154
|
+
options.withRelated = _.union(['member', 'likes', 'replies', 'replies.member', 'replies.likes'], options.withRelated || []);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return options;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
module.exports = {
|
|
162
|
+
Comment: ghostBookshelf.model('Comment', Comment)
|
|
163
|
+
};
|