Commit Graph

82 Commits

Author SHA1 Message Date
Simon Backx
a822c5a8c5 Added test to check if feedback buttons are hidden if alpha flag is disabled 2022-10-18 16:47:06 +02:00
Simon Backx
d1e6870740
🐛 Fixed large mailgun recipient data (#15638)
fixes https://github.com/TryGhost/Team/issues/2096

When generating the recipient data for emails, the email clicks
implementation is resulting in a recipient variable being added called
replacement_xxx once for each link containing the same UUID.

This generates a lot of unnecessary data overhead for emails, and it
turns out that mailgun has a 25MB message limit. We wouldn't have come
close if we only included the uuid once.
2022-10-18 10:32:50 +02:00
Elena Baidakova
e831be6bc2
Added the feedback buttons in the emails (#15619)
closes TryGhost/Team#2046
closes TryGhost/Team#2045
- Added feedback buttons markup.
- Added feedback links generation.
2022-10-14 18:12:17 +04:00
Fabien 'egg' O'Carroll
bd0f4b4b8c
Added Tier price and currency data to products table (#15366)
refs https://github.com/TryGhost/Team/issues/1765

In order to better handle deleted objects in Stripe we want to decouple
Members from Stripe.

These changes allow us to have the Tier concept completely independent
of the Stripe tables, such that the Stripe data can be generated as/when
it's needed - which will help to protect against missing data.
2022-10-14 06:40:17 +01:00
Naz
4db0be603f Added subscriptions table
refs https://github.com/TryGhost/Team/issues/2030

- adds `subscriptions` table to the DB schema
- this new table is aimed to support a native "subscription" primitive in Ghost
  that most resembles previously used `members_stripe_customers_subscriptions` table
2022-10-13 11:19:13 +07:00
Daniel Lockyer
74e1d52d6a Fixed incorrect maximum length definition in schema
refs https://github.com/TryGhost/Toolbox/issues/441

- whilst reviewing another PR, I noticed we were incorrectly using
  `maxLength` instead of `maxlength` in the schema column definition
- it turns out we've already been doing this wrong for a while with
  other columns
- this key is not acted upon, so the maximum column length was not applied
- fixing up the DB to the correct maximum length is something to fix in the
  future but right now, the schema does not reflect the size of the
  column that actually got created
- the fallback when `maxlength` is not provided is currently 191 [0], so
  this commit switches the schema and migrations to using the correct
  key name and column length that they are using when applied

[0]: 24670aa555/ghost/core/core/server/data/schema/commands.js (L27)
2022-10-13 09:58:19 +07:00
Daniel Lockyer
143ae857c9 Removed bool type from schema
refs https://github.com/TryGhost/Toolbox/issues/441

- we tend to have a mix of `bool` and `boolean` in the schema and
  migrations, which has become a real nit for me at this point
- we don't do any special handling between `bool` and `boolean`, it's
  just something we pass to Knex
- `bool` is an alias for `boolean` but `boolean` is actually documented - https://knexjs.org/guide/schema-builder.html#boolean
- this commit switches Ghost to only using `boolean` in the schema and
  migrations, and removes `bool` from the allowlist in tests to prevent
  us from adding it again in the future
- this should make absolutely no difference to the DB because both
  resulted in the same column
2022-10-13 09:37:38 +07:00
Daniel Lockyer
24670aa555
Fixed validating numbers as booleans in schema validator
refs https://github.com/TryGhost/Toolbox/issues/441

- I'm currently working on cleaning up our uses of `bool` and `boolean`
  in favor of `boolean`, and I've noticed we only handle converting
  numbers into booleans when the type is `bool`, so validation would
  otherwise fail
- given these can be used interchangeably, we should also support
  converting the numbers into booleans when the type is `boolean`
- this is going to get cleaned up again when I remove `bool` but this
  fixes the validation bug for now
2022-10-13 08:20:31 +07:00
Daniel Lockyer
845f8d965e
Added test to validate schema structure
refs https://github.com/TryGhost/Toolbox/issues/441

- this is only v1 of the test I would like but it validates the keys on
  a column definition are part of an allowlist
- this has already uncovered a bug with `maxLength` (vs `maxlength`)
2022-10-12 19:19:33 +07:00
Daniel Lockyer
e2ba19b0df
Fixed import of bson-objectid in accordance to the typings
- there's a few different ways we can import it but I've chosen to
  append `.default` as we have done in several other places in the code
2022-10-12 14:54:35 +07:00
Simon Backx
68bdc1afea
Added post sentiment (#15592)
fixes https://github.com/TryGhost/Team/issues/2054

This change adds the sentiment and positive_feedback counts to the posts models. This change isn't really ideal because there are some problems here:
- sentiment isn't really a count
- we don't need to include the sentiment and positive_feedback as a default for posts (but the same is true for attribution)

It would make sense to move this to separate endpoints that only fetch the analytics for a given post when the analytics page is opened. But for our initial skateboard version of audience feedback this should be a good start to already see the data.
2022-10-11 17:52:14 +02:00
Elena Baidakova
1221ba5d1d
Added feedback_enabled to newsletters table (#15589)
closes TryGhost/Team#2042
- Added ability to enable audience feedback per newsletter (just on BE side).
2022-10-11 16:06:26 +04:00
Simon Backx
74d749fa63
Added members_feedback table (#15581)
fixes https://github.com/TryGhost/Team/issues/2041
2022-10-11 13:21:31 +02:00
Fabien 'egg' O'Carroll
45d65663f4
Simplified link tracking related tables naming (#15480)
- Removes superfluous "link" from table names
- Fixes type definititon of dropTables util
- Updates & renames models
- Noop existing migrations to avoid unnecessary work
2022-09-29 22:08:45 +01:00
Simon Backx
0cd0fc838d
Added email track clicks column and cleaned up frontend checks (#15501)
fixes https://github.com/TryGhost/Team/issues/2008

- New column that stores email click tracking at the time it was created
- Improved frontend side checks for when to show analytics
2022-09-29 16:42:45 +02:00
Naz
8cbf913582 Increased Vary granularity for versioned requests
refs https://github.com/TryGhost/Toolbox/issues/425
refs https://github.com/TryGhost/Toolbox/issues/280

- The versioned API responses vary based on requested version (passed in request's 'accept-version' header). shared caches that sit between Ghost's origin server and the browser would be putting responses with same Vary into the same caching bucket, which is incorrect.
- This change makes response's Vary more granular and tells caching mechanisms to take 'Accept-Version' request header into account when caching.
- Informative read on the topic - https://www.fastly.com/blog/getting-most-out-vary-fastly
2022-09-28 14:48:43 +08:00
Rishabh Garg
b99c5428d0
Added referrer attribution columns to events table (#15436)
refs TryGhost/Team#1931

- referrer source, medium and url will be stored in the events table along with rest of attribution data
- stores referrer information on two tables
  - `members_created_events` for signups
  - `members_subscription_created_events` for paid conversions
2022-09-21 19:01:36 +05:30
Simon Backx
901a28f3c6
Added link_redirects and members_link_click_events tables (#15421)
closes https://github.com/TryGhost/Team/issues/1912
closes https://github.com/TryGhost/Team/issues/1913
2022-09-19 11:20:36 +02:00
Kevin Ansfield
3b21d26be7
Wired up creation of post_revisions entries when saving posts with lexical (#15422)
no issue

- added `PostRevsion` model
- duplicated `mobiledoc_revision` creation routine in Post model's onSaving hook to create `post_revision` when model's `lexical` field has changed
- updated `mobiledoc_revision` creation to skip when `lexical` field is populated
2022-09-16 11:59:35 +01:00
Kevin Ansfield
1581f439e9
Added post_revisions table (#15420)
no issue

- initially this will perform the same function as `mobiledoc_revisions` but storing `lexical` instead of `mobiledoc`
- naming is intentionally generic ready for later expansions
2022-09-16 10:19:05 +01:00
Simon Backx
a7b583050c
Added link tracking to paywall (#15414)
closes https://github.com/TryGhost/Team/issues/1908

### Problem:
- We need tracking on the paywall links in each email. (we cannot ignore them because those buttons are probably gonna have a higher paid conversion attribution than others).
- Currently we only add the paywall HTML to an email when processing each batch. So if we batch an email to 1.000 recipients per 100, we'll generate the paywall HTML 10 times. 
- We cannot replace links in `renderEmailForSegment` because that methods will get called multiple times. We don't want to have multiple redirect instances created for the same link in the same email.

###  Solution:
- Move the generation of the paywall to the `serialize` method of the post email serializer.
- Surround the generated paywall with HTML-comments so we can remove it if required in `renderEmailForSegment` depending on the member segment we are sending the email to.

---

### Before:

**Serialize output:**
```html
<html>
    <body>
        <h1>Generated email header</h1>
        <p>Generated text</p>

        <div>
            <!-- POST CONTENT START -->
                <h1>Post title</h1>
                <p>Content visible for all members</p>
            <!--members-only-->
                <p>Content visible for paid members only</p>
            <!-- POST CONTENT END -->
        </div>
    </body>
</html>
```

To be modified later by  `renderEmailForSegment`:

**Paid members (nothing changed):**
```html
<html>
    <body>
        <h1>Generated email header</h1>
        <p>Generated text</p>

        <div>
            <!-- POST CONTENT START -->
                <h1>Post title</h1>
                <p>Content visible for all members</p>
            <!--members-only-->
                <p>Content visible for paid members only</p>
            <!-- POST CONTENT END -->
        </div>
    </body>
</html>
```

**Free members (paywall _added_):**
```html
<html>
    <body>
        <h1>Generated email header</h1>
        <p>Generated text</p>

        <div>
            <!-- POST CONTENT START -->
                <h1>Post title</h1>
                <p>Content visible for all members</p>
                <h2>Generated paywall here</h2>
                <a href="https://subscribe.com">Subscribe to read the full post</a>
            <!-- POST CONTENT END -->
        </div>
    </body>
</html>
```

### After this change:

**Serialize output:**
```html
<html>
    <body>
        <h1>Generated email header</h1>
        <p>Generated text</p>

        <div>
            <!-- POST CONTENT START -->
                <h1>Post title</h1>
                <p>Content visible for all members</p>
            <!--members-only-->
                <p>Content visible for paid members only</p>
             <!-- PAYWALL -->
                <h2>Generated paywall here</h2>
                <a href="https://subscribe.com/?tracked">Subscribe to read the full post</a>
            <!-- POST CONTENT END -->
        </div>
    </body>
</html>
```

To be modified later by  `renderEmailForSegment`:

**Paid members (paywall removed):**
```html
<html>
    <body>
        <h1>Generated email header</h1>
        <p>Generated text</p>

        <div>
            <!-- POST CONTENT START -->
                <h1>Post title</h1>
                <p>Content visible for all members</p>
            <!--members-only-->
                <p>Content visible for paid members only</p>
            <!-- POST CONTENT END -->
        </div>
    </body>
</html>
```

**Free members (members-only content removed):**
```html
<html>
    <body>
        <h1>Generated email header</h1>
        <p>Generated text</p>

        <div>
            <!-- POST CONTENT START -->
                <h1>Post title</h1>
                <p>Content visible for all members</p>
            <!-- PAYWALL -->
                <h2>Generated paywall here</h2>
                <a href="https://subscribe.com/?tracked">Subscribe to read the full post</a>
            <!-- POST CONTENT END -->
        </div>
    </body>
</html>
```
2022-09-16 10:08:12 +02:00
Kevin Ansfield
c240f7afa4
Added rendering of posts.lexical to posts.html when saving (#15416)
no issue

- added `@tryghost/kg-lexical-html-renderer` dependency
- added `lexical` lib following the same pattern as our `mobiledoc` lib
- updated the Post model's `onSaving` hook to generate the `html` value from `lexical` when present
2022-09-15 16:49:14 +01:00
Simon Backx
e9974d8cc0
🐛 Fixed feature image caption escaped twice in newsletters (#15417)
fixes https://github.com/TryGhost/Team/issues/1909

- The feature image caption is already escaped on the frontend
- Doing it again in the backend breaks the possibility to add links to the caption
- I checked and the `feature_image_alt` is not escaped in the frontend.
2022-09-15 17:07:10 +02:00
Simon Backx
699e67f4e4
Added email_track_clicks setting (#15409)
fixes https://github.com/TryGhost/Team/issues/1900
refs https://github.com/TryGhost/Team/issues/1901

- Defaults to the same value as the current email_track_opens setting for existing installations, otherwise defaults to true
- Had to use a custom migration because the `addSetting` helper doesn't support using an existing setting as current value
- Added a minimal UI to change the setting, but this still needs some design magic 🪄
- Link replacement is disabled if `email_track_clicks` is disabled. In the future we might consider to still do parial additions, such as source attribution and maybe redirects (to discuss).
2022-09-15 15:48:22 +02:00
Fabien "egg" O'Carroll
4726742673 Renamed redirects to custom-redirects
We're going to be adding more redirection logic into Ghost and it's
going to get confusing if we have names this generic. This makes it
clear which feature this service is related to.

Ideally in the future we can combine all of these into one redirects
service, but for now we will be running a specific service per feature
2022-09-14 13:24:17 -04:00
Kevin Ansfield
8cdd2e10b7
Added posts.lexical database field (#15397)
closes https://github.com/TryGhost/Team/issues/1884

- adds `post.lexical` ready for use by the lexical-powered editor re-write
- fulfils the same purpose as `posts.mobiledoc` so uses the same field properties
- added `lexical` to allowed formats in Post model so it won't be included by default in API responses meaning tests/snapshots don't need updating at present
2022-09-13 11:21:47 +01:00
Rishabh
4187f0da54 Updated staff service to trigger alerts via events
refs https://github.com/TryGhost/Team/issues/1865

- refactors staff service to listen to member and subscription events
- triggers email alerts based on events instead of directly calling the service
- removes staff service dependency for members api
2022-09-10 11:06:34 +05:30
Hannah Wolfe
04f3ac37d3 Removed defunct applyPublicRules code
closes: https://github.com/TryGhost/Toolbox/issues/369
refs: https://github.com/TryGhost/Toolbox/issues/229

- this code is defunct as we no longer accept a status parameter via the API for posts, pages, users or authors
2022-09-09 17:14:15 +01:00
Hannah Wolfe
b0234dd58e
Removed apiVersions from test urlUtils
refs: https://github.com/TryGhost/Toolbox/issues/229

- These properties were removed from urlUtils in 5.0 and no longer do anything
2022-09-09 13:32:30 +01:00
Ronald Langeveld
eb6534bd7f
Replaced all 'bio' references with 'expertise' for member comments. (#15359)
closes https://github.com/TryGhost/Team/issues/1772

- The user facing side of comments recently replaced `bio` with `expertise`.
- To remain consistent we replaced all the references of `bio` with `expertise` throughout the codebase.
- This includes a database column name changing migration, within the `members` table.
- Bumped up the comments-ui version to a new minor (0.10.x) as its a breaking change.
2022-09-09 10:14:49 +02:00
Simon Backx
4534b693e4
Added test that validates output HTML of email template (#15365)
refs https://github.com/TryGhost/Team/issues/1871

This commit adds a test to the serialize method of `post-emaiserializer`. It checks whether the generated email HTML is valid and standard HTML5 and that all properties are escaped.

To do this validation, I depend on the new `html-validate` dev dependency. Just parsing the HTML with a HTML parser is not enough to guarantee that the HTML is okay.

Apart from that this fixes:
- Removed the sanitizeHTML method and replaced it with normal HTML escaping. We don't want to allow any HTML in the escaped fields. Whereas `sanitizeHTML` still allows valid HTML, but we don't want that and want the same behaviour as on the site. E.g., a post with a title `All your need to know about the <br /> tag` should actually render the same title and non-html content, being `All your need to know about the &lt;br /&gt; tag`
- The file, nft and audio card didn't (always) escape the injected HTML fields (new version @tryghost/kg-default-cards) 
- `@tryghost/string` is bumped because it contains the new escapeHtml method
2022-09-08 10:11:01 +02:00
Daniel Lockyer
4a6f57b105
Merged v5.13.2 into main
v5.13.2
2022-09-06 16:45:52 +01:00
Fabien 'egg' O'Carroll
f7a58ecafc
🐛 Fixed OpenSea NFT OEmbeds (#15372)
refs https://github.com/TryGhost/Team/issues/1879

OpenSea updated their URL format for NFTs after adding support for Solana
which broke our regex, this updates to support the new format.
2022-09-06 11:29:35 -04:00
Naz
920a3aeb4c
Fixed adapter-related unit test
refs 37dd187fe6
refs c36575627d/ghost/core/core/server/data/importer/handlers/image.js (L16)

- The tests were failing because they were stubbing a "generic" adapter, instead of the one which the module under test was using (see referenced code to see what I mean)
2022-09-06 18:46:32 +08:00
Naz
c36575627d
Fixed unit test
refs 37dd187fe6

- The referenced commit lacked cleanup after module removal
2022-09-06 18:11:22 +08:00
Naz
a96a7340c0
Added JSDoc to adapter options resolver
refs https://github.com/TryGhost/Toolbox/issues/384

- Added jsdoc for intellisence/typechecking
- Cleaned up the naming of returned values to resemble the usecases a bit better
2022-09-06 17:51:57 +08:00
Naz
67df9a6105
Removed unused adapterType variable
refs https://github.com/TryGhost/Toolbox/issues/384

- The adapter manager can parse the adapter type internally from the "type:feature" syntax, so there's no need to pass it around.
2022-09-06 17:51:57 +08:00
Naz
1fc8c8d671
Added more explicit adapter config syntax
refs https://github.com/TryGhost/Toolbox/issues/384

- Existing adapter config was based on the notion there can only be one configuration per one adapter class. With adapter cache now allowing instantiating multiple adapter instances with the same base class it opened up a possibility to have shared configuration for a base class and then extend/override it in "feature" configurations (see tests in this commit for specific examples)
2022-09-06 17:51:57 +08:00
Simon Backx
2e85ae98be
🐛 Fixed sending emails from email domain that includes www subdomain (#15348)
fixes https://github.com/TryGhost/Team/issues/1855
fixes https://github.com/TryGhost/Team/issues/1866

This commit moves all duplicate methods to get the support email address to a single location. Also methods to get the default email domain are moved.

For the location, I initially wanted to put it at the settings service. But that service doesn't feel like the right place. Instead I created a new settings helpers service. This service takes the settingsCache, urlUtils and config and calculates some special 'calculated' settings based on those:

- Support email methods
- Stripe (active) keys / stripe connected (also removed some duplicate code that calculated the keys in a couple of places)
- All the calculated settings are moved to the settings helpers

I'm not 100% confident in whether this is the right place to put the helpers. Suggestions are welcome.
2022-09-02 16:57:59 +02:00
Daniel Lockyer
dd2bfb8c0e
Merged v5.12.4 into main
v5.12.4
2022-09-02 15:13:37 +01:00
Simon Backx
999b111fce
🐛 Fixed paid email preview stopped working in emails (#15356)
fixes https://github.com/TryGhost/Team/issues/1870

Disables email sanitization that was enabled earlier because this bug is more important and urgent.

The recently introduced email sanitzation removes HTML comments from the post html.
- This breaks the email paid preview, because it depends on the `<!--members-only-->` comment.
- Breaks the Outlook comments `<!--[if !mso !vml]-->`

This commit reverts this change.
2022-09-02 15:49:39 +02:00
Fabien 'egg' O'Carroll
e4cbb3d24d
Reset magic link rate limiting upon successful login (#15345)
refs https://github.com/TryGhost/Team/issues/1771

We don't have access to `req.brute.reset` due to the way the flow
works, we have one endpoint which sends an email with a magic link,
and another route which handles the login. We don't want to apply
brute force protection to both because our rate limiting is designed
for API requests not web page visits (which is how login is handled).

Because of this we require access to the underlying ExpressBrute
instance exposed by the spam-protection module, so that we can
perform the reset.
2022-09-01 08:54:14 -04:00
Naz
945ebd4806
Fixed ERR_NOCK_NO_MATCH warning during test runs
refs https://github.com/TryGhost/Toolbox/issues/389

- The e2e test suite log was full of ERR_NOCK_NO_MATCH warnings when the logging level was set to "warn". The cause of this warning was legit duplicated webhook trigger processing on test environment. Gah!
- The source of duplicate webhook processing was duplication of event handlers. Event handlers were registered multiple times for same event because of the singleton nature of the "common/events" module - it remains the same instance and is not cleaned up between reboots. The deeper issue of events module initialization should be solved separately, this slightly hacky approach fixes the problem now and highlights it to be tackled in the future.
2022-09-01 12:25:47 +08:00
Fabien 'egg' O'Carroll
21e473ff78
🐛 Fixed newsletters not rendering with non-HTML safe chars (#15331)
Co-authored-by: Kevin Ansfield <kevin@lookingsideways.co.uk>
2022-08-30 11:26:01 +01:00
Simon Backx
a8239bfa97
Added ENUM validation for member/subscription created events (#15312)
closes https://github.com/TryGhost/Team/issues/1842

- members_created_events: source + attribution_type
- members_subscription_created_events: attribution_type
- members_subscribe_events: source
2022-08-25 15:39:37 +02:00
Rishabh
effd5af615 Handled fetching staff users for email alerts
refs TryGhost/Team#1826

- adds a method on user model which fetches all eligible users for a type of email alert
- restricts users to active `Owner` and `Administrators` with setting turned on
2022-08-25 18:01:52 +05:30
Rishabh
326bb97d2c Enabled free trials via tiers and offers
refs https://github.com/TryGhost/Team/issues/1724
refs https://github.com/TryGhost/Team/issues/1726

- allows site owners to add a default free trial period to their tiers
- allows site owners to create custom offers that allow free trials on tiers
2022-08-24 19:24:31 +05:30
Rishabh Garg
9abfae2ddb
Switched off email alerts for subscription cancellation by default (#15304)
refs TryGhost/Team#1825

- all sites are expected to have cancellation alerts off by default
2022-08-24 18:54:00 +05:30
Rishabh Garg
c48c65cc88
Added member email alert notification columns for staff (#15276)
refs https://github.com/TryGhost/Team/issues/1825

- adds 3 new columns to users table for storing email alert preferences for member signups/cancellation
- adds column for new member signup alert
- adds column for paid subscription started alert
- adds column for paid subscription canceled alert
- Updated default fixtures and tests for new columns
2022-08-23 22:11:38 +05:30
Hannah Wolfe
809c1a6e08 🐛 Fixed error deleting post with comment replies
closes: https://github.com/TryGhost/Ghost/issues/15252

- comments are deleted when posts are deleted. Without cascade delete on parent_id, replies cannot be deleted
- this change means that deleting a post will delete all comments and replies without error
2022-08-19 15:49:58 +01:00