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
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const ExploreService = require('./service');
|
|
2
|
+
|
|
3
|
+
const MembersService = require('../members');
|
|
4
|
+
const PostsService = require('../posts/posts-service')();
|
|
5
|
+
const PublicConfigService = require('../public-config');
|
|
6
|
+
const StatsService = require('../stats');
|
|
7
|
+
const StripeService = require('../stripe');
|
|
8
|
+
|
|
9
|
+
const models = require('../../models');
|
|
10
|
+
|
|
11
|
+
module.exports = new ExploreService({
|
|
12
|
+
MembersService,
|
|
13
|
+
PostsService,
|
|
14
|
+
PublicConfigService,
|
|
15
|
+
StatsService,
|
|
16
|
+
StripeService,
|
|
17
|
+
UserModel: models.User
|
|
18
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const ghostVersion = require('@tryghost/version');
|
|
2
|
+
|
|
3
|
+
module.exports = class ExploreService {
|
|
4
|
+
/**
|
|
5
|
+
* @param {Object} options
|
|
6
|
+
* @param {Object} options.MembersService
|
|
7
|
+
* @param {Object} options.PostsService
|
|
8
|
+
* @param {Object} options.PublicConfigService
|
|
9
|
+
* @param {Object} options.StatsService
|
|
10
|
+
* @param {Object} options.StripeService
|
|
11
|
+
* @param {Object} options.UserModel
|
|
12
|
+
*/
|
|
13
|
+
constructor({MembersService, PostsService, PublicConfigService, StatsService, StripeService, UserModel}) {
|
|
14
|
+
this.MembersService = MembersService;
|
|
15
|
+
this.PostsService = PostsService;
|
|
16
|
+
this.PublicConfigService = PublicConfigService;
|
|
17
|
+
this.StatsService = StatsService;
|
|
18
|
+
this.StripeService = StripeService;
|
|
19
|
+
this.UserModel = UserModel;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Build and return the response object containing the data for the Ghost Explore endpoint
|
|
24
|
+
*/
|
|
25
|
+
async fetchData() {
|
|
26
|
+
const totalMembers = await this.MembersService.stats.getTotalMembers();
|
|
27
|
+
const mrrStats = await this.StatsService.getMRRHistory();
|
|
28
|
+
|
|
29
|
+
const {description, icon, title, url} = this.PublicConfigService.site;
|
|
30
|
+
|
|
31
|
+
const exploreProperties = {
|
|
32
|
+
version: ghostVersion.full,
|
|
33
|
+
totalMembers,
|
|
34
|
+
mrrStats,
|
|
35
|
+
site: {
|
|
36
|
+
description,
|
|
37
|
+
icon,
|
|
38
|
+
title,
|
|
39
|
+
url
|
|
40
|
+
},
|
|
41
|
+
stripe: {
|
|
42
|
+
configured: this.StripeService.api.configured,
|
|
43
|
+
livemode: (this.StripeService.api.configured && this.StripeService.api.mode === 'live')
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const mostRecentlyPublishedPost = await this.PostsService.getMostRecentlyPublishedPost();
|
|
48
|
+
exploreProperties.mostRecentlyPublishedAt = mostRecentlyPublishedPost?.get('published_at') || null;
|
|
49
|
+
|
|
50
|
+
const owner = await this.UserModel.findOne({role: 'Owner', status: 'all'});
|
|
51
|
+
exploreProperties.ownerEmail = owner?.get('email') || null;
|
|
52
|
+
|
|
53
|
+
return exploreProperties;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
@@ -75,7 +75,7 @@ const getMemberNewsletters = async function (req, res) {
|
|
|
75
75
|
return res.end('Email address not found.');
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
const data = _.pick(memberData.toJSON(), 'uuid', 'email', 'name', 'newsletters', 'status');
|
|
78
|
+
const data = _.pick(memberData.toJSON(), 'uuid', 'email', 'name', 'newsletters', 'enable_comment_notifications', 'status');
|
|
79
79
|
return res.json(data);
|
|
80
80
|
} catch (err) {
|
|
81
81
|
res.writeHead(400);
|
|
@@ -91,7 +91,7 @@ const updateMemberNewsletters = async function (req, res) {
|
|
|
91
91
|
return res.end('Invalid member uuid');
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
const data = _.pick(req.body, 'newsletters');
|
|
94
|
+
const data = _.pick(req.body, 'newsletters', 'enable_comment_notifications');
|
|
95
95
|
const memberData = await membersService.api.members.get({
|
|
96
96
|
uuid: memberUuid
|
|
97
97
|
});
|
|
@@ -106,7 +106,7 @@ const updateMemberNewsletters = async function (req, res) {
|
|
|
106
106
|
};
|
|
107
107
|
|
|
108
108
|
const updatedMember = await membersService.api.members.update(data, options);
|
|
109
|
-
const updatedMemberData = _.pick(updatedMember.toJSON(), ['uuid', 'email', 'name', 'newsletters', 'status']);
|
|
109
|
+
const updatedMemberData = _.pick(updatedMember.toJSON(), ['uuid', 'email', 'name', 'newsletters', 'enable_comment_notifications', 'status']);
|
|
110
110
|
res.json(updatedMemberData);
|
|
111
111
|
} catch (err) {
|
|
112
112
|
res.writeHead(400);
|
|
@@ -116,7 +116,7 @@ const updateMemberNewsletters = async function (req, res) {
|
|
|
116
116
|
|
|
117
117
|
const updateMemberData = async function (req, res) {
|
|
118
118
|
try {
|
|
119
|
-
const data = _.pick(req.body, 'name', 'subscribed', 'newsletters');
|
|
119
|
+
const data = _.pick(req.body, 'name', 'subscribed', 'newsletters', 'enable_comment_notifications');
|
|
120
120
|
const member = await membersService.ssr.getMemberDataFromSession(req, res);
|
|
121
121
|
if (member) {
|
|
122
122
|
const options = {
|
|
@@ -16,7 +16,8 @@ module.exports.formattedMemberResponse = function formattedMemberResponse(member
|
|
|
16
16
|
avatar_image: member.avatar_image,
|
|
17
17
|
subscribed: !!member.subscribed,
|
|
18
18
|
subscriptions: member.subscriptions || [],
|
|
19
|
-
paid: member.status !== 'free'
|
|
19
|
+
paid: member.status !== 'free',
|
|
20
|
+
enable_comment_notifications: member.enable_comment_notifications
|
|
20
21
|
};
|
|
21
22
|
if (member.newsletters) {
|
|
22
23
|
data.newsletters = formatNewsletterResponse(member.newsletters);
|
|
@@ -27,7 +27,8 @@ CanThisResult.prototype.buildObjectTypeHandlers = function (objTypes, actType, c
|
|
|
27
27
|
permission: models.Permission,
|
|
28
28
|
setting: models.Settings,
|
|
29
29
|
invite: models.Invite,
|
|
30
|
-
integration: models.Integration
|
|
30
|
+
integration: models.Integration,
|
|
31
|
+
comment: models.Comment
|
|
31
32
|
};
|
|
32
33
|
|
|
33
34
|
// Iterate through the object types, i.e. ['post', 'tag', 'user']
|
|
@@ -57,10 +58,12 @@ CanThisResult.prototype.buildObjectTypeHandlers = function (objTypes, actType, c
|
|
|
57
58
|
return permissionLoad.then(function (loadedPermissions) {
|
|
58
59
|
// Iterate through the user permissions looking for an affirmation
|
|
59
60
|
const userPermissions = loadedPermissions.user ? loadedPermissions.user.permissions : null;
|
|
60
|
-
|
|
61
61
|
const apiKeyPermissions = loadedPermissions.apiKey ? loadedPermissions.apiKey.permissions : null;
|
|
62
|
+
const memberPermissions = loadedPermissions.member ? loadedPermissions.member.permissions : null;
|
|
63
|
+
|
|
62
64
|
let hasUserPermission;
|
|
63
65
|
let hasApiKeyPermission;
|
|
66
|
+
let hasMemberPermission = false;
|
|
64
67
|
|
|
65
68
|
const checkPermission = function (perm) {
|
|
66
69
|
let permObjId;
|
|
@@ -91,6 +94,10 @@ CanThisResult.prototype.buildObjectTypeHandlers = function (objTypes, actType, c
|
|
|
91
94
|
hasUserPermission = _.some(userPermissions, checkPermission);
|
|
92
95
|
}
|
|
93
96
|
|
|
97
|
+
if (loadedPermissions.member) {
|
|
98
|
+
hasMemberPermission = _.some(memberPermissions, checkPermission);
|
|
99
|
+
}
|
|
100
|
+
|
|
94
101
|
// Check api key permissions if they were passed
|
|
95
102
|
hasApiKeyPermission = true;
|
|
96
103
|
if (!_.isNull(apiKeyPermissions)) {
|
|
@@ -102,7 +109,7 @@ CanThisResult.prototype.buildObjectTypeHandlers = function (objTypes, actType, c
|
|
|
102
109
|
// Offer a chance for the TargetModel to override the results
|
|
103
110
|
if (TargetModel && _.isFunction(TargetModel.permissible)) {
|
|
104
111
|
return TargetModel.permissible(
|
|
105
|
-
modelId, actType, context, unsafeAttrs, loadedPermissions, hasUserPermission, hasApiKeyPermission
|
|
112
|
+
modelId, actType, context, unsafeAttrs, loadedPermissions, hasUserPermission, hasApiKeyPermission, hasMemberPermission
|
|
106
113
|
);
|
|
107
114
|
}
|
|
108
115
|
|
|
@@ -122,6 +129,7 @@ CanThisResult.prototype.beginCheck = function (context) {
|
|
|
122
129
|
const self = this;
|
|
123
130
|
let userPermissionLoad;
|
|
124
131
|
let apiKeyPermissionLoad;
|
|
132
|
+
let memberPermissionLoad;
|
|
125
133
|
let permissionsLoad;
|
|
126
134
|
|
|
127
135
|
// Get context.user, context.api_key and context.app
|
|
@@ -147,11 +155,16 @@ CanThisResult.prototype.beginCheck = function (context) {
|
|
|
147
155
|
apiKeyPermissionLoad = Promise.resolve(null);
|
|
148
156
|
}
|
|
149
157
|
|
|
158
|
+
if (context.member) {
|
|
159
|
+
memberPermissionLoad = providers.member(context.member.id);
|
|
160
|
+
}
|
|
161
|
+
|
|
150
162
|
// Wait for both user and app permissions to load
|
|
151
|
-
permissionsLoad = Promise.all([userPermissionLoad, apiKeyPermissionLoad]).then(function (result) {
|
|
163
|
+
permissionsLoad = Promise.all([userPermissionLoad, apiKeyPermissionLoad, memberPermissionLoad]).then(function (result) {
|
|
152
164
|
return {
|
|
153
165
|
user: result[0],
|
|
154
|
-
apiKey: result[1]
|
|
166
|
+
apiKey: result[1],
|
|
167
|
+
member: result[2]
|
|
155
168
|
};
|
|
156
169
|
});
|
|
157
170
|
|
|
@@ -12,6 +12,7 @@ module.exports = function parseContext(context) {
|
|
|
12
12
|
user: null,
|
|
13
13
|
api_key: null,
|
|
14
14
|
integration: null,
|
|
15
|
+
member: null,
|
|
15
16
|
public: true
|
|
16
17
|
};
|
|
17
18
|
|
|
@@ -37,5 +38,9 @@ module.exports = function parseContext(context) {
|
|
|
37
38
|
parsed.public = (context.api_key.type === 'content');
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
if (context && context.member) {
|
|
42
|
+
parsed.member = context.member;
|
|
43
|
+
}
|
|
44
|
+
|
|
40
45
|
return parsed;
|
|
41
46
|
};
|
|
@@ -6,7 +6,8 @@ const tpl = require('@tryghost/tpl');
|
|
|
6
6
|
|
|
7
7
|
const messages = {
|
|
8
8
|
userNotFound: 'User not found',
|
|
9
|
-
apiKeyNotFound: 'API Key not found'
|
|
9
|
+
apiKeyNotFound: 'API Key not found',
|
|
10
|
+
memberNotFound: 'Member not found'
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
module.exports = {
|
|
@@ -72,5 +73,20 @@ module.exports = {
|
|
|
72
73
|
|
|
73
74
|
return {permissions, roles};
|
|
74
75
|
});
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
async member(id) {
|
|
79
|
+
const foundMember = await models.Member.findOne({id});
|
|
80
|
+
if (!foundMember) {
|
|
81
|
+
throw new errors.NotFoundError({
|
|
82
|
+
message: tpl(messages.memberNotFound)
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// @TODO: figure out how we want to associate members with permissions
|
|
87
|
+
// Dirty code to load all comment permissions except moderation for members
|
|
88
|
+
const permissions = await models.Permission.findAll({filter: 'object_type:comment+action_type:-moderate'});
|
|
89
|
+
|
|
90
|
+
return {permissions: permissions.models};
|
|
75
91
|
}
|
|
76
92
|
};
|
|
@@ -76,6 +76,20 @@ class PostsService {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Returns the most recently `published_at` post that was published or sent
|
|
81
|
+
* via email
|
|
82
|
+
*/
|
|
83
|
+
async getMostRecentlyPublishedPost() {
|
|
84
|
+
const recentlyPublishedPost = await this.models.Post.findPage({
|
|
85
|
+
status: ['published', 'sent'],
|
|
86
|
+
order: 'published_at DESC',
|
|
87
|
+
limit: 1
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return recentlyPublishedPost?.data[0];
|
|
91
|
+
}
|
|
92
|
+
|
|
79
93
|
/**
|
|
80
94
|
* Calculates if the email should be tried to be sent out
|
|
81
95
|
* @private
|
|
@@ -46,6 +46,8 @@ class Users {
|
|
|
46
46
|
this.auth = auth;
|
|
47
47
|
this.apiMail = apiMail;
|
|
48
48
|
this.apiSettings = apiSettings;
|
|
49
|
+
|
|
50
|
+
this.assignTagToUserPosts = this.assignTagToUserPosts.bind(this);
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
async resetAllPasswords(frameOptions) {
|
|
@@ -68,6 +70,77 @@ class Users {
|
|
|
68
70
|
});
|
|
69
71
|
}
|
|
70
72
|
|
|
73
|
+
async assignTagToUserPosts({id, context, transacting}) {
|
|
74
|
+
// create an internal tag to assign to reassigned posts
|
|
75
|
+
// in following format: `#{author_slug}`
|
|
76
|
+
const author = await this.models.User.findOne({
|
|
77
|
+
id
|
|
78
|
+
}, {
|
|
79
|
+
id,
|
|
80
|
+
context,
|
|
81
|
+
transacting
|
|
82
|
+
});
|
|
83
|
+
let tag = await this.models.Tag.findOne({
|
|
84
|
+
slug: `hash-${author.get('slug')}`
|
|
85
|
+
}, {
|
|
86
|
+
context,
|
|
87
|
+
transacting
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (!tag) {
|
|
91
|
+
tag = await this.models.Tag.add({
|
|
92
|
+
slug: `#${author.get('slug')}`
|
|
93
|
+
}, {
|
|
94
|
+
context,
|
|
95
|
+
transacting
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const userPosts = await this.models.Base.knex('posts_authors')
|
|
100
|
+
.transacting(transacting)
|
|
101
|
+
.where('author_id', id)
|
|
102
|
+
.select('post_id');
|
|
103
|
+
const usersPostIds = userPosts.map(p => p.post_id);
|
|
104
|
+
|
|
105
|
+
// Add a tag to all posts that do not have the author tag yet
|
|
106
|
+
// NOTE: the method is implemented in an iterative way to avoid
|
|
107
|
+
// memory consumption in case the user has thousands of posts
|
|
108
|
+
// assigned to them. Also, didn't have any "bulk" way to add
|
|
109
|
+
// a tag to multiple posts as the "sort_order" needs custom
|
|
110
|
+
// logic to be run for each post.
|
|
111
|
+
// Rewrite this bit if/when we hit a performance bottleneck here
|
|
112
|
+
for (const postId of usersPostIds) {
|
|
113
|
+
const post = await this.models.Post.findOne({
|
|
114
|
+
id: postId
|
|
115
|
+
}, {
|
|
116
|
+
id: postId,
|
|
117
|
+
withRelated: ['tags'],
|
|
118
|
+
context,
|
|
119
|
+
transacting
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// check if tag already assigned to the post
|
|
123
|
+
const existingTagSlugs = post.relations.tags.models.map(t => t.get('slug'));
|
|
124
|
+
|
|
125
|
+
if (!existingTagSlugs.includes(tag.get('slug'))) {
|
|
126
|
+
await this.models.Post.edit({
|
|
127
|
+
tags: [...post.relations.tags.models, tag]
|
|
128
|
+
}, {
|
|
129
|
+
id: postId,
|
|
130
|
+
context,
|
|
131
|
+
transacting
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
*
|
|
139
|
+
* @param {Object} frameOptions
|
|
140
|
+
* @param {string} frameOptions.id - user ID to destroy
|
|
141
|
+
* @param {Object} frameOptions.context - frame context to perform the action
|
|
142
|
+
* @returns
|
|
143
|
+
*/
|
|
71
144
|
async destroyUser(frameOptions) {
|
|
72
145
|
const backupPath = await this.dbBackup.backup();
|
|
73
146
|
const parsedFileName = path.parse(backupPath);
|
|
@@ -76,7 +149,17 @@ class Users {
|
|
|
76
149
|
return this.models.Base.transaction(async (t) => {
|
|
77
150
|
frameOptions.transacting = t;
|
|
78
151
|
|
|
79
|
-
await this.
|
|
152
|
+
await this.assignTagToUserPosts({
|
|
153
|
+
id: frameOptions.id,
|
|
154
|
+
context: frameOptions.context,
|
|
155
|
+
transacting: frameOptions.transacting
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
await this.models.Post.reassignByAuthor({
|
|
159
|
+
id: frameOptions.id,
|
|
160
|
+
context: frameOptions.context,
|
|
161
|
+
transacting: frameOptions.transacting
|
|
162
|
+
});
|
|
80
163
|
|
|
81
164
|
try {
|
|
82
165
|
await this.models.ApiKey.destroy({
|
|
@@ -21,6 +21,10 @@ module.exports = function setupAdminApp() {
|
|
|
21
21
|
{maxAge: (configMaxAge || configMaxAge === 0) ? configMaxAge : constants.ONE_YEAR_MS, fallthrough: false}
|
|
22
22
|
));
|
|
23
23
|
|
|
24
|
+
adminApp.use('/auth-frame', serveStatic(
|
|
25
|
+
config.get('paths').adminAuthAssets
|
|
26
|
+
));
|
|
27
|
+
|
|
24
28
|
// Ember CLI's live-reload script
|
|
25
29
|
if (config.get('env') === 'development') {
|
|
26
30
|
adminApp.get('/ember-cli-live-reload.js', function emberLiveReload(req, res) {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<title>Ghost Admin</title>
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%2F%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.
|
|
11
|
+
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%2F%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.3%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22moment%22%3A%7B%22includeTimezone%22%3A%22all%22%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%7D" />
|
|
12
12
|
|
|
13
13
|
<meta name="HandheldFriendly" content="True" />
|
|
14
14
|
<meta name="MobileOptimized" content="320" />
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
</style>
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
<link rel="stylesheet" href="assets/vendor.min-
|
|
41
|
-
<link rel="stylesheet" href="assets/ghost.min-
|
|
40
|
+
<link rel="stylesheet" href="assets/vendor.min-4a6661c574707ceca220aa2e76558995.css">
|
|
41
|
+
<link rel="stylesheet" href="assets/ghost.min-e7cfbd1800f8e99b9158f74f1e39cd76.css" title="light">
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
|
|
@@ -56,8 +56,8 @@
|
|
|
56
56
|
<div id="ember-basic-dropdown-wormhole"></div>
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
<script src="assets/vendor.min-
|
|
60
|
-
<script src="assets/ghost.min-
|
|
59
|
+
<script src="assets/vendor.min-4076498ccd6c8412365f43b156084ed8.js"></script>
|
|
60
|
+
<script src="assets/ghost.min-f4bba3a2a5ef256b82641345505d4f0f.js"></script>
|
|
61
61
|
|
|
62
62
|
</body>
|
|
63
63
|
</html>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<title>Ghost Admin</title>
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%2F%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.
|
|
11
|
+
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%2F%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.3%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22moment%22%3A%7B%22includeTimezone%22%3A%22all%22%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%7D" />
|
|
12
12
|
|
|
13
13
|
<meta name="HandheldFriendly" content="True" />
|
|
14
14
|
<meta name="MobileOptimized" content="320" />
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
</style>
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
<link rel="stylesheet" href="assets/vendor.min-
|
|
41
|
-
<link rel="stylesheet" href="assets/ghost.min-
|
|
40
|
+
<link rel="stylesheet" href="assets/vendor.min-4a6661c574707ceca220aa2e76558995.css">
|
|
41
|
+
<link rel="stylesheet" href="assets/ghost.min-e7cfbd1800f8e99b9158f74f1e39cd76.css" title="light">
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
|
|
@@ -56,8 +56,8 @@
|
|
|
56
56
|
<div id="ember-basic-dropdown-wormhole"></div>
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
<script src="assets/vendor.min-
|
|
60
|
-
<script src="assets/ghost.min-
|
|
59
|
+
<script src="assets/vendor.min-4076498ccd6c8412365f43b156084ed8.js"></script>
|
|
60
|
+
<script src="assets/ghost.min-f4bba3a2a5ef256b82641345505d4f0f.js"></script>
|
|
61
61
|
|
|
62
62
|
</body>
|
|
63
63
|
</html>
|
|
@@ -16,8 +16,8 @@ module.exports = function setupApiApp() {
|
|
|
16
16
|
apiApp.use(APIVersionCompatibilityService.versionRewrites);
|
|
17
17
|
apiApp.use(APIVersionCompatibilityService.contentVersion);
|
|
18
18
|
|
|
19
|
-
apiApp.lazyUse('/content/', require('./
|
|
20
|
-
apiApp.lazyUse('/admin/', require('./
|
|
19
|
+
apiApp.lazyUse('/content/', require('./endpoints/content/app'));
|
|
20
|
+
apiApp.lazyUse('/admin/', require('./endpoints/admin/app'));
|
|
21
21
|
|
|
22
22
|
// Error handling for requests to non-existent API versions
|
|
23
23
|
apiApp.use(errorHandler.resourceNotFound);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const debug = require('@tryghost/debug')('web:
|
|
1
|
+
const debug = require('@tryghost/debug')('web:endpoints:admin:app');
|
|
2
2
|
const boolParser = require('express-query-boolean');
|
|
3
3
|
const express = require('../../../../../shared/express');
|
|
4
4
|
const bodyParser = require('body-parser');
|
|
@@ -10,8 +10,8 @@ const routes = require('./routes');
|
|
|
10
10
|
const APIVersionCompatibilityService = require('../../../../services/api-version-compatibility');
|
|
11
11
|
|
|
12
12
|
module.exports = function setupApiApp() {
|
|
13
|
-
debug('Admin API
|
|
14
|
-
const apiApp = express('
|
|
13
|
+
debug('Admin API setup start');
|
|
14
|
+
const apiApp = express('admin api');
|
|
15
15
|
|
|
16
16
|
// API middleware
|
|
17
17
|
|
|
@@ -37,7 +37,7 @@ module.exports = function setupApiApp() {
|
|
|
37
37
|
apiApp.use(APIVersionCompatibilityService.errorHandler);
|
|
38
38
|
apiApp.use(errorHandler.handleJSONResponse(sentry));
|
|
39
39
|
|
|
40
|
-
debug('Admin API
|
|
40
|
+
debug('Admin API setup end');
|
|
41
41
|
|
|
42
42
|
return apiApp;
|
|
43
43
|
};
|
|
@@ -7,7 +7,7 @@ const mw = require('./middleware');
|
|
|
7
7
|
const shared = require('../../../shared');
|
|
8
8
|
|
|
9
9
|
module.exports = function apiRoutes() {
|
|
10
|
-
const router = express.Router('
|
|
10
|
+
const router = express.Router('admin api');
|
|
11
11
|
|
|
12
12
|
// alias delete with del
|
|
13
13
|
router.del = router.delete;
|
|
@@ -20,6 +20,9 @@ module.exports = function apiRoutes() {
|
|
|
20
20
|
// ## Configuration
|
|
21
21
|
router.get('/config', mw.authAdminApi, http(api.config.read));
|
|
22
22
|
|
|
23
|
+
// ## Ghost Explore
|
|
24
|
+
router.get('/explore', mw.authAdminApi, http(api.explore.read));
|
|
25
|
+
|
|
23
26
|
// ## Posts
|
|
24
27
|
router.get('/posts', mw.authAdminApi, http(api.posts.browse));
|
|
25
28
|
router.post('/posts', mw.authAdminApi, http(api.posts.add));
|
|
@@ -28,6 +31,8 @@ module.exports = function apiRoutes() {
|
|
|
28
31
|
router.put('/posts/:id', mw.authAdminApi, http(api.posts.edit));
|
|
29
32
|
router.del('/posts/:id', mw.authAdminApi, http(api.posts.destroy));
|
|
30
33
|
|
|
34
|
+
router.put('/comments/:id', mw.authAdminApi, http(api.comments.edit));
|
|
35
|
+
|
|
31
36
|
// ## Pages
|
|
32
37
|
router.get('/pages', mw.authAdminApi, http(api.pages.browse));
|
|
33
38
|
router.post('/pages', mw.authAdminApi, http(api.pages.add));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const debug = require('@tryghost/debug')('web:api:
|
|
1
|
+
const debug = require('@tryghost/debug')('web:api:endpoints:content:app');
|
|
2
2
|
const boolParser = require('express-query-boolean');
|
|
3
3
|
const bodyParser = require('body-parser');
|
|
4
4
|
const express = require('../../../../../shared/express');
|
|
@@ -9,8 +9,8 @@ const errorHandler = require('@tryghost/mw-error-handler');
|
|
|
9
9
|
const apiVersionCompatibility = require('../../../../services/api-version-compatibility');
|
|
10
10
|
|
|
11
11
|
module.exports = function setupApiApp() {
|
|
12
|
-
debug('Content API
|
|
13
|
-
const apiApp = express('
|
|
12
|
+
debug('Content API setup start');
|
|
13
|
+
const apiApp = express('content api');
|
|
14
14
|
|
|
15
15
|
// API middleware
|
|
16
16
|
|
|
@@ -31,7 +31,7 @@ module.exports = function setupApiApp() {
|
|
|
31
31
|
apiApp.use(apiVersionCompatibility.errorHandler);
|
|
32
32
|
apiApp.use(errorHandler.handleJSONResponse(sentry));
|
|
33
33
|
|
|
34
|
-
debug('Content API
|
|
34
|
+
debug('Content API setup end');
|
|
35
35
|
|
|
36
36
|
return apiApp;
|
|
37
37
|
};
|
|
File without changes
|
|
@@ -5,7 +5,7 @@ const jobsService = require('../../../services/jobs');
|
|
|
5
5
|
|
|
6
6
|
/** A bunch of helper routes for testing purposes */
|
|
7
7
|
module.exports = function testRoutes() {
|
|
8
|
-
const router = express.Router('
|
|
8
|
+
const router = express.Router('testmode');
|
|
9
9
|
|
|
10
10
|
router.get('/500', (req, res) => res.sendStatus(500));
|
|
11
11
|
router.get('/400', (req, res) => res.sendStatus(400));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./routes');
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const express = require('../../../shared/express');
|
|
2
|
+
const api = require('../../api').endpoints;
|
|
3
|
+
const http = require('../../api').shared.http;
|
|
4
|
+
|
|
5
|
+
const bodyParser = require('body-parser');
|
|
6
|
+
const membersService = require('../../../server/services/members');
|
|
7
|
+
|
|
8
|
+
module.exports = function apiRoutes() {
|
|
9
|
+
const router = express.Router('comment api');
|
|
10
|
+
|
|
11
|
+
router.use(bodyParser.json({limit: '50mb'}));
|
|
12
|
+
|
|
13
|
+
// Global handling for member session, ensures a member is logged in to the frontend
|
|
14
|
+
router.use(membersService.middleware.loadMemberSession);
|
|
15
|
+
|
|
16
|
+
router.post('/counts', http(api.commentsComments.counts));
|
|
17
|
+
|
|
18
|
+
router.get('/', http(api.commentsComments.browse));
|
|
19
|
+
router.get('/:id', http(api.commentsComments.read));
|
|
20
|
+
router.post('/', http(api.commentsComments.add));
|
|
21
|
+
router.put('/:id', http(api.commentsComments.edit));
|
|
22
|
+
router.delete('/:id', http(api.commentsComments.destroy));
|
|
23
|
+
|
|
24
|
+
router.post('/:id/like', http(api.commentsComments.like));
|
|
25
|
+
router.delete('/:id/like', http(api.commentsComments.unlike));
|
|
26
|
+
|
|
27
|
+
return router;
|
|
28
|
+
};
|
|
@@ -12,6 +12,8 @@ const shared = require('../shared');
|
|
|
12
12
|
const labs = require('../../../shared/labs');
|
|
13
13
|
const errorHandler = require('@tryghost/mw-error-handler');
|
|
14
14
|
|
|
15
|
+
const commentRouter = require('../comments');
|
|
16
|
+
|
|
15
17
|
module.exports = function setupMembersApp() {
|
|
16
18
|
debug('Members App setup start');
|
|
17
19
|
const membersApp = express('members');
|
|
@@ -54,6 +56,9 @@ module.exports = function setupMembersApp() {
|
|
|
54
56
|
membersApp.put('/api/subscriptions/:id', (req, res, next) => membersService.api.middleware.updateSubscription(req, res, next));
|
|
55
57
|
membersApp.post('/api/events', labs.enabledMiddleware('membersActivity'), middleware.loadMemberSession, (req, res, next) => membersService.api.middleware.createEvents(req, res, next));
|
|
56
58
|
|
|
59
|
+
// Comments
|
|
60
|
+
membersApp.use('/api/comments', commentRouter());
|
|
61
|
+
|
|
57
62
|
// API error handling
|
|
58
63
|
membersApp.use('/api', errorHandler.resourceNotFound);
|
|
59
64
|
membersApp.use('/api', errorHandler.handleJSONResponse(sentry));
|
|
@@ -18,6 +18,7 @@ module.exports = (routerConfig) => {
|
|
|
18
18
|
frontendApp.use(shared.middleware.urlRedirects.frontendSSLRedirect);
|
|
19
19
|
|
|
20
20
|
frontendApp.lazyUse('/members', require('../members'));
|
|
21
|
+
frontendApp.lazyUse('/comments', require('../comments'));
|
|
21
22
|
frontendApp.use('/', require('../../../frontend/web')(routerConfig));
|
|
22
23
|
|
|
23
24
|
return frontendApp;
|