ghost 5.130.2 → 6.0.0-alpha.2
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/components/tryghost-i18n-6.0.0-alpha.2.tgz +0 -0
- package/core/boot.js +0 -2
- package/core/built/admin/assets/admin-x-activitypub/admin-x-activitypub.js +1 -1
- package/core/built/admin/assets/admin-x-activitypub/{index-B8te98RZ.mjs → index-BZDwG-OG.mjs} +7397 -7385
- package/core/built/admin/assets/admin-x-activitypub/{index-C8qwgKWF.mjs → index-DTlSQCGz.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{CodeEditorView-CAtv7MlN.mjs → CodeEditorView-CCUvrZhe.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-BVxh86CD.mjs → index-Cubs_8W6.mjs} +8088 -8532
- package/core/built/admin/assets/admin-x-settings/{index-DUhmXSBR.mjs → index-D0ejKdD5.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{modals-B5dtfzsB.mjs → modals-DSxs9dLy.mjs} +1676 -1614
- package/core/built/admin/assets/{chunk.524.1f2faf572078e5b86b09.js → chunk.524.0953dd72ae1efbabe0de.js} +7 -7
- package/core/built/admin/assets/{chunk.582.675905fe8f9be138fb19.js → chunk.582.3caa825c2a91efc48f1d.js} +8 -8
- package/core/built/admin/assets/{ghost-280b83af263b51bc4d6ce5bd8f536096.js → ghost-db0f84981913aec8a672c57aa22da07a.js} +40 -45
- package/core/built/admin/assets/posts/posts.js +6549 -6537
- package/core/built/admin/assets/stats/stats.js +8824 -8812
- package/core/built/admin/index.html +3 -3
- package/core/frontend/helpers/get.js +4 -2
- package/core/frontend/helpers/ghost_head.js +71 -77
- package/core/frontend/meta/canonical-url.js +1 -7
- package/core/frontend/meta/context-object.js +1 -1
- package/core/frontend/meta/get-meta.js +1 -4
- package/core/frontend/meta/og-image.js +1 -1
- package/core/frontend/meta/og-type.js +0 -2
- package/core/frontend/meta/schema.js +1 -1
- package/core/frontend/meta/twitter-image.js +1 -1
- package/core/frontend/meta/url.js +1 -12
- package/core/frontend/services/rendering/context.js +0 -8
- package/core/frontend/web/middleware/static-theme.js +20 -1
- package/core/server/api/endpoints/index.js +0 -4
- package/core/server/api/endpoints/session.js +0 -9
- package/core/server/api/endpoints/utils/serializers/input/settings.js +0 -2
- package/core/server/api/endpoints/utils/serializers/input/utils/settings-filter-type-group-mapper.js +0 -1
- package/core/server/api/endpoints/utils/serializers/input/utils/settings-key-group-mapper.js +0 -1
- package/core/server/api/endpoints/utils/serializers/input/utils/settings-key-type-mapper.js +0 -1
- package/core/server/api/endpoints/utils/serializers/output/all.js +1 -1
- package/core/server/api/endpoints/utils/serializers/output/index.js +0 -4
- package/core/server/api/endpoints/utils/serializers/output/mappers/snippets.js +1 -5
- package/core/server/api/endpoints/utils/serializers/output/members.js +0 -2
- package/core/server/api/endpoints/utils/validators/input/index.js +0 -4
- package/core/server/data/importer/importers/data/Base.js +1 -3
- package/core/server/data/importer/importers/data/SettingsImporter.js +1 -3
- package/core/server/data/migrations/utils/index.js +1 -4
- package/core/server/data/migrations/utils/permissions.js +14 -6
- package/core/server/data/migrations/utils/settings.js +39 -22
- package/core/server/data/migrations/versions/4.47/2022-05-03-15-30-final-v4.js +2 -0
- package/core/server/data/migrations/versions/4.47/2022-05-04-10-03-no-op.js +6 -0
- package/core/server/data/migrations/versions/5.100/2024-11-06-04-45-15-add-activitypub-integration.js +4 -2
- package/core/server/data/migrations/versions/5.113/2025-03-07-12-24-00-add-super-editor.js +4 -2
- package/core/server/data/migrations/versions/5.3/2022-07-06-07-58-add-ghost-explore-integration-role.js +4 -2
- package/core/server/data/migrations/versions/5.3/2022-07-06-09-17-add-ghost-explore-integration.js +4 -2
- package/core/server/data/migrations/versions/5.3/2022-07-06-09-26-add-ghost-explore-integration-api-key.js +4 -2
- package/core/server/data/migrations/versions/5.40/2023-03-21-18-42-add-self-serve-integration-role.js +4 -2
- package/core/server/data/migrations/versions/5.40/2023-03-21-18-52-add-self-serve-integration.js +4 -2
- package/core/server/data/migrations/versions/5.40/2023-03-21-19-02-add-self-serve-integration-api-key.js +4 -2
- package/core/server/data/migrations/versions/5.63/2023-09-13-13-03-10-add-ghost-core-content-integration.js +4 -2
- package/core/server/data/migrations/versions/5.63/2023-09-13-13-34-11-add-ghost-core-content-integration-key.js +4 -2
- package/core/server/data/migrations/versions/6.0/2025-06-20-01-41-54-remove-updated-by-column.js +46 -0
- package/core/server/data/migrations/versions/6.0/2025-06-20-13-41-55-remove-created-by-column.js +47 -0
- package/core/server/data/migrations/versions/6.0/2025-06-23-09-49-25-add-missing-member-uuids.js +22 -0
- package/core/server/data/migrations/versions/6.0/2025-06-23-10-03-26-members-nullable-uuid.js +5 -0
- package/core/server/data/migrations/versions/6.0/2025-06-24-09-19-42-use-object-id-for-hardcoded-user-id.js +95 -0
- package/core/server/data/migrations/versions/6.0/2025-06-25-15-03-29-remove-amp-from-settings.js +6 -0
- package/core/server/data/migrations/versions/6.0/2025-06-30-13-59-10-remove-mail-events-table.js +3 -0
- package/core/server/data/migrations/versions/6.0/2025-06-30-14-00-00-update-feature-image-alt-length.js +25 -0
- package/core/server/data/schema/default-settings/default-settings.json +0 -13
- package/core/server/data/schema/fixtures/FixtureManager.js +128 -5
- package/core/server/data/schema/fixtures/fixtures.json +4 -6
- package/core/server/data/schema/fixtures/index.js +3 -1
- package/core/server/data/schema/schema.js +20 -65
- package/core/server/data/seeders/DataGenerator.js +11 -2
- package/core/server/data/seeders/importers/EmailsImporter.js +1 -3
- package/core/server/data/seeders/importers/LabelsImporter.js +1 -3
- package/core/server/data/seeders/importers/MembersImporter.js +0 -1
- package/core/server/data/seeders/importers/MembersStripeCustomersImporter.js +1 -2
- package/core/server/data/seeders/importers/MembersStripeCustomersSubscriptionsImporter.js +0 -1
- package/core/server/data/seeders/importers/PostsImporter.js +0 -1
- package/core/server/data/seeders/importers/RolesUsersImporter.js +6 -1
- package/core/server/data/seeders/importers/TagsImporter.js +1 -2
- package/core/server/data/seeders/importers/UsersImporter.js +1 -2
- package/core/server/data/tinybird/ARCHITECTURE.md +0 -4
- package/core/server/data/tinybird/DOCS.md +0 -4
- package/core/server/models/base/bookshelf.js +8 -1
- package/core/server/models/base/plugins/events.js +0 -28
- package/core/server/models/base/plugins/user-type.js +10 -36
- package/core/server/models/post.js +25 -10
- package/core/server/models/relations/authors.js +2 -2
- package/core/server/models/settings.js +1 -14
- package/core/server/models/user.js +33 -6
- package/core/server/services/activitypub/ActivityPubService.js +1 -2
- package/core/server/services/activitypub/ActivityPubService.ts +1 -2
- package/core/server/services/explore-ping/ExplorePingService.js +3 -1
- package/core/server/services/link-redirection/README.md +1 -1
- package/core/server/services/mentions/MentionSendingService.js +1 -1
- package/core/server/services/settings/SettingsBREADService.js +5 -1
- package/core/server/services/settings/settings-service.js +3 -1
- package/core/server/services/settings-helpers/SettingsHelpers.js +0 -12
- package/core/server/services/update-check/UpdateCheckService.js +18 -2
- package/core/server/services/url/config.js +0 -2
- package/core/server/web/api/app.js +4 -0
- package/core/server/web/api/endpoints/admin/middleware.js +8 -9
- package/core/server/web/api/endpoints/admin/routes.js +0 -2
- package/core/server/web/comments/routes.js +3 -0
- package/core/server/web/shared/middleware/index.js +4 -0
- package/core/server/web/shared/middleware/max-limit-cap.js +27 -0
- package/core/server/web/shared/middleware/pretty-urls.js +3 -1
- package/core/server/web/shared/middleware/redirect-amp-urls.js +36 -0
- package/core/shared/config/defaults.json +2 -0
- package/core/shared/config/overrides.json +1 -4
- package/core/shared/labs.js +2 -6
- package/core/shared/max-limit-cap.js +61 -0
- package/package.json +5 -6
- package/tsconfig.tsbuildinfo +1 -1
- package/yarn.lock +18 -107
- package/components/tryghost-i18n-5.130.2.tgz +0 -0
- package/core/built/admin/assets/img/amp-d7b72aae3315fda95921fb575dfca100.svg +0 -4
- package/core/frontend/apps/amp/index.js +0 -30
- package/core/frontend/apps/amp/lib/helpers/amp_analytics.js +0 -32
- package/core/frontend/apps/amp/lib/helpers/amp_components.js +0 -48
- package/core/frontend/apps/amp/lib/helpers/amp_content.js +0 -214
- package/core/frontend/apps/amp/lib/helpers/amp_style.js +0 -8
- package/core/frontend/apps/amp/lib/router.js +0 -95
- package/core/frontend/apps/amp/lib/views/amp.hbs +0 -1046
- package/core/frontend/meta/amp-url.js +0 -14
- package/core/server/api/endpoints/mail-events.js +0 -17
- package/core/server/api/endpoints/utils/serializers/output/mail-events.js +0 -9
- package/core/server/api/endpoints/utils/validators/input/mail-events.js +0 -7
- package/core/server/data/migrations/utils/constants.js +0 -3
- package/core/server/data/migrations/versions/4.0/01-update-mobiledoc.js +0 -61
- package/core/server/data/migrations/versions/4.0/02-add-status-column-to-members.js +0 -11
- package/core/server/data/migrations/versions/4.0/03-populate-status-column-for-members.js +0 -81
- package/core/server/data/migrations/versions/4.0/04-drop-apps-related-tables.js +0 -10
- package/core/server/data/migrations/versions/4.0/05-add-members-subscribe-events-table.js +0 -9
- package/core/server/data/migrations/versions/4.0/06-populate-members-subscribe-events-table.js +0 -53
- package/core/server/data/migrations/versions/4.0/07-alter-unique-constraint-for-posts-slug.js +0 -7
- package/core/server/data/migrations/versions/4.0/08-add-members-login-events-table.js +0 -7
- package/core/server/data/migrations/versions/4.0/09-add-members-email-change-events-table.js +0 -9
- package/core/server/data/migrations/versions/4.0/10-add-members-status-events-table.js +0 -9
- package/core/server/data/migrations/versions/4.0/11-add-members-paid-subscription-events-table.js +0 -12
- package/core/server/data/migrations/versions/4.0/12-delete-apps-related-settings-keys.js +0 -16
- package/core/server/data/migrations/versions/4.0/13-add-members-payment-events-table.js +0 -10
- package/core/server/data/migrations/versions/4.0/14-remove-orphaned-stripe-records.js +0 -36
- package/core/server/data/migrations/versions/4.0/15-add-frontmatter-column-to-meta.js +0 -7
- package/core/server/data/migrations/versions/4.0/16-refactor-slack-setting.js +0 -96
- package/core/server/data/migrations/versions/4.0/17-populate-members-status-events-table.js +0 -41
- package/core/server/data/migrations/versions/4.0/18-transform-urls-absolute-to-transform-ready.js +0 -201
- package/core/server/data/migrations/versions/4.0/19-remove-labs-members-setting.js +0 -10
- package/core/server/data/migrations/versions/4.0/20-refactor-unsplash-setting.js +0 -41
- package/core/server/data/migrations/versions/4.0/21-sanitize-email-batches-provider-id.js +0 -8
- package/core/server/data/migrations/versions/4.0/22-solve-orphaned-webhooks.js +0 -87
- package/core/server/data/migrations/versions/4.0/23-regenerate-posts-html.js +0 -66
- package/core/server/data/migrations/versions/4.0/24-add-missing-email-permissions.js +0 -36
- package/core/server/data/migrations/versions/4.0/25-populate-members-paid-subscription-events-table.js +0 -129
- package/core/server/data/migrations/versions/4.0/26-add-cascade-on-delete.js +0 -76
- package/core/server/data/migrations/versions/4.0/27-add-primary-key-brute-migrations-lock.js +0 -9
- package/core/server/data/migrations/versions/4.0/28-add-webhook-intergrations-foreign-key.js +0 -16
- package/core/server/data/migrations/versions/4.0/29-fix-foreign-key-for-members-stripe-customers-subscriptions.js +0 -35
- package/core/server/data/migrations/versions/4.0/30-set-default-accent-color.js +0 -21
- package/core/server/data/migrations/versions/4.1/01-fix-backup-content-permission-typo.js +0 -15
- package/core/server/data/migrations/versions/4.1/02-add-unique-constraint-for-member-stripe-tables.js +0 -21
- package/core/server/data/migrations/versions/4.11/01-add-oauth-user-data.js +0 -12
- package/core/server/data/migrations/versions/4.11/02-add-email-verification-required-setting.js +0 -43
- package/core/server/data/migrations/versions/4.12/01-add-email-only-column-to-posts-meta-table.js +0 -7
- package/core/server/data/migrations/versions/4.12/02-fix-member-statuses.js +0 -39
- package/core/server/data/migrations/versions/4.13/01-add-members-stripe-connect-auth-permission-to-administrators.js +0 -6
- package/core/server/data/migrations/versions/4.13/02-add-members-products-events-table.js +0 -33
- package/core/server/data/migrations/versions/4.14/01-fix-comped-member-statuses.js +0 -73
- package/core/server/data/migrations/versions/4.14/02-fix-free-members-status-events.js +0 -61
- package/core/server/data/migrations/versions/4.15/01-add-temp-members-analytic-events-table.js +0 -12
- package/core/server/data/migrations/versions/4.16/01-add-custom-theme-settings-table.js +0 -9
- package/core/server/data/migrations/versions/4.17/01-add-custom-theme-settings-permissions.js +0 -21
- package/core/server/data/migrations/versions/4.17/02-add-offers-table.js +0 -19
- package/core/server/data/migrations/versions/4.17/03-add-offers-permissions.js +0 -35
- package/core/server/data/migrations/versions/4.19/01-add-active-column-to-offers.js +0 -7
- package/core/server/data/migrations/versions/4.19/02-add-offer-redemptions-table.js +0 -8
- package/core/server/data/migrations/versions/4.2/01-fix-incorrect-mrr-delta-events.js +0 -13
- package/core/server/data/migrations/versions/4.20/01-remove-offer-redemptions-table.js +0 -19
- package/core/server/data/migrations/versions/4.20/02-remove-offers-table.js +0 -30
- package/core/server/data/migrations/versions/4.20/03-add-offers-table.js +0 -21
- package/core/server/data/migrations/versions/4.20/04-add-offer-redemptions-table.js +0 -9
- package/core/server/data/migrations/versions/4.20/05-remove-not-null-constraint-from-portal-title.js +0 -44
- package/core/server/data/migrations/versions/4.22/01-add-is-launch-complete-setting.js +0 -8
- package/core/server/data/migrations/versions/4.22/02-update-launch-complete-setting-from-user-data.js +0 -39
- package/core/server/data/migrations/versions/4.23/01-truncate-offer-names.js +0 -59
- package/core/server/data/migrations/versions/4.3/01-add-products-table.js +0 -9
- package/core/server/data/migrations/versions/4.3/02-add-members-products-table.js +0 -8
- package/core/server/data/migrations/versions/4.3/03-add-default-product.js +0 -39
- package/core/server/data/migrations/versions/4.3/04-attach-members-to-product.js +0 -50
- package/core/server/data/migrations/versions/4.3/05-add-stripe-products-table.js +0 -9
- package/core/server/data/migrations/versions/4.3/06-add-stripe-prices-table.js +0 -15
- package/core/server/data/migrations/versions/4.3/07-add-products-permissions.js +0 -29
- package/core/server/data/migrations/versions/4.3/08-migrate-members-signup-setting.js +0 -109
- package/core/server/data/migrations/versions/4.3/09-add-price-id-column-to-subscriptions-table.js +0 -10
- package/core/server/data/migrations/versions/4.3/10-populate-stripe-price-id-in-subscriptions.js +0 -20
- package/core/server/data/migrations/versions/4.33/2022-01-14-11-50-add-type-column-to-products.js +0 -12
- package/core/server/data/migrations/versions/4.33/2022-01-14-11-51-add-default-free-tier.js +0 -40
- package/core/server/data/migrations/versions/4.33/2022-01-18-09-07-remove-duplicate-offer-redemptions.js +0 -46
- package/core/server/data/migrations/versions/4.33/2022-01-19-10-43-add-active-column-to-products-table.js +0 -7
- package/core/server/data/migrations/versions/4.34/2022-01-25-13-53-add-welcome-page-url-column-to-products.js +0 -7
- package/core/server/data/migrations/versions/4.35/2022-01-20-05-55-add-post-products-table.js +0 -8
- package/core/server/data/migrations/versions/4.35/2022-01-30-15-17-set-welcome-page-url-from-settings.js +0 -45
- package/core/server/data/migrations/versions/4.35/2022-02-01-11-48-update-email-recipient-filter-column-type.js +0 -19
- package/core/server/data/migrations/versions/4.35/2022-02-01-12-03-update-recipient-filter-column-type.js +0 -19
- package/core/server/data/migrations/versions/4.35/2022-02-02-10-38-add-default-content-visibility-tiers-setting.js +0 -8
- package/core/server/data/migrations/versions/4.35/2022-02-02-13-10-transform-specific-tiers-default-content-visibility.js +0 -147
- package/core/server/data/migrations/versions/4.35/2022-02-04-04-34-populate-empty-portal-products.js +0 -60
- package/core/server/data/migrations/versions/4.36/2022-02-07-14-34-add-last-seen-at-column-to-members.js +0 -10
- package/core/server/data/migrations/versions/4.37/2022-02-21-09-53-backfill-members-last-seen-at-column.js +0 -32
- package/core/server/data/migrations/versions/4.38/2022-03-01-08-46-add-visibility-to-tiers.js +0 -11
- package/core/server/data/migrations/versions/4.38/2022-03-03-16-12-add-visibility-to-tiers.js +0 -8
- package/core/server/data/migrations/versions/4.38/2022-03-03-16-17-drop-tiers-visible-column.js +0 -7
- package/core/server/data/migrations/versions/4.39/2022-03-07-10-57-update-free-products-visibility-column.js +0 -66
- package/core/server/data/migrations/versions/4.39/2022-03-07-10-57-update-products-visibility-column.js +0 -36
- package/core/server/data/migrations/versions/4.4/01-restore-free-members-signup-setting-from-backup.js +0 -99
- package/core/server/data/migrations/versions/4.4/02-migrate-members-signup-access.js +0 -126
- package/core/server/data/migrations/versions/4.40/2022-03-07-14-37-add-members-cancel-events-table.js +0 -8
- package/core/server/data/migrations/versions/4.40/2022-03-15-06-40-add-offers-admin-integration-permission-roles.js +0 -23
- package/core/server/data/migrations/versions/4.40/2022-03-15-06-40-add-tiers-admin-integration-permission-roles.js +0 -20
- package/core/server/data/migrations/versions/4.42/2022-03-21-17-17-add.js +0 -25
- package/core/server/data/migrations/versions/4.42/2022-03-30-15-44-add-newsletter-permissions.js +0 -28
- package/core/server/data/migrations/versions/4.43/2022-03-28-19-26-recreate-newsletter-table.js +0 -29
- package/core/server/data/migrations/versions/4.43/2022-03-29-14-45-add-members-newsletters-table.js +0 -7
- package/core/server/data/migrations/versions/4.43/2022-04-01-10-13-add-post-newsletter-relation.js +0 -108
- package/core/server/data/migrations/versions/4.43/2022-04-06-09-47-add-type-column-to-paid-subscription-events.js +0 -7
- package/core/server/data/migrations/versions/4.43/2022-04-06-14-56-add-email-newsletter-relation.js +0 -8
- package/core/server/data/migrations/versions/4.43/2022-04-08-10-45-add-subscription-id-to-mrr-events.js +0 -7
- package/core/server/data/migrations/versions/4.44/2022-04-06-15-22-populate-type-column-for-paid-subscription-events.js +0 -21
- package/core/server/data/migrations/versions/4.44/2022-04-08-11-54-add-cancelled-events.js +0 -51
- package/core/server/data/migrations/versions/4.44/2022-04-11-08-24-add-newsletter-permissions.js +0 -33
- package/core/server/data/migrations/versions/4.44/2022-04-11-10-54-add-mrr-to-subscriptions.js +0 -8
- package/core/server/data/migrations/versions/4.44/2022-04-12-07-33-fill-mrr.js +0 -29
- package/core/server/data/migrations/versions/4.44/2022-04-13-12-00-remove-newsletter-sender-name-not-null-constraint.js +0 -33
- package/core/server/data/migrations/versions/4.44/2022-04-15-07-53-add-offer-id-to-subscriptions.js +0 -9
- package/core/server/data/migrations/versions/4.45/2022-04-19-12-23-backfill-subscriptions-offers.js +0 -60
- package/core/server/data/migrations/versions/4.45/2022-04-20-11-25-add-newsletter-read-permission.js +0 -9
- package/core/server/data/migrations/versions/4.45/2022-04-21-02-55-add-notifications-key-entry-to-settings-table.js +0 -8
- package/core/server/data/migrations/versions/4.46/2022-04-13-12-00-add-created-at-newsletters.js +0 -6
- package/core/server/data/migrations/versions/4.46/2022-04-13-12-01-add-updated-at-newsletters.js +0 -6
- package/core/server/data/migrations/versions/4.46/2022-04-13-12-02-fill-created-at-newsletters.js +0 -19
- package/core/server/data/migrations/versions/4.46/2022-04-13-12-03-drop-nullable-created-at-newsletters.js +0 -3
- package/core/server/data/migrations/versions/4.46/2022-04-13-12-08-newsletters-show-header-name.js +0 -7
- package/core/server/data/migrations/versions/4.46/2022-04-13-12-57-add-uuid-column-to-newsletters.js +0 -8
- package/core/server/data/migrations/versions/4.46/2022-04-13-12-58-fill-uuid-for-newsletters.js +0 -19
- package/core/server/data/migrations/versions/4.46/2022-04-13-12-59-drop-nullable-uuid-newsletters.js +0 -3
- package/core/server/data/migrations/versions/4.46/2022-04-13-13-00-add-default-newsletter.js +0 -92
- package/core/server/data/migrations/versions/4.46/2022-04-20-08-39-map-subscribers-to-default-newsletter.js +0 -66
- package/core/server/data/migrations/versions/4.46/2022-04-22-07-43-add-newsletter-id-to-subscribe-events.js +0 -9
- package/core/server/data/migrations/versions/4.46/2022-04-27-07-59-set-newsletter-id-subscribe-events.js +0 -31
- package/core/server/data/migrations/versions/4.47/2022-05-03-15-30-update-newsletter-sending-options.js +0 -34
- package/core/server/data/migrations/versions/4.47/2022-05-04-10-03-transform-newsletter-header-image.js +0 -26
- package/core/server/data/migrations/versions/4.5/01-add-stripe-price-description-column.js +0 -7
- package/core/server/data/migrations/versions/4.5/02-add-product-description-column.js +0 -7
- package/core/server/data/migrations/versions/4.5/03-give-label-read-permissions-to-editors.js +0 -14
- package/core/server/data/migrations/versions/4.5/04-remove-unique-constraint-from-product-name.js +0 -13
- package/core/server/data/migrations/versions/4.5/05-rename-default-product-to-site-title.js +0 -38
- package/core/server/data/migrations/versions/4.6/01-remove-comped-status.js +0 -47
- package/core/server/data/migrations/versions/4.7/01-add-monthly-price-column-to-products.js +0 -7
- package/core/server/data/migrations/versions/4.7/02-add-yearly-price-column-to-products.js +0 -7
- package/core/server/data/migrations/versions/4.7/03-add-labs-setting.js +0 -42
- package/core/server/data/migrations/versions/4.8/01-add-feature-image-alt-column-to-posts-meta.js +0 -7
- package/core/server/data/migrations/versions/4.8/02-add-feature-image-caption-column-to-posts-meta.js +0 -7
- package/core/server/data/migrations/versions/4.8/03-add-default-product-portal-products.js +0 -69
- package/core/server/data/migrations/versions/4.8/04-migrate-show-newsletter-header-setting.js +0 -124
- package/core/server/data/migrations/versions/4.9/01-add-reset-all-passwords-permission.js +0 -11
- package/core/server/data/migrations/versions/4.9/02-add-benefits-table.js +0 -9
- package/core/server/data/migrations/versions/4.9/03-add-products-benefits-table.js +0 -8
- package/core/server/data/migrations/versions/4.9/04-add-member-segment-to-email-batches.js +0 -7
- package/core/server/data/migrations/versions/4.9/05-fix-missed-mobiledoc-url-transforms.js +0 -87
- package/core/server/data/migrations/versions/4.9/06-add-comped-status.js +0 -47
- package/core/server/data/migrations/versions/4.9/07-update-comped-members-status-events.js +0 -39
- package/core/server/models/mail-event.js +0 -12
- package/core/server/services/mail-events/BookshelfMailEventRepository.js +0 -40
- package/core/server/services/mail-events/InMemoryMailEventRepository.js +0 -10
- package/core/server/services/mail-events/InMemoryMailEventRepository.ts +0 -8
- package/core/server/services/mail-events/MailEvent.js +0 -20
- package/core/server/services/mail-events/MailEvent.ts +0 -10
- package/core/server/services/mail-events/MailEventRepository.js +0 -2
- package/core/server/services/mail-events/MailEventRepository.ts +0 -5
- package/core/server/services/mail-events/MailEventService.js +0 -124
- package/core/server/services/mail-events/MailEventService.ts +0 -169
- package/core/server/services/mail-events/index.js +0 -21
- package/core/server/services/mail-events/libraries.d.ts +0 -2
|
@@ -138,26 +138,12 @@ module.exports = function (Bookshelf) {
|
|
|
138
138
|
|
|
139
139
|
/**
|
|
140
140
|
* Adding resources implies setting these properties on the server side
|
|
141
|
-
* - set `created_by` based on the context
|
|
142
|
-
* - set `updated_by` based on the context
|
|
143
141
|
* - the bookshelf `timestamps` plugin sets `created_at` and `updated_at`
|
|
144
142
|
* - if plugin is disabled (e.g. import) we have a fallback condition
|
|
145
143
|
*
|
|
146
144
|
* Exceptions: internal context or importing
|
|
147
145
|
*/
|
|
148
146
|
onCreating: function onCreating(model, attr, options) {
|
|
149
|
-
if (Object.prototype.hasOwnProperty.call(schema.tables[this.tableName], 'created_by')) {
|
|
150
|
-
if (!options.importing || (options.importing && !this.get('created_by'))) {
|
|
151
|
-
this.set('created_by', String(this.contextUser(options)));
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (Object.prototype.hasOwnProperty.call(schema.tables[this.tableName], 'updated_by')) {
|
|
156
|
-
if (!options.importing) {
|
|
157
|
-
this.set('updated_by', String(this.contextUser(options)));
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
147
|
if (Object.prototype.hasOwnProperty.call(schema.tables[this.tableName], 'created_at')) {
|
|
162
148
|
if (!model.get('created_at')) {
|
|
163
149
|
model.set('created_at', new Date());
|
|
@@ -199,9 +185,7 @@ module.exports = function (Bookshelf) {
|
|
|
199
185
|
|
|
200
186
|
/**
|
|
201
187
|
* Changing resources implies setting these properties on the server side
|
|
202
|
-
* - set `updated_by` based on the context
|
|
203
188
|
* - ensure `created_at` never changes
|
|
204
|
-
* - ensure `created_by` never changes
|
|
205
189
|
* - the bookshelf `timestamps` plugin sets `updated_at` automatically
|
|
206
190
|
*
|
|
207
191
|
* Exceptions:
|
|
@@ -216,24 +200,12 @@ module.exports = function (Bookshelf) {
|
|
|
216
200
|
model.changed = _.omit(model.changed, this.relationships);
|
|
217
201
|
}
|
|
218
202
|
|
|
219
|
-
if (Object.prototype.hasOwnProperty.call(schema.tables[this.tableName], 'updated_by')) {
|
|
220
|
-
if (!options.importing && !options.migrating) {
|
|
221
|
-
this.set('updated_by', String(this.contextUser(options)));
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
203
|
if (options && options.context && !options.context.internal && !options.importing) {
|
|
226
204
|
if (Object.prototype.hasOwnProperty.call(schema.tables[this.tableName], 'created_at')) {
|
|
227
205
|
if (model.hasDateChanged('created_at', {beforeWrite: true})) {
|
|
228
206
|
model.set('created_at', this.previous('created_at'));
|
|
229
207
|
}
|
|
230
208
|
}
|
|
231
|
-
|
|
232
|
-
if (Object.prototype.hasOwnProperty.call(schema.tables[this.tableName], 'created_by')) {
|
|
233
|
-
if (model.hasChanged('created_by')) {
|
|
234
|
-
model.set('created_by', String(this.previous('created_by')));
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
209
|
}
|
|
238
210
|
|
|
239
211
|
// CASE: do not allow setting only the `updated_at` field, exception: importing
|
|
@@ -8,7 +8,7 @@ const messages = {
|
|
|
8
8
|
/**
|
|
9
9
|
* @param {import('bookshelf')} Bookshelf
|
|
10
10
|
*/
|
|
11
|
-
module.exports = function (Bookshelf) {
|
|
11
|
+
module.exports = function (Bookshelf, pluginOptions) {
|
|
12
12
|
Bookshelf.Model = Bookshelf.Model.extend({
|
|
13
13
|
getActor(options = {context: {}}) {
|
|
14
14
|
if (options.context && options.context.integration) {
|
|
@@ -29,37 +29,22 @@ module.exports = function (Bookshelf) {
|
|
|
29
29
|
},
|
|
30
30
|
|
|
31
31
|
// Get the user from the options object
|
|
32
|
-
contextUser: function contextUser(options) {
|
|
32
|
+
contextUser: async function contextUser(options) {
|
|
33
33
|
options = options || {};
|
|
34
34
|
options.context = options.context || {};
|
|
35
35
|
|
|
36
36
|
if (options.context.user) {
|
|
37
37
|
return options.context.user;
|
|
38
38
|
} else if (options.context.integration) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
* @deprecated x_by columns are deprecated as of v1.0 - instead we should use the actions table
|
|
44
|
-
* see https://github.com/TryGhost/Ghost/issues/10286.
|
|
45
|
-
*
|
|
46
|
-
* We return the owner ID '1' in case an integration updates or creates resources.
|
|
47
|
-
*
|
|
48
|
-
* ---
|
|
49
|
-
*
|
|
50
|
-
* Why using ID '1'? WAIT. What???????
|
|
51
|
-
*
|
|
52
|
-
* See https://github.com/TryGhost/Ghost/issues/9299.
|
|
53
|
-
*
|
|
54
|
-
* We currently don't read the correct owner ID from the database and assume it's '1'.
|
|
55
|
-
* This is a leftover from switching from auto increment ID's to Object ID's.
|
|
56
|
-
* But this takes too long to refactor out now. If an internal update happens, we also
|
|
57
|
-
* use ID '1'. This logic exists for a LONG while now. The owner ID only changes from '1' to something else,
|
|
58
|
-
* if you transfer ownership.
|
|
59
|
-
*/
|
|
60
|
-
return Bookshelf.Model.internalUser;
|
|
39
|
+
return pluginOptions.resolveIntegrationUserId({
|
|
40
|
+
transacting: options.transacting,
|
|
41
|
+
context: options.context
|
|
42
|
+
});
|
|
61
43
|
} else if (options.context.internal) {
|
|
62
|
-
return
|
|
44
|
+
return pluginOptions.resolveInternalUserId({
|
|
45
|
+
transacting: options.transacting,
|
|
46
|
+
context: options.context
|
|
47
|
+
});
|
|
63
48
|
} else if (this.get('id')) {
|
|
64
49
|
return this.get('id');
|
|
65
50
|
} else {
|
|
@@ -69,16 +54,5 @@ module.exports = function (Bookshelf) {
|
|
|
69
54
|
});
|
|
70
55
|
}
|
|
71
56
|
}
|
|
72
|
-
}, {
|
|
73
|
-
/**
|
|
74
|
-
* please use these static definitions when comparing id's
|
|
75
|
-
* we keep type Number, because we have too many check's where we rely on Number
|
|
76
|
-
* context.user ? true : false (if context.user is 0 as number, this condition is false)
|
|
77
|
-
*/
|
|
78
|
-
internalUser: 1,
|
|
79
|
-
|
|
80
|
-
isInternalUser: function isInternalUser(id) {
|
|
81
|
-
return id === Bookshelf.Model.internalUser || id === Bookshelf.Model.internalUser.toString();
|
|
82
|
-
}
|
|
83
57
|
});
|
|
84
58
|
};
|
|
@@ -601,6 +601,28 @@ Post = ghostBookshelf.Model.extend({
|
|
|
601
601
|
}
|
|
602
602
|
}
|
|
603
603
|
|
|
604
|
+
// CASE: Force a change for scheduled posts within 2 minutes of
|
|
605
|
+
// publishing. This ensures the scheduler can detect last-minute
|
|
606
|
+
// touches to the post
|
|
607
|
+
const isScheduled = newStatus === 'scheduled';
|
|
608
|
+
const isUpdate = options.method === 'update';
|
|
609
|
+
const isWithin2Minutes = publishedAt && moment(publishedAt).diff(moment(), 'minutes') <= 2;
|
|
610
|
+
const isNotImporting = !options.importing;
|
|
611
|
+
const isNotMigrating = !options.migrating;
|
|
612
|
+
|
|
613
|
+
if (isScheduled && isUpdate && isWithin2Minutes && isNotImporting && isNotMigrating) {
|
|
614
|
+
// Check if no actual changes have been made
|
|
615
|
+
if (!this.changed || Object.keys(this.changed).length === 0) {
|
|
616
|
+
// Force a "touch" by setting a dummy property that will be stored in _changed
|
|
617
|
+
this.set('_touch', true);
|
|
618
|
+
// Immediately unset it so it doesn't get saved to the database
|
|
619
|
+
this.unset('_touch');
|
|
620
|
+
// But ensure the changed object still has it for event detection
|
|
621
|
+
this.changed = this.changed || {};
|
|
622
|
+
this.changed._touch = true;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
604
626
|
// CASE: detect lowercase/uppercase tag slugs
|
|
605
627
|
if (!_.isUndefined(this.get('tags')) && !_.isNull(this.get('tags'))) {
|
|
606
628
|
tagsToSave = [];
|
|
@@ -744,7 +766,8 @@ Post = ghostBookshelf.Model.extend({
|
|
|
744
766
|
if ((newStatus === 'published' || newStatus === 'sent') && this.hasChanged('status')) {
|
|
745
767
|
// unless published_by is set and we're importing, set published_by to contextUser
|
|
746
768
|
if (!(this.get('published_by') && options.importing)) {
|
|
747
|
-
|
|
769
|
+
const userId = await this.contextUser(options);
|
|
770
|
+
this.set('published_by', String(userId));
|
|
748
771
|
}
|
|
749
772
|
} else {
|
|
750
773
|
// In any other case (except import), `published_by` should not be changed
|
|
@@ -888,7 +911,7 @@ Post = ghostBookshelf.Model.extend({
|
|
|
888
911
|
revision_interval_ms: POST_REVISIONS_INTERVAL_MS
|
|
889
912
|
}
|
|
890
913
|
});
|
|
891
|
-
let authorId = this.contextUser(options);
|
|
914
|
+
let authorId = await this.contextUser(options);
|
|
892
915
|
const authorExists = await ghostBookshelf.model('User').findOne({id: authorId}, {transacting: options.transacting});
|
|
893
916
|
if (!authorExists) {
|
|
894
917
|
authorId = await ghostBookshelf.model('User').getOwnerUser().get('id');
|
|
@@ -954,14 +977,6 @@ Post = ghostBookshelf.Model.extend({
|
|
|
954
977
|
return sequence(ops);
|
|
955
978
|
},
|
|
956
979
|
|
|
957
|
-
created_by: function createdBy() {
|
|
958
|
-
return this.belongsTo('User', 'created_by');
|
|
959
|
-
},
|
|
960
|
-
|
|
961
|
-
updated_by: function updatedBy() {
|
|
962
|
-
return this.belongsTo('User', 'updated_by');
|
|
963
|
-
},
|
|
964
|
-
|
|
965
980
|
published_by: function publishedBy() {
|
|
966
981
|
return this.belongsTo('User', 'published_by');
|
|
967
982
|
},
|
|
@@ -75,10 +75,10 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
|
|
|
75
75
|
return proto.onFetchedCollection.call(this, collection, attrs, options);
|
|
76
76
|
},
|
|
77
77
|
|
|
78
|
-
onCreating: function onCreating(model, attrs, options) {
|
|
78
|
+
onCreating: async function onCreating(model, attrs, options) {
|
|
79
79
|
if (!model.get('authors')) {
|
|
80
80
|
model.set('authors', [{
|
|
81
|
-
id: this.contextUser(options)
|
|
81
|
+
id: await this.contextUser(options)
|
|
82
82
|
}]);
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -292,25 +292,12 @@ Settings = ghostBookshelf.Model.extend({
|
|
|
292
292
|
|
|
293
293
|
// fetch other data that is used when inserting new settings
|
|
294
294
|
const date = ghostBookshelf.knex.raw('CURRENT_TIMESTAMP');
|
|
295
|
-
let owner;
|
|
296
|
-
try {
|
|
297
|
-
owner = await ghostBookshelf.model('User').getOwnerUser();
|
|
298
|
-
} catch (e) {
|
|
299
|
-
// in some tests the owner is deleted and not recreated before setup
|
|
300
|
-
if (e.errorType === 'NotFoundError') {
|
|
301
|
-
owner = {id: 1};
|
|
302
|
-
} else {
|
|
303
|
-
throw e;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
295
|
|
|
307
296
|
const settingsDataToInsert = settingsToInsert.map((setting) => {
|
|
308
297
|
const settingValues = Object.assign({}, setting, {
|
|
309
298
|
id: ObjectID().toHexString(),
|
|
310
299
|
created_at: date,
|
|
311
|
-
|
|
312
|
-
updated_at: date,
|
|
313
|
-
updated_by: owner.id
|
|
300
|
+
updated_at: date
|
|
314
301
|
});
|
|
315
302
|
|
|
316
303
|
return _.pick(settingValues, columns);
|
|
@@ -76,7 +76,7 @@ User = ghostBookshelf.Model.extend({
|
|
|
76
76
|
},
|
|
77
77
|
|
|
78
78
|
format(options) {
|
|
79
|
-
if (options.website &&
|
|
79
|
+
if (options.website &&
|
|
80
80
|
!validator.isURL(options.website, {
|
|
81
81
|
require_protocol: true,
|
|
82
82
|
protocols: ['http', 'https']
|
|
@@ -295,10 +295,6 @@ User = ghostBookshelf.Model.extend({
|
|
|
295
295
|
return attrs;
|
|
296
296
|
},
|
|
297
297
|
|
|
298
|
-
posts: function posts() {
|
|
299
|
-
return this.hasMany('Posts', 'created_by');
|
|
300
|
-
},
|
|
301
|
-
|
|
302
298
|
sessions: function sessions() {
|
|
303
299
|
return this.hasMany('Session');
|
|
304
300
|
},
|
|
@@ -778,9 +774,38 @@ User = ghostBookshelf.Model.extend({
|
|
|
778
774
|
});
|
|
779
775
|
},
|
|
780
776
|
|
|
777
|
+
ownerIdCache: {
|
|
778
|
+
value: null,
|
|
779
|
+
set(value) {
|
|
780
|
+
this.value = value;
|
|
781
|
+
},
|
|
782
|
+
get() {
|
|
783
|
+
return this.value;
|
|
784
|
+
},
|
|
785
|
+
clear() {
|
|
786
|
+
this.value = null;
|
|
787
|
+
}
|
|
788
|
+
},
|
|
789
|
+
|
|
790
|
+
getOwnerId: function getOwnerId(options) {
|
|
791
|
+
if (this.ownerIdCache.value !== null) {
|
|
792
|
+
return Promise.resolve(this.ownerIdCache.value);
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
return this.getOwnerUser(options).then((owner) => {
|
|
796
|
+
this.ownerIdCache.set(owner.id);
|
|
797
|
+
|
|
798
|
+
return owner.id;
|
|
799
|
+
});
|
|
800
|
+
},
|
|
801
|
+
|
|
802
|
+
generateId: function generateId() {
|
|
803
|
+
return ObjectId().toHexString();
|
|
804
|
+
},
|
|
805
|
+
|
|
781
806
|
/**
|
|
782
807
|
* Checks if a user has permission to perform an action on another user
|
|
783
|
-
*
|
|
808
|
+
*
|
|
784
809
|
* @param {Object|string|number} userModelOrId - The user model or ID being acted upon
|
|
785
810
|
* @param {'edit'|'destroy'} action - The action being performed:
|
|
786
811
|
* - 'edit': Edit user details, status, or role
|
|
@@ -1112,6 +1137,8 @@ User = ghostBookshelf.Model.extend({
|
|
|
1112
1137
|
]);
|
|
1113
1138
|
})
|
|
1114
1139
|
.then((results) => {
|
|
1140
|
+
this.ownerIdCache.clear();
|
|
1141
|
+
|
|
1115
1142
|
return Users.forge()
|
|
1116
1143
|
.query('whereIn', 'id', [contextUser.id, results[2]])
|
|
1117
1144
|
.fetch({withRelated: ['roles']});
|
|
@@ -124,8 +124,7 @@ class ActivityPubService {
|
|
|
124
124
|
name: `ActivityPub ${expectedWebhook.event} Webhook`,
|
|
125
125
|
secret: secret,
|
|
126
126
|
integration_id: integration.id,
|
|
127
|
-
created_at: this.knex.raw('current_timestamp')
|
|
128
|
-
created_by: '1'
|
|
127
|
+
created_at: this.knex.raw('current_timestamp')
|
|
129
128
|
};
|
|
130
129
|
});
|
|
131
130
|
await this.knex
|
|
@@ -147,8 +147,7 @@ export class ActivityPubService {
|
|
|
147
147
|
name: `ActivityPub ${expectedWebhook.event} Webhook`,
|
|
148
148
|
secret: secret,
|
|
149
149
|
integration_id: integration.id,
|
|
150
|
-
created_at: this.knex.raw('current_timestamp')
|
|
151
|
-
created_by: '1'
|
|
150
|
+
created_at: this.knex.raw('current_timestamp')
|
|
152
151
|
};
|
|
153
152
|
});
|
|
154
153
|
|
|
@@ -33,7 +33,9 @@ module.exports = class ExplorePingService {
|
|
|
33
33
|
ghost: this.ghostVersion.full,
|
|
34
34
|
site_uuid: this.settingsCache.get('site_uuid'),
|
|
35
35
|
url: this.config.get('url'),
|
|
36
|
-
theme: this.settingsCache.get('active_theme')
|
|
36
|
+
theme: this.settingsCache.get('active_theme'),
|
|
37
|
+
facebook: this.settingsCache.get('facebook'),
|
|
38
|
+
twitter: this.settingsCache.get('twitter')
|
|
37
39
|
};
|
|
38
40
|
|
|
39
41
|
try {
|
|
@@ -77,7 +77,7 @@ select `newsletters`.*, `members_newsletters`.`member_id` as `_pivot_member_id`,
|
|
|
77
77
|
|
|
78
78
|
Then we update the member:
|
|
79
79
|
```
|
|
80
|
-
update `members` set `uuid` = ?, `transient_id` = ?, `email` = ?, `status` = ?, `name` = ?, `expertise` = ?, `note` = ?, `geolocation` = ?, `enable_comment_notifications` = ?, `email_count` = ?, `email_opened_count` = ?, `email_open_rate` = ?, `email_disabled` = ?, `last_seen_at` = ?, `last_commented_at` = ?, `created_at` = ?, `
|
|
80
|
+
update `members` set `uuid` = ?, `transient_id` = ?, `email` = ?, `status` = ?, `name` = ?, `expertise` = ?, `note` = ?, `geolocation` = ?, `enable_comment_notifications` = ?, `email_count` = ?, `email_opened_count` = ?, `email_open_rate` = ?, `email_disabled` = ?, `last_seen_at` = ?, `last_commented_at` = ?, `created_at` = ?, `updated_at` = ? where `id` = ? trx34
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
Then we select the member by ID again to get the freshly updated values from the DB:
|
|
@@ -45,7 +45,7 @@ module.exports = class MentionSendingService {
|
|
|
45
45
|
// for now we don't want to evaluate mentions when importing data (at least needs queueing set up)
|
|
46
46
|
// we do not want to evaluate mentions with fixture (internal) data, e.g. generating posts
|
|
47
47
|
// TODO: real solution is likely suppressing event emission when building fixture data
|
|
48
|
-
if (options && (options.importing || options.context.internal)) {
|
|
48
|
+
if (options && (options.importing || (options.context && options.context.internal))) {
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -24,12 +24,14 @@ class SettingsBREADService {
|
|
|
24
24
|
* @param {Object} options.singleUseTokenProvider
|
|
25
25
|
* @param {Object} options.urlUtils
|
|
26
26
|
* @param {Object} options.labsService - labs service instance
|
|
27
|
+
* @param {Object} options.limitsService - limits service instance
|
|
27
28
|
* @param {{service: Object}} options.emailAddressService
|
|
28
29
|
*/
|
|
29
|
-
constructor({SettingsModel, settingsCache, labsService, mail, singleUseTokenProvider, urlUtils, emailAddressService}) {
|
|
30
|
+
constructor({SettingsModel, settingsCache, labsService, limitsService, mail, singleUseTokenProvider, urlUtils, emailAddressService}) {
|
|
30
31
|
this.SettingsModel = SettingsModel;
|
|
31
32
|
this.settingsCache = settingsCache;
|
|
32
33
|
this.labs = labsService;
|
|
34
|
+
this.limitsService = limitsService;
|
|
33
35
|
this.emailAddressService = emailAddressService;
|
|
34
36
|
|
|
35
37
|
/* email verification setup */
|
|
@@ -194,6 +196,8 @@ class SettingsBREADService {
|
|
|
194
196
|
}
|
|
195
197
|
|
|
196
198
|
if (stripeConnectData) {
|
|
199
|
+
await this.limitsService.errorIfWouldGoOverLimit('limitStripeConnect');
|
|
200
|
+
|
|
197
201
|
filteredSettings.push({
|
|
198
202
|
key: 'stripe_connect_publishable_key',
|
|
199
203
|
value: stripeConnectData.public_key
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
const events = require('../../lib/common/events');
|
|
6
6
|
const models = require('../../models');
|
|
7
7
|
const labs = require('../../../shared/labs');
|
|
8
|
+
const limits = require('../limits');
|
|
8
9
|
const config = require('../../../shared/config');
|
|
9
10
|
const adapterManager = require('../adapter-manager');
|
|
10
11
|
const SettingsCache = require('../../../shared/settings-cache');
|
|
@@ -30,6 +31,7 @@ const getSettingsBREADServiceInstance = () => {
|
|
|
30
31
|
SettingsModel: models.Settings,
|
|
31
32
|
settingsCache: SettingsCache,
|
|
32
33
|
labsService: labs,
|
|
34
|
+
limitsService: limits,
|
|
33
35
|
mail,
|
|
34
36
|
singleUseTokenProvider: new SingleUseTokenProvider({
|
|
35
37
|
SingleUseTokenModel: models.SingleUseToken,
|
|
@@ -110,7 +112,7 @@ module.exports = {
|
|
|
110
112
|
fields.push(new CalculatedField({key: 'social_web_enabled', type: 'boolean', group: 'social_web', fn: settingsHelpers.isSocialWebEnabled.bind(settingsHelpers), dependents: ['social_web', 'labs']}));
|
|
111
113
|
|
|
112
114
|
// Web analytics
|
|
113
|
-
fields.push(new CalculatedField({key: 'web_analytics_enabled', type: 'boolean', group: 'analytics', fn: settingsHelpers.isWebAnalyticsEnabled.bind(settingsHelpers), dependents: ['web_analytics'
|
|
115
|
+
fields.push(new CalculatedField({key: 'web_analytics_enabled', type: 'boolean', group: 'analytics', fn: settingsHelpers.isWebAnalyticsEnabled.bind(settingsHelpers), dependents: ['web_analytics']}));
|
|
114
116
|
fields.push(new CalculatedField({key: 'web_analytics_configured', type: 'boolean', group: 'analytics', fn: settingsHelpers.isWebAnalyticsConfigured.bind(settingsHelpers), dependents: ['web_analytics']}));
|
|
115
117
|
|
|
116
118
|
return fields;
|
|
@@ -234,12 +234,6 @@ class SettingsHelpers {
|
|
|
234
234
|
return false;
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
// Labs setting
|
|
238
|
-
if (!this.labs.isSet('ActivityPub')) {
|
|
239
|
-
debug('Social web is disabled in labs');
|
|
240
|
-
return false;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
237
|
// Ghost (Pro) limits
|
|
244
238
|
if (this.limitService.isDisabled('limitSocialWeb')) {
|
|
245
239
|
debug('Social web is not available for Ghost (Pro) sites without a custom domain, or hosted on a subdirectory');
|
|
@@ -279,12 +273,6 @@ class SettingsHelpers {
|
|
|
279
273
|
return false;
|
|
280
274
|
}
|
|
281
275
|
|
|
282
|
-
// Labs setting
|
|
283
|
-
if (!this.labs.isSet('trafficAnalytics')) {
|
|
284
|
-
debug('Web analytics is disabled in labs');
|
|
285
|
-
return false;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
276
|
// Check if web analytics can be configured (limit service and required config)
|
|
289
277
|
if (!this.isWebAnalyticsConfigured()) {
|
|
290
278
|
return false;
|
|
@@ -116,7 +116,10 @@ class UpdateCheckService {
|
|
|
116
116
|
const hash = (await this.api.settings.read(_.extend({key: 'db_hash'}, internal))).settings[0];
|
|
117
117
|
const theme = (await this.api.settings.read(_.extend({key: 'active_theme'}, internal))).settings[0];
|
|
118
118
|
const posts = await this.api.posts.browse();
|
|
119
|
-
const users = await this.api.users.browse(
|
|
119
|
+
const users = await this.api.users.browse({
|
|
120
|
+
...internal,
|
|
121
|
+
include: ['roles']
|
|
122
|
+
});
|
|
120
123
|
const npm = await util.promisify(exec)('npm -v');
|
|
121
124
|
|
|
122
125
|
const blogUrl = this.config.siteUrl;
|
|
@@ -128,7 +131,20 @@ class UpdateCheckService {
|
|
|
128
131
|
data.theme = theme ? theme.value : '';
|
|
129
132
|
data.post_count = posts && posts.meta && posts.meta.pagination ? posts.meta.pagination.total : 0;
|
|
130
133
|
data.user_count = users && users.users && users.users.length ? users.users.length : 0;
|
|
131
|
-
|
|
134
|
+
|
|
135
|
+
let blogCreatedAt = null;
|
|
136
|
+
|
|
137
|
+
if (users && users.users && users.users.length > 0) {
|
|
138
|
+
const ownerUser = users.users.find(user => user.roles.some(role => role.name === 'Owner'));
|
|
139
|
+
|
|
140
|
+
if (ownerUser) {
|
|
141
|
+
blogCreatedAt = ownerUser.created_at;
|
|
142
|
+
} else {
|
|
143
|
+
blogCreatedAt = users.users[0].created_at;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
data.blog_created_at = blogCreatedAt ? moment(blogCreatedAt).unix() : '';
|
|
132
148
|
data.npm_version = npm.stdout.trim();
|
|
133
149
|
|
|
134
150
|
return data;
|
|
@@ -19,7 +19,6 @@ module.exports = [
|
|
|
19
19
|
// @TODO: https://github.com/TryGhost/Ghost/issues/10335
|
|
20
20
|
// 'page',
|
|
21
21
|
'status',
|
|
22
|
-
'amp',
|
|
23
22
|
'codeinjection_head',
|
|
24
23
|
'codeinjection_foot',
|
|
25
24
|
'meta_title',
|
|
@@ -68,7 +67,6 @@ module.exports = [
|
|
|
68
67
|
// @TODO: https://github.com/TryGhost/Ghost/issues/10335
|
|
69
68
|
// 'page',
|
|
70
69
|
// 'status',
|
|
71
|
-
'amp',
|
|
72
70
|
'codeinjection_head',
|
|
73
71
|
'codeinjection_foot',
|
|
74
72
|
'meta_title',
|
|
@@ -2,6 +2,7 @@ const debug = require('@tryghost/debug')('web:api:default:app');
|
|
|
2
2
|
const config = require('../../../shared/config');
|
|
3
3
|
const express = require('../../../shared/express');
|
|
4
4
|
const sentry = require('../../../shared/sentry');
|
|
5
|
+
const middleware = require('../shared/middleware');
|
|
5
6
|
const errorHandler = require('@tryghost/mw-error-handler');
|
|
6
7
|
const APIVersionCompatibilityService = require('../../services/api-version-compatibility');
|
|
7
8
|
|
|
@@ -19,6 +20,9 @@ module.exports = function setupApiApp() {
|
|
|
19
20
|
apiApp.use(APIVersionCompatibilityService.versionRewrites);
|
|
20
21
|
apiApp.use(APIVersionCompatibilityService.contentVersion);
|
|
21
22
|
|
|
23
|
+
// Enforce capped limit parameter
|
|
24
|
+
apiApp.use(middleware.maxLimitCap);
|
|
25
|
+
|
|
22
26
|
apiApp.lazyUse('/content/', require('./endpoints/content/app'));
|
|
23
27
|
apiApp.lazyUse('/admin/', require('./endpoints/admin/app'));
|
|
24
28
|
|
|
@@ -5,7 +5,7 @@ const shared = require('../../../shared');
|
|
|
5
5
|
const apiMw = require('../../middleware');
|
|
6
6
|
|
|
7
7
|
const messages = {
|
|
8
|
-
|
|
8
|
+
apiTokenBlocked: 'API tokens do not have permission to access this endpoint',
|
|
9
9
|
staffTokenBlocked: 'Staff tokens are not allowed to access this endpoint'
|
|
10
10
|
};
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ const messages = {
|
|
|
14
14
|
* @param {import('express').Response} res
|
|
15
15
|
* @param {import('express').NextFunction} next
|
|
16
16
|
*/
|
|
17
|
-
const
|
|
17
|
+
const tokenPermissionCheck = function tokenPermissionCheck(req, res, next) {
|
|
18
18
|
// CASE: user is logged in with user auth, skip to permission system
|
|
19
19
|
if (!req.api_key) {
|
|
20
20
|
return next();
|
|
@@ -81,10 +81,9 @@ const notImplemented = function notImplemented(req, res, next) {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
next(new errors.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
statusCode: 501
|
|
84
|
+
next(new errors.NoPermissionError({
|
|
85
|
+
message: tpl(messages.apiTokenBlocked),
|
|
86
|
+
statusCode: 403
|
|
88
87
|
}));
|
|
89
88
|
};
|
|
90
89
|
|
|
@@ -102,7 +101,7 @@ module.exports.authAdminApi = [
|
|
|
102
101
|
apiMw.cors,
|
|
103
102
|
shared.middleware.urlRedirects.adminSSLAndHostRedirect,
|
|
104
103
|
shared.middleware.prettyUrls,
|
|
105
|
-
|
|
104
|
+
tokenPermissionCheck
|
|
106
105
|
];
|
|
107
106
|
|
|
108
107
|
/**
|
|
@@ -118,7 +117,7 @@ module.exports.authAdminApiWithUrl = [
|
|
|
118
117
|
apiMw.cors,
|
|
119
118
|
shared.middleware.urlRedirects.adminSSLAndHostRedirect,
|
|
120
119
|
shared.middleware.prettyUrls,
|
|
121
|
-
|
|
120
|
+
tokenPermissionCheck
|
|
122
121
|
];
|
|
123
122
|
|
|
124
123
|
/**
|
|
@@ -130,5 +129,5 @@ module.exports.publicAdminApi = [
|
|
|
130
129
|
apiMw.cors,
|
|
131
130
|
shared.middleware.urlRedirects.adminSSLAndHostRedirect,
|
|
132
131
|
shared.middleware.prettyUrls,
|
|
133
|
-
|
|
132
|
+
tokenPermissionCheck
|
|
134
133
|
];
|
|
@@ -19,7 +19,6 @@ module.exports = function apiRoutes() {
|
|
|
19
19
|
|
|
20
20
|
// ## Public
|
|
21
21
|
router.get('/site', mw.publicAdminApi, http(api.site.read));
|
|
22
|
-
router.post('/mail_events', mw.publicAdminApi, http(api.mailEvents.add));
|
|
23
22
|
|
|
24
23
|
// ## Configuration
|
|
25
24
|
router.get('/config', mw.authAdminApi, http(api.config.read));
|
|
@@ -247,7 +246,6 @@ module.exports = function apiRoutes() {
|
|
|
247
246
|
router.get('/tinybird/token', mw.authAdminApi, http(api.tinybird.token));
|
|
248
247
|
|
|
249
248
|
// ## Sessions
|
|
250
|
-
router.get('/session', mw.authAdminApi, http(api.session.read));
|
|
251
249
|
// We don't need auth when creating a new session (logging in)
|
|
252
250
|
router.post('/session',
|
|
253
251
|
shared.middleware.brute.globalBlock,
|
|
@@ -23,6 +23,9 @@ module.exports = function apiRoutes() {
|
|
|
23
23
|
// Authenticated Routes
|
|
24
24
|
router.use(membersService.middleware.loadMemberSession);
|
|
25
25
|
|
|
26
|
+
// Enforce capped limit parameter
|
|
27
|
+
router.use(shared.middleware.maxLimitCap);
|
|
28
|
+
|
|
26
29
|
router.get('/', http(api.commentsMembers.browse));
|
|
27
30
|
router.get('/post/:post_id', http(api.commentsMembers.browse));
|
|
28
31
|
router.get('/:id', http(api.commentsMembers.read));
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const {applyLimitCap, limitConfig} = require('../../../../shared/max-limit-cap');
|
|
2
|
+
|
|
3
|
+
// Prior to Ghost 6.x we allowed any limit value, including 'all', but as sites
|
|
4
|
+
// grew in size it led to performance issues and mis-use of the API.
|
|
5
|
+
|
|
6
|
+
// After Ghost 6.x we only allow a max limit of 100. This middleware enforces
|
|
7
|
+
// that limit by rewriting the limit parameter before it reaches any API code.
|
|
8
|
+
|
|
9
|
+
function maxLimitCap(req, res, next) {
|
|
10
|
+
const limit = req.query.limit;
|
|
11
|
+
|
|
12
|
+
if (!limit) {
|
|
13
|
+
return next();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Apply the shared limit capping logic with URL for exception endpoint checking
|
|
17
|
+
const cappedLimit = applyLimitCap(limit, {url: req.originalUrl});
|
|
18
|
+
|
|
19
|
+
req.query.limit = cappedLimit;
|
|
20
|
+
next();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Create middleware stack with limitConfig property for test access
|
|
24
|
+
/** @type {Array<Function> & {limitConfig: object}} */
|
|
25
|
+
const middlewareStack = Object.assign([maxLimitCap], {limitConfig});
|
|
26
|
+
|
|
27
|
+
module.exports = middlewareStack;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// Pretty URL redirects
|
|
2
2
|
//
|
|
3
|
-
// These are
|
|
3
|
+
// These are three pieces of middleware that handle ensuring that
|
|
4
4
|
// URLs get formatted correctly.
|
|
5
5
|
// Slashes ensures that we get trailing slashes
|
|
6
|
+
// redirectAmpUrls removes /amp from the end of urls if it exists (AMP support removed in v6)
|
|
6
7
|
// Uncapitalise changes case to lowercase
|
|
7
8
|
// @TODO optimize this to reduce the number of redirects required to get to a pretty URL
|
|
8
9
|
// @TODO move this to being used by routers?
|
|
@@ -15,5 +16,6 @@ module.exports = [
|
|
|
15
16
|
'Cache-Control': `public, max-age=${config.get('caching:301:maxAge')}`
|
|
16
17
|
}
|
|
17
18
|
}),
|
|
19
|
+
require('./redirect-amp-urls'),
|
|
18
20
|
require('./uncapitalise')
|
|
19
21
|
];
|