ghost 5.129.2 → 6.0.0-alpha.1
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.1.tgz +0 -0
- package/core/boot.js +0 -2
- package/core/built/admin/assets/admin-x-activitypub/admin-x-activitypub.js +2 -2
- package/core/built/admin/assets/admin-x-activitypub/{index-B12913rO.mjs → index-BhgdXgH_.mjs} +2 -2
- package/core/built/admin/assets/admin-x-activitypub/{index-B7EmcyVj.mjs → index-rDFm98Ub.mjs} +15498 -15418
- package/core/built/admin/assets/admin-x-settings/{CodeEditorView-l2Ex2555.mjs → CodeEditorView-CA2VVtOE.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-C6P_16OJ.mjs → index-Dl3F40x5.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/index-KA2tjCkS.mjs +30462 -0
- package/core/built/admin/assets/admin-x-settings/{modals-CY1xx4Em.mjs → modals-B0zezufO.mjs} +2185 -2183
- package/core/built/admin/assets/{chunk.524.c8313bccd308920abf9c.js → chunk.524.996c1c4d269fa6a50e90.js} +7 -7
- package/core/built/admin/assets/{chunk.582.e4feab981886cfc91835.js → chunk.582.75cf44e5d1b925adf16d.js} +9 -9
- package/core/built/admin/assets/{chunk.728.214803966b81ffdb1acd.js → chunk.728.985c45ad584b4b91ca60.js} +124 -124
- package/core/built/admin/assets/{ghost-db9fcb8c1f65776f3ee11c39f19a660b.js → ghost-5a5b2112df68dfaf6813ce38cad16847.js} +29 -30
- package/core/built/admin/assets/posts/posts.js +6641 -6621
- package/core/built/admin/assets/stats/stats.js +12770 -12724
- package/core/built/admin/index.html +4 -4
- package/core/frontend/helpers/get.js +4 -2
- package/core/frontend/helpers/ghost_head.js +71 -77
- package/core/frontend/helpers/match.js +3 -0
- 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 +20 -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/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 +3 -3
- 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 +3 -2
- package/core/server/api/endpoints/utils/serializers/input/utils/settings-key-type-mapper.js +3 -2
- package/core/server/api/endpoints/utils/serializers/output/all.js +1 -1
- package/core/server/api/endpoints/utils/serializers/output/config.js +2 -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.130/2025-07-11-14-14-54-add-explore-settings.js +16 -0
- 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 +18 -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/README.md +9 -14
- 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 +23 -4
- package/core/server/services/activitypub/ActivityPubService.ts +27 -8
- package/core/server/services/email-service/email-templates/partials/styles.hbs +0 -14
- package/core/server/services/explore-ping/ExplorePingService.js +44 -33
- package/core/server/services/link-redirection/README.md +1 -1
- package/core/server/services/mentions/MentionSendingService.js +1 -1
- package/core/server/services/public-config/config.js +4 -0
- package/core/server/services/themes/installer.js +17 -3
- 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/env/config.production.json +4 -0
- package/core/shared/config/overrides.json +1 -4
- package/core/shared/labs.js +5 -6
- package/core/shared/max-limit-cap.js +61 -0
- package/package.json +7 -8
- package/tsconfig.tsbuildinfo +1 -1
- package/yarn.lock +203 -261
- package/components/tryghost-i18n-5.129.2.tgz +0 -0
- package/core/built/admin/assets/admin-x-settings/index-DoLRADbr.mjs +0 -30308
- 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
- /package/core/built/admin/assets/{chunk.728.214803966b81ffdb1acd.js.LICENSE.txt → chunk.728.985c45ad584b4b91ca60.js.LICENSE.txt} +0 -0
|
@@ -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']});
|
|
@@ -18,12 +18,32 @@ class ActivityPubService {
|
|
|
18
18
|
this.identityTokenService = identityTokenService;
|
|
19
19
|
}
|
|
20
20
|
getExpectedWebhooks(secret) {
|
|
21
|
-
return [
|
|
21
|
+
return [
|
|
22
|
+
{
|
|
22
23
|
event: 'post.published',
|
|
23
24
|
target_url: new URL('.ghost/activitypub/v1/webhooks/post/published', this.siteUrl),
|
|
24
25
|
api_version: 'v5.100.0',
|
|
25
26
|
secret
|
|
26
|
-
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
event: 'post.deleted',
|
|
30
|
+
target_url: new URL('.ghost/activitypub/v1/webhooks/post/deleted', this.siteUrl),
|
|
31
|
+
api_version: 'v5.100.0',
|
|
32
|
+
secret
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
event: 'post.unpublished',
|
|
36
|
+
target_url: new URL('.ghost/activitypub/v1/webhooks/post/unpublished', this.siteUrl),
|
|
37
|
+
api_version: 'v5.100.0',
|
|
38
|
+
secret
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
event: 'post.published.edited',
|
|
42
|
+
target_url: new URL('.ghost/activitypub/v1/webhooks/post/updated', this.siteUrl),
|
|
43
|
+
api_version: 'v5.100.0',
|
|
44
|
+
secret
|
|
45
|
+
}
|
|
46
|
+
];
|
|
27
47
|
}
|
|
28
48
|
async checkWebhookState(expectedWebhooks, integration) {
|
|
29
49
|
this.logging.info(`Checking ActivityPub Webhook state`);
|
|
@@ -104,8 +124,7 @@ class ActivityPubService {
|
|
|
104
124
|
name: `ActivityPub ${expectedWebhook.event} Webhook`,
|
|
105
125
|
secret: secret,
|
|
106
126
|
integration_id: integration.id,
|
|
107
|
-
created_at: this.knex.raw('current_timestamp')
|
|
108
|
-
created_by: '1'
|
|
127
|
+
created_at: this.knex.raw('current_timestamp')
|
|
109
128
|
};
|
|
110
129
|
});
|
|
111
130
|
await this.knex
|
|
@@ -25,12 +25,32 @@ export class ActivityPubService {
|
|
|
25
25
|
) {}
|
|
26
26
|
|
|
27
27
|
getExpectedWebhooks(secret: string): ExpectedWebhook[] {
|
|
28
|
-
return [
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
return [
|
|
29
|
+
{
|
|
30
|
+
event: 'post.published',
|
|
31
|
+
target_url: new URL('.ghost/activitypub/v1/webhooks/post/published', this.siteUrl),
|
|
32
|
+
api_version: 'v5.100.0',
|
|
33
|
+
secret
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
event: 'post.deleted',
|
|
37
|
+
target_url: new URL('.ghost/activitypub/v1/webhooks/post/deleted', this.siteUrl),
|
|
38
|
+
api_version: 'v5.100.0',
|
|
39
|
+
secret
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
event: 'post.unpublished',
|
|
43
|
+
target_url: new URL('.ghost/activitypub/v1/webhooks/post/unpublished', this.siteUrl),
|
|
44
|
+
api_version: 'v5.100.0',
|
|
45
|
+
secret
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
event: 'post.published.edited',
|
|
49
|
+
target_url: new URL('.ghost/activitypub/v1/webhooks/post/updated', this.siteUrl),
|
|
50
|
+
api_version: 'v5.100.0',
|
|
51
|
+
secret
|
|
52
|
+
}
|
|
53
|
+
];
|
|
34
54
|
}
|
|
35
55
|
|
|
36
56
|
async checkWebhookState(expectedWebhooks: ExpectedWebhook[], integration: {id: string}) {
|
|
@@ -127,8 +147,7 @@ export class ActivityPubService {
|
|
|
127
147
|
name: `ActivityPub ${expectedWebhook.event} Webhook`,
|
|
128
148
|
secret: secret,
|
|
129
149
|
integration_id: integration.id,
|
|
130
|
-
created_at: this.knex.raw('current_timestamp')
|
|
131
|
-
created_by: '1'
|
|
150
|
+
created_at: this.knex.raw('current_timestamp')
|
|
132
151
|
};
|
|
133
152
|
});
|
|
134
153
|
|
|
@@ -381,7 +381,6 @@ h6 + .kg-paywall .kg-paywall-hr td {
|
|
|
381
381
|
}
|
|
382
382
|
|
|
383
383
|
/* Exclude CTA cards with colored backgrounds from custom text color, but allow transparent ones */
|
|
384
|
-
{{#hasFeature "emailCustomization"}}
|
|
385
384
|
{{#each ctaBgColors}}
|
|
386
385
|
.post-content-row .kg-cta-bg-{{this}} .kg-cta-text p,
|
|
387
386
|
.post-content-row .kg-cta-bg-{{this}} .kg-cta-text ul,
|
|
@@ -391,17 +390,6 @@ h6 + .kg-paywall .kg-paywall-hr td {
|
|
|
391
390
|
color: inherit !important;
|
|
392
391
|
}
|
|
393
392
|
{{/each}}
|
|
394
|
-
{{else}}
|
|
395
|
-
.post-content-row .kg-cta-bg-grey .kg-cta-text p,
|
|
396
|
-
.post-content-row .kg-cta-bg-blue .kg-cta-text p,
|
|
397
|
-
.post-content-row .kg-cta-bg-green .kg-cta-text p,
|
|
398
|
-
.post-content-row .kg-cta-bg-yellow .kg-cta-text p,
|
|
399
|
-
.post-content-row .kg-cta-bg-red .kg-cta-text p,
|
|
400
|
-
.post-content-row .kg-cta-bg-pink .kg-cta-text p,
|
|
401
|
-
.post-content-row .kg-cta-bg-purple .kg-cta-text p {
|
|
402
|
-
color: inherit !important;
|
|
403
|
-
}
|
|
404
|
-
{{/hasFeature}}
|
|
405
393
|
|
|
406
394
|
.kg-cta-bg-none .kg-cta-sponsor-label span,
|
|
407
395
|
.kg-cta-bg-white .kg-cta-sponsor-label span {
|
|
@@ -2542,10 +2530,8 @@ table.btn-accent a {
|
|
|
2542
2530
|
{{/if}}
|
|
2543
2531
|
|
|
2544
2532
|
</style>
|
|
2545
|
-
{{#hasFeature "emailCustomization"}}
|
|
2546
2533
|
<!--[if mso]>
|
|
2547
2534
|
<style type="text/css">
|
|
2548
2535
|
ul, ol { margin-left: 1.5em !important; } {{!-- fix bullets/numbers not appearing for lists in older Outlook versions --}}
|
|
2549
2536
|
</style>
|
|
2550
2537
|
<![endif]-->
|
|
2551
|
-
{{/hasFeature}}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module.exports = class ExplorePingService {
|
|
2
2
|
/**
|
|
3
3
|
* @param {object} deps
|
|
4
|
-
* @param {{
|
|
4
|
+
* @param {{get: (string) => string}} deps.settingsCache
|
|
5
5
|
* @param {object} deps.config
|
|
6
6
|
* @param {object} deps.labs
|
|
7
7
|
* @param {object} deps.logging
|
|
@@ -14,6 +14,7 @@ module.exports = class ExplorePingService {
|
|
|
14
14
|
* }}} deps.posts
|
|
15
15
|
* @param {{stats: {
|
|
16
16
|
* getTotalMembers: () => Promise<number>
|
|
17
|
+
* getMRRHistory: () => Promise<number>
|
|
17
18
|
* }}} deps.members
|
|
18
19
|
*/
|
|
19
20
|
constructor({settingsCache, config, labs, logging, ghostVersion, request, posts, members}) {
|
|
@@ -28,45 +29,50 @@ module.exports = class ExplorePingService {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
async constructPayload() {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this.posts.stats.getMostRecentlyPublishedPostDate(),
|
|
38
|
-
this.posts.stats.getFirstPublishedPostDate()
|
|
39
|
-
]);
|
|
32
|
+
const payload = {
|
|
33
|
+
ghost: this.ghostVersion.full,
|
|
34
|
+
site_uuid: this.settingsCache.get('site_uuid'),
|
|
35
|
+
url: this.config.get('url'),
|
|
36
|
+
theme: this.settingsCache.get('active_theme')
|
|
37
|
+
};
|
|
40
38
|
|
|
41
|
-
// Get member statistics with error handling
|
|
42
|
-
let totalMembers = null;
|
|
43
39
|
try {
|
|
44
|
-
|
|
40
|
+
const [totalPosts, lastPublishedAt, firstPublishedAt] = await Promise.all([
|
|
41
|
+
this.posts.stats.getTotalPostsPublished(),
|
|
42
|
+
this.posts.stats.getMostRecentlyPublishedPostDate(),
|
|
43
|
+
this.posts.stats.getFirstPublishedPostDate()
|
|
44
|
+
]);
|
|
45
|
+
|
|
46
|
+
payload.posts_total = totalPosts;
|
|
47
|
+
payload.posts_last = lastPublishedAt ? lastPublishedAt.toISOString() : null;
|
|
48
|
+
payload.posts_first = firstPublishedAt ? firstPublishedAt.toISOString() : null;
|
|
45
49
|
} catch (err) {
|
|
46
|
-
this.logging.warn('Failed to fetch
|
|
50
|
+
this.logging.warn('Failed to fetch post statistics', {
|
|
47
51
|
error: err.message,
|
|
48
52
|
context: 'explore-ping-service'
|
|
49
53
|
});
|
|
50
|
-
|
|
54
|
+
payload.posts_total = null;
|
|
55
|
+
payload.posts_last = null;
|
|
56
|
+
payload.posts_first = null;
|
|
51
57
|
}
|
|
52
58
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
59
|
+
if (this.settingsCache.get('explore_ping_growth')) {
|
|
60
|
+
try {
|
|
61
|
+
const totalMembers = await this.members.stats.getTotalMembers();
|
|
62
|
+
const mrr = await this.members.stats.getMRRHistory();
|
|
63
|
+
payload.members_total = totalMembers;
|
|
64
|
+
payload.mrr = mrr;
|
|
65
|
+
} catch (err) {
|
|
66
|
+
this.logging.warn('Failed to fetch member statistics', {
|
|
67
|
+
error: err.message,
|
|
68
|
+
context: 'explore-ping-service'
|
|
69
|
+
});
|
|
70
|
+
payload.members_total = null;
|
|
71
|
+
payload.mrr = null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return payload;
|
|
70
76
|
}
|
|
71
77
|
|
|
72
78
|
async makeRequest(exploreUrl, payload) {
|
|
@@ -95,12 +101,17 @@ module.exports = class ExplorePingService {
|
|
|
95
101
|
return;
|
|
96
102
|
}
|
|
97
103
|
|
|
98
|
-
const exploreUrl = this.config.get('explore:
|
|
104
|
+
const exploreUrl = this.config.get('explore:update_url');
|
|
99
105
|
if (!exploreUrl) {
|
|
100
106
|
this.logging.warn('Explore URL not set');
|
|
101
107
|
return;
|
|
102
108
|
}
|
|
103
109
|
|
|
110
|
+
if (!this.settingsCache.get('explore_ping')) {
|
|
111
|
+
this.logging.info('Explore ping disabled');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
104
115
|
const payload = await this.constructPayload();
|
|
105
116
|
await this.makeRequest(exploreUrl, payload);
|
|
106
117
|
}
|
|
@@ -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
|
|
|
@@ -25,6 +25,10 @@ module.exports = function getConfigProperties() {
|
|
|
25
25
|
security: config.get('security')
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
+
if (config.get('explore') && config.get('explore:testimonials_url')) {
|
|
29
|
+
configProperties.exploreTestimonialsUrl = config.get('explore:testimonials_url');
|
|
30
|
+
}
|
|
31
|
+
|
|
28
32
|
// WIP tinybird stats feature - it's entirely config driven instead of using an alpha flag for now
|
|
29
33
|
if (config.get('tinybird') && config.get('tinybird:stats')) {
|
|
30
34
|
const statsConfig = config.get('tinybird:stats');
|
|
@@ -19,9 +19,18 @@ const messages = {
|
|
|
19
19
|
const installFromGithub = async (ref) => {
|
|
20
20
|
const [org, repo] = ref.toLowerCase().split('/');
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
if (limitService.isLimited('customThemes')) {
|
|
23
|
+
// The custom theme limit might consist of only one single theme, so we can't rely on
|
|
24
|
+
// the org alone to determine if the request is allowed or not.
|
|
25
|
+
const noOtherThemesAllowed = limitService.limits.customThemes?.allowlist?.length === 1;
|
|
26
|
+
//TODO: move the organization check to config
|
|
27
|
+
const isNotOfficialThemeRequest = org.toLowerCase() !== 'tryghost';
|
|
28
|
+
|
|
29
|
+
const checkThemeLimit = noOtherThemesAllowed || isNotOfficialThemeRequest;
|
|
30
|
+
|
|
31
|
+
if (checkThemeLimit) {
|
|
32
|
+
await limitService.errorIfWouldGoOverLimit('customThemes', {value: repo.toLowerCase()});
|
|
33
|
+
}
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
// omit /:ref so we fetch the default branch
|
|
@@ -62,6 +71,11 @@ const installFromGithub = async (ref) => {
|
|
|
62
71
|
}));
|
|
63
72
|
}
|
|
64
73
|
|
|
74
|
+
if (e instanceof errors.HostLimitError) {
|
|
75
|
+
// If the error is a HostLimitError, we can assume that the theme name is not allowed
|
|
76
|
+
return Promise.reject(e);
|
|
77
|
+
}
|
|
78
|
+
|
|
65
79
|
throw e;
|
|
66
80
|
} finally {
|
|
67
81
|
// clean up tmp dir with downloaded file
|
|
@@ -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;
|