Commit Graph

292 Commits

Author SHA1 Message Date
Naz
831a76505c
Fixed root zip image/media/files copying during import
https://github.com/TryGhost/Toolbox/issues/523

- During import process of content files the files from the root directory were also copied over. This is causing chaos in the root of content folder with files that only needed for data import. For example, the csv files needed for Revue import were also copied over by "file importer" even though those do not belong to any content.
- Any content import files - images, media, files, should be in according folders in the imported zip file. The root files in the base zip directory are for data-related imports
2023-03-08 11:03:47 +08:00
Simon Backx
38de815d98
Removed old email flow (#16349)
fixes https://github.com/TryGhost/Team/issues/2611

The old email flow is no longer used since we introduced the email stability flow. This commit removes the related code and tests. The general test coverage decreased a bit as a result, because the old email flow probably had a high test coverage. The new flow is in separate packages, so it couldn't contribute to a higher test coverage (but it does have 100% unit test coverage).
2023-03-07 16:08:40 +01:00
Simon Backx
f50224f445
Improved network access and mocking in tests (#16371)
refs https://github.com/TryGhost/Team/issues/2667

Some tests still accessed the internet. Now network access is disabled
by default. This change also introduces two helper methods related to
networking (mocking Slack and Mailgun).

This fixes two unreliable tests:
- Staff service was accessing a Slack test API -> timeout possible
- MentionSendingService was trying to send webmentions for every post
publish/change -> possible timeouts and job issues
2023-03-07 13:20:28 +01:00
Sam Lord
472e52a536 Made URL class warn on duplicate URLs in the test suite
refs: https://github.com/TryGhost/Toolbox/issues/389

Instead of logging errors, this will warn when adding a duplicate URL in the test environment.

At the moment, this is happening a lot in the test suite. While we also need to fix the root cause of this so we're not erroring in the product, it's a massive amount of spam in the logs when running the test suite which could prevent us from finding other errors which are causing issues.
2023-03-03 18:25:53 +00:00
Steve Larson
3e18715caa added twitter embed tests
refs TryGhost/Team#2663
-added basic coverage for twitter embeds
2023-03-03 10:54:03 -06:00
Naz
a701724903
Renamed content file importer test
refs https://github.com/TryGhost/Toolbox/issues/523

- Test was not renamed after the "image" module changed it's name to "ContentFileImporter"
2023-03-02 17:59:36 +08:00
Naz
ab3959f3f2
Added document file support to the zip importer
refs https://github.com/TryGhost/Toolbox/issues/523

- When migrating or importing ZIP files into Ghost there's often a need to include document files.
- When document files are present in the imported zip file they are now copied across and processed along with the rest of import files: json, images, csvs, etc.
- The importer also searches for use of the document files in the imported "posts" substituting the links with local ones
- The document files importer recognizes media files inside of "files" or "content/files" folders present in the zip.
- The supported media file extensions are same as for file upload widget:
".pdf",".json",".jsonld",".odp",".ods",".odt",".ppt",".pptx",".rtf",".txt",".xls",".xlsx",".xml"

with following content-types:
"application/pdf", "application/json", "application/ld+json", "application/vnd.oasis.opendocument.presentation", "application/vnd.oasis.opendocument.spreadsheet", "application/vnd.oasis.opendocument.text", "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "application/rtf", "text/plain", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/xml", "application/atom+xml"
2023-03-02 17:54:19 +08:00
Naz
cd49992cd9
Added generic file import handler
refs https://github.com/TryGhost/Toolbox/issues/523
refs c2534e3c86/packages/mg-assetscraper/lib/AssetScraper.js (L14-L16)
refs https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types

- Importer needs to process and recognize document files like pdfs, presentations etc to be able to import them into sites file storage.
- The handler allows a new root directory "files" to place imported documents
- The handler adds validation and processing for following file extensions:
".pdf",
".json",
".jsonld",
".odp",
".ods",
".odt",
".ppt",
".pptx",
".rtf",
".txt",
".xls",
".xlsx",
".xml"
- With following content types:
"application/pdf",
"application/json",
"application/ld+json",
"application/vnd.oasis.opendocument.presentation",
"application/vnd.oasis.opendocument.spreadsheet",
"application/vnd.oasis.opendocument.text",
"application/vnd.ms-powerpoint",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"application/rtf",
"text/plain",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/xml",
"application/atom+xml"
2023-03-02 17:54:18 +08:00
Naz
2361669bb6
Added media file support to the zip importer
refs https://github.com/TryGhost/Toolbox/issues/523

- When migrating or importing ZIP files into Ghost there's often a need to include more than just post content and images.
- When media files are present in the imported zip file they are now copied across and processed along with the rest of import files: json, images, csvs, etc.
- The importer also searches for use of the media files in the imported "posts" substituting the links with local ones
- The media importer recognizes media files inside of "media" or "content/media" folders present in the zip. The supported media file extensions are same as for media upload widget:
".mp4", ".webm", ".ogv", ".mp3", ".wav", ".ogg", ".m4a"

with following content-types:
 "video/mp4", "video/webm", "video/ogg", "audio/mpeg", "audio/vnd.wav", "audio/wave", "audio/wav", "audio/x-wav", "audio/ogg", "audio/mp4", "audio/x-m4a"
2023-03-02 14:35:37 +08:00
Naz
49553e5942
Renamed "image" importer to generic ContentFileImporter
refs https://github.com/TryGhost/Toolbox/issues/523

- This is ground work before introducing a "media" content type importer
- Previous "image" file name was not describing well what the importer was capable of doing
2023-03-02 14:35:37 +08:00
Sam Lord
90ef8f008e Prevent error logs from occuring in Ghost unit test suite
refs: https://github.com/TryGhost/Toolbox/issues/389
2023-03-01 16:37:46 +00:00
Naz
eb8d9df923
Made image importer type dynamic
refs https://github.com/TryGhost/Toolbox/issues/523

- Having a dynamic importer type allows to reuse the image importer implementation for other file types e.g.: 'media'
2023-03-01 18:28:17 +08:00
Naz
edebe1571c
Extracted image store to constructor parameter
refs https://github.com/TryGhost/Toolbox/issues/523

- We need to be able to use different storage mechanisms when importing different types of content
- Having the storage passed in using constructor DI allows to have more flexible storage mechanism in the Images importer (soon to become a generic file importer)
2023-03-01 18:21:46 +08:00
Naz
4573d8b4b8
Refactored image importer to use class
refs https://github.com/TryGhost/Toolbox/issues/523

- The class syntax would allow swapping out the storage mechanism in the importer making it universal to use with other file types like media or generic files.
2023-03-01 18:10:39 +08:00
Naz
2bf98e288f
Removed unused module from test suite
refs https://github.com/TryGhost/Toolbox/issues/523
2023-03-01 18:10:39 +08:00
Naz
e14520115a
Extracted Image Importer test suite
refs https://github.com/TryGhost/Toolbox/issues/523
refs 3119a5cc4c

- The "index.test.js" is doing too much, has to be broken down to allow things to move into new packages
2023-03-01 16:48:38 +08:00
Daniel Lockyer
4c2ff0539d
Fixed tests for ImportManager audio types
refs c5a4ee89c9

- as of the referenced commit, the supported list of mime types has been
  updated
2023-03-01 09:14:09 +01:00
Naz
3119a5cc4c
Extracted ImageHandler test suite
refs https://github.com/TryGhost/Toolbox/issues/523

- The "importer/index.test.js" test suite is testing more than it should. ImageHandler test suite section is one of the examples of test cases that should live in a separate file.
- Having these tests in different files makes it easier to reason about coverage and extract to it's own packages.
2023-03-01 15:55:10 +08:00
Naz
ce5eea5707
Added media file handling to Ghost importer
refs https://github.com/TryGhost/Toolbox/issues/523

- When a zip file is imported into Ghost we need to recognize and process media files with following extensions:
".mp4",".webm", ".ogv", ".mp3", ".wav", ".ogg", ".m4a"
- The media files can come from a "media" or "content/media" folder inside of zip file
2023-03-01 15:55:10 +08:00
Naz
23e2fdde95
Added image importer test coverage
refs https://github.com/TryGhost/Toolbox/issues/523

- The test cases for "content" and "content/images" zip import file structure were missing.
2023-03-01 15:55:10 +08:00
monkey sees
838516efb0 🐛 Fixed Handlebars’ asset helper for SafeString input
closes https://github.com/TryGhost/Ghost/issues/16332

Passing `SafeString` input to `asset` helper was resulting in the
exception being thrown. This meant that we couldn’t combine `asset`
helper with other helpers which produce `SafeString` e.g. `concat`
helper for string concatenation.
2023-03-01 08:39:14 +01:00
Sam Lord
579ecd5b0b Prevent error logging in Urls tests from being output
refs: https://github.com/TryGhost/Toolbox/issues/389
2023-02-28 11:14:11 +00:00
Sam Lord
6512fc770d Prevent xmlprc tests from outputting errors for failure cases
refs: https://github.com/TryGhost/Toolbox/issues/389
2023-02-28 11:14:11 +00:00
Sam Lord
007adb6a33 Prevent tests from erroring when calling validate.init()
refs: https://github.com/TryGhost/Toolbox/issues/389

Calling validate always uses the cache system, so this commit makes sure that the cache system is always initialised correctly by the tests.
2023-02-28 11:14:11 +00:00
Daniel Lockyer
93e0898c12
Extracted version-match middleware to separate package
- this middlware is standalone and has 100% test coverage, therefore we
  can move it out to a separate package and remap the requires
  accordingly
2023-02-27 18:34:03 +01:00
Aileen Nowak
74a65f3b1c Simplyfied milestone event meta data
no issue

- Reduced the amount of diffeerent properties by not populating a `currentARR` and `currentMembers` fields, but use a `currentValue` instead.
- The type of milestone can still be determined by its `type` property, so we actually don't need two different props here
2023-02-23 17:21:20 +02:00
Simon Backx
3ded0bbee8
Added outbound link tagging setting (#16324)
no issue

Enable or disable outbound link tagging in both web posts and
newsletters.
2023-02-23 14:37:23 +01:00
Aileen Booker
e0331bbfcf
Added MilestoneCreatedEvent to staff service notifications (#16307)
refs
https://www.notion.so/ghost/Marketing-Milestone-email-campaigns-1d2c9dee3cfa4029863edb16092ad5c4?pvs=4

- Added MilestoneCreatedEvent subscription to staff-service incl. first
handling
- Logs information for now instead of actually sending an email
2023-02-23 11:20:13 +02:00
Aileen Booker
cf7d34d862
Added BookshelfMilestoneRepository implementation (#16305)
refs
https://www.notion.so/ghost/Marketing-Milestone-email-campaigns-1d2c9dee3cfa4029863edb16092ad5c4?pvs=4

This stores the received milestones in the database.
2023-02-22 15:53:29 +02:00
Aileen Booker
4556e9be88
Added milestone_notifications column (#16306)
refs
https://www.notion.so/ghost/Marketing-Milestone-email-campaigns-1d2c9dee3cfa4029863edb16092ad5c4?pvs=4

- created a migration for a new boolean column in users that would
determine if the staff user gets an email when a new milestone is
achieved.
2023-02-22 14:13:50 +02:00
Aileen Booker
32630c27cc
Added milestones database table (#16300)
refs
https://www.notion.so/ghost/Marketing-Milestone-email-campaigns-1d2c9dee3cfa4029863edb16092ad5c4?pvs=4

- added new `milestones` database table to be able to store created
milestones.
- updated schema and tests to match.
2023-02-22 10:46:43 +02:00
Naz
ad6097b695
Refactored post's extra-attributes to use options
refs https://github.com/TryGhost/Toolbox/issues/522

- Having simpler method signature makes it easier to use it in different context - needed for changes in public resource repository
- TLDR of the changes - reduced parameter 'frame.options' -> 'options'
2023-02-22 15:46:56 +08:00
Steve Larson
2d84b7d990
Upgraded got package from v9.6.0 to v11.8.6 (#16261)
Refs TryGhost/Team#2459
-upgraded got from v9.6.0 to v11.8.6 to support following redirects (and
other fixes)
-got v12+ requires ESM, so we do not want to upgrade further at this
time
-required changes to a few libraries that use externalRequests
-mention discovery service tests updated to test for follow redirects
2023-02-20 09:33:11 -06:00
Simon Backx
ec3f262ea4 Increased scheduling default test timeout 2023-02-17 13:29:07 +01:00
Aileen Booker
2f57e95a5d
Slack notifications service for Milestones behind flag (#16281)
refs
https://www.notion.so/ghost/Marketing-Milestone-email-campaigns-1d2c9dee3cfa4029863edb16092ad5c4?pvs=4

- Added a `slack-notifications` repository which handles sending Slack
messages to a URL as defined in our Ghost(Pro) config (also includes a
global switch to disable the feature if needed) and listens to
`MilestoneCreatedEvents`.
- Added a `slack-notification` service which listens to the events on
boot.
- In order to have access to further information such as the reason why
a Milestone email hasn't been sent, or the current ARR or Member value
as comparison to the achieved milestone, I added a `meta` object to the
`MilestoneCreatedEvent` which then gets accessible by the event
subscriber. This avoid doing further requests to the DB as we need to
have this information in relation to the event occurred.

---------

Co-authored-by: Fabien "egg" O'Carroll <fabien@allou.is>
2023-02-17 12:59:18 +02:00
Aileen Nowak
a400353881 Renamed milestone-emails to milestones
no issue

- The way we're going to implement milestones diverged from the original idea of handling email sending within the milestone-emails package, as we'll be sending events instead and will utilise the StaffService to listen to them and send the emails
- This renames the package as well as the service in core itself and all relevant tests
2023-02-15 10:43:05 +02:00
Ronald Langeveld
c651f5b10f
Added verified mention column (#16264)
refs https://github.com/TryGhost/Team/issues/2549

- Added `verified` column to mentions table
- Added a new migration
- Updated schema
- Updated integrity test
2023-02-14 15:46:07 +08:00
Kevin Ansfield
c489343831
Fixed saving and rendering of Lexical posts containing new cards
closes https://github.com/TryGhost/Team/issues/2558

- bumped `kg-lexical` packages so we're working with latest suite of default nodes and renderer
- added a `render()` method directly to our `lexicalLib` object
  - allows us to pass through all of Ghost's config for image transforms etc in one place rather than every time we want to render something
2023-02-13 16:35:34 +00:00
Daniel Lockyer
4bca725215
Added basic unit test for cache adapter module
- this helps improve our testing capabilities of the new cache adapters
2023-02-13 17:10:42 +01:00
Aileen Booker
6f0d1b0ff9
Added milestone email service behind alpha flag (#16241)
refs
https://www.notion.so/ghost/Marketing-Milestone-email-campaigns-1d2c9dee3cfa4029863edb16092ad5c4

Added milestone email service behind a flag. The service will currently
run on boot and is meant to be scheduled soon, which should happen in
the next step. For now it's protected behind the alpha flag.
2023-02-13 16:29:01 +02:00
Simon Backx
77032262c4
🐛 Fixed subscriptions visible as "Active" within Ghost Admin (#16255)
fixes https://github.com/TryGhost/Team/issues/2542 
fixes https://github.com/TryGhost/Team/issues/2543 
fixes https://github.com/TryGhost/Team/issues/2544

- Hides incomplete subscriptions
- Shows Past Due subscriptions
- Fixed UI issues with 3+ subscriptions
- Fixed missing complimentary subscription when one subscription was
incomplete/inactive
- Fixed sending a paid subscription started email for incomplete
subscriptions. This change also required us to actually send the email
when the incomplete subscription eventually becomes active. So the
introduction of a new `SubscriptionActivatedEvent` made sense/was
required (because sending a SubscriptionCreatedEvent again would cause
other issues).
2023-02-13 13:07:53 +01:00
Steve Larson
d20696805f
Added mentions deleted column (#16251)
refs https://github.com/TryGhost/Team/issues/2534

This is so that we can support soft deletes for Mentions.
We need to add the defaults to the model so that write continue to work.

Co-authored-by: Fabien "egg" O'Carroll <fabien@allou.is>
2023-02-09 16:19:07 +07:00
Ronald Langeveld
30dc2a8228
Added mention_notifications column (#16242)
refs https://github.com/TryGhost/Team/issues/2526

- created a migration for a new boolean column in users that would
determine if the staff user gets an email when the publication receive a
new mention.
2023-02-09 16:15:54 +08:00
Naz
9390f0953f
Fixed {{price}} helper to render empty instead of throwing
refs https://github.com/TryGhost/Toolbox/issues/497
refs fb7532bf5d

- We downgraded the 'GS090-NO-PRICE-DATA-CURRENCY-CONTEXT' rule in gscan to non-fatal, meaning Ghost should not be throwing an error but instead render an empty value for {{price}} helper when price data is empty.
- For example, a legacy syntax like this: '{{price currency=@price.currency}}' should not cause a page render error but return an empty price string.
- The pattern of returning an empty string instead of crashing is used in other helpers like {{img_url}} and and {{url}}
2023-01-31 21:01:19 +08:00
Ronald Langeveld
c77984e6ab
Added mentions permissions (#16200)
closes https://github.com/TryGhost/Team/issues/2420

- Added user roles and permissions for the mentions admin API.
- We only have a `browse` function for our current use case, accessible
by `administrator` and `admin integration`.
2023-01-31 16:40:44 +08:00
Simon Backx
8e66edee2b
🐛 Fixed storing original files for images (#16117)
fixes https://github.com/TryGhost/Team/issues/481

This change fixes an issue when multiple images with the same name are
uploaded in parallel. The current system does not guarantee that the
original filename is stored under NAME+`_o`, because the upload for the
original file and the resized file are happening in parallel.

Solution:
- Wait for the storage of the resized image (= the image without the _o
suffix) before storing the original file.
- When that is stored, use the generated file name of the stored image
to generate the filename with the _o suffix. This way, it will always
match and we don't risk both files to have a different number suffix.
We'll also set the `targetDir` argument when saving the file, to avoid
storing the original file in a different directory (when uploading a
file around midnight both files could be stored in 2023/01 and 2023/02).

Some extra optimisations needed with this fix:
- Previously when uploading image.jpg, while it already exists, it would
store two filenames on e.g., `image-3.jpg` and `image_o-3.jpg`. Note the
weird positioning of `_o`. This probably caused bugs when uploading
files named `image-3.jpg`, which would store the original in
`image-3_o.jpg`, but this original would never be used by the
handle-image-sizes middleware (it would look for `image_o-3.jpg`). This
fix would solve this weird naming issue, and make it more consistent.
But we need to make sure our middlewares (including handle-image-sizes)
will be able to handle both file locations to remain compatible with the
old format. This isn't additional work, because it would fix the old bug
too.
- Prevent uploading files that end with `_o`, e.g. by automatically
stripping that suffix from uploaded files. To prevent collisions.

Advantage(s):
- We keep the original file name, which is better for SEO.
- No changes required to the storage adapters.

Downside(s):
- The storage of both files will nog happen parallel any longer. But I
expect the performance implications to be minimal.
- Changes to the routing: normalize middleware is removed
2023-01-30 16:40:50 +01:00
Simon Backx
8f8ca481a6
Fixed configUtils and adapter cache issues in E2E tests (#16167)
no issue

There are a couple of issues with resetting the Ghost instance between
E2E test files:

These issues came to the surface because of new tests written in
https://github.com/TryGhost/Ghost/pull/16117

**1. configUtils.restore does not work correctly**
`config.reset()` is a callback based method. On top of that, it doesn't
really work reliably (https://github.com/indexzero/nconf/issues/93)

What kinda happens, is that you first call `config.reset` but
immediately after you correcty reset the config using the `config.set`
calls afterwards. But since `config.reset` is async, that reset will
happen after all those sets, and the end result is that it isn't reset
correctly.

This mainly caused issues in the new updated images tests, which were
updating the config `imageOptimization.contentImageSizes`, which is a
deeply nested config value. Maybe some references to objects are reused
in nconf that cause this issue?

Wrapping `config.reset()` in a promise does fix the issue.

**2. Adapters cache not reset between tests**
At the start of each test, we set `paths:contentPath` to a nice new
temporary directory. But if a previous test already requests a
localStorage adapter, that adapter would have been created and in the
constructor `paths:contentPath` would have been passed. That same
instance will be reused in the next test run. So it won't read the new
config again. To fix this, we need to reset the adapter instances
between E2E tests.

How was this visible? Test uploads were stored in the actual git
repository, and not in a temporary directory. When writing the new image
upload tests, this also resulted in unreliable test runs because some
image names were already taken (from previous test runs).

**3. Old 2E2 test Ghost server not stopped**
Sometimes we still need access to the frontend test server using
`getAgentsWithFrontend`. But that does start a new Ghost server which is
actually listening for HTTP traffic. This could result in a fatal error
in tests because the port is already in use. The issue is that old E2E
tests also start a HTTP server, but they don't stop the server. When you
used the old `startGhost` util, it would check if a server was already
running and stop it first. The new `getAgentsWithFrontend` now also has
the same functionality to fix that issue.
2023-01-30 14:06:20 +01:00
Rishabh Garg
a81620e37d
🐛 Fixed invalid expiry for member tier subscriptions (#16174)
refs https://github.com/TryGhost/Team/issues/2476

When upgrading from a Complimentary subscription with an expiry, to a paid Subscription of the same Tier, the Member was eventually losing access to the Tier when the complimentary subscription expires as the `expiry_at` on the mapping was not removed. This change fixes the code by setting expiry as null when a member upgrades their subscription to paid. This also adds 2 migrations to fix any side-effects on existing sites -

- Removed invalid expiry tier expiry date for paid members
- Restored missing tier mapping for paid members
2023-01-25 13:59:43 +05:30
Fabien "egg" O'Carroll
169eb6046e Fixed RoutingService checks for resource existence
We were incorrectly handling a "no resource found" return value from the
ResourceService, instead of an object with `null` values, we were expecting a
`null` value - so we were considering all URL's to be pointing toward a
resource.
2023-01-24 18:00:52 +07:00
Fabien "egg" O'Carroll
9df131ee5a Checked for existence of page via a network request
refs https://github.com/TryGhost/Team/issues/2466

Now that we're checking for resources at the URL and rejecting if
there isn't one found, we want to make sure that we can handle pages
which are not a resource.

The idea here is to make a HEAD request to determine whether or not
the page exists. We don't need the full response so HEAD saves us some
bandwidth and we allow both 2xx and 3xx status codes because Ghost has
redirects to add missing trailing slashes, which may not be present in
the URL we're passed.
2023-01-24 16:17:40 +07:00
Fabien "egg" O'Carroll
919d0a80c0 Checked for existence of a resource to determine page existence
refs https://github.com/TryGhost/Team/issues/2466

The existing implementation was a very basic check to get us to the
first milestone. By checking if the page points to a resource we can
know for sure the URL exists on the site.
2023-01-24 16:17:40 +07:00
Naz
62e3caba2c
Fixed route update error on attach/detach events
refs https://github.com/TryGhost/Toolbox/issues/503

- There was an error thrown due to empty "model._changed" field
- When attached or detached events (e.g. tag.attached) are sent through, their models do not contain any _changed properties. This was taken into account when checking for route related resource changes
2023-01-24 12:29:09 +08:00
Fabien "egg" O'Carroll
182e0b831d Implemented and tested ResourceService as separate class
refs https://github.com/TryGhost/Team/issues/2465

This code is still in the Ghost package for now as it's essentially glue code.
2023-01-23 18:34:52 +07:00
Fabien "egg" O'Carroll
f746f223cd Implemented and tested RoutingService as separate class
refs https://github.com/TryGhost/Team/issues/2466

This code is still in the Ghost package for now as it's essentially glue code.
2023-01-23 18:34:52 +07:00
Sagar Gupta
bba4743739
Removed bluebird dependency from unit tests in core (#16096)
refs https://github.com/TryGhost/Ghost/issues/14882

- Replaced `new Promise.reject()` / `new Promise.resolve()` with the
static methods `Promise.reject` / `Promise/resolve` from native promises
- Replaced `Promise.delay()` with a promisified `setTimeout()`
2023-01-23 11:23:48 +00:00
Naz
2a01dd0481
Added test coverage for sitemap base generator
refs https://github.com/TryGhost/Toolbox/issues/503

- The "updateURL" method was not covered during implementation. Covering the gap with basic tests for the "updateURL" method
2023-01-23 16:33:41 +08:00
Naz
4aacd50fee
Added coverage for URLResourceUpdatedEvent
refs https://github.com/TryGhost/Toolbox/issues/503

- The listener was not covered during quick and dirty implementation. While in the area did some cleanup to the sitemap manager test
- One of the problems I've stumbled upon when adding a test is having multiple instances of SiteManager in the test, which in turn created multiple "subscribe" events and repeat handle executions. Fixed it by having just one site manager instance (a singleton) as that's the pattern that used in main codebase
2023-01-23 16:33:41 +08:00
Naz
ccb485110b
Short-circuited resource URL regeneration when it's not necessary
refs https://github.com/TryGhost/Toolbox/issues/503

- Full URL regeneration process was happening even when only unrelated to URL generation fields were updated (e.g. 'plaintext' change in post does not affect the URL of the post). Stopping the  "resource updated" event processing early circumvents full url regeneration inside of DynamicRouting, which can be quite heavy depending on routing configuration
- The URLResourceUpdatedEvent is supposed to be emmited whenever there's an update to the resource already associated with the URL and no url-affecting fields were touched.
2023-01-23 16:33:41 +08:00
Simon Backx
e879406659
Added outbound link tagging setting (#16146)
fixes https://github.com/TryGhost/Team/issues/2432
    
Adds outbound_link_tagging setting (enabled by default and behind
feature flag). If the feature flag is enabled, and the setting is
disabled, we won't add ?ref to links in emails.
    
This includes new E2E tests for email click tracking, which were also
extended to check outbound link tagging (for both MEGA and the new email
stability flow).

Also fixes a test fixture for the comments_enabled setting.
2023-01-20 13:41:36 +01:00
Ronald Langeveld
3061fb2b3b
Added mentions database table (#16150)
closes https://github.com/TryGhost/Team/issues/2417

- added new `mentions` database table to be able to store incoming webmentions.
- updated schema and tests to match.
2023-01-20 19:08:07 +08:00
Fabien "egg" O'Carroll
d0d45d45bc Refactored OEmbed service into a proper service
This allows us to share the implementation with other parts of the codebase, the
specific usecase here being fetching the metadata from webmention sources, for
display in the mentions UI, which will be borrowing a lot of stuff from the
bookmark card.
2023-01-19 18:41:49 +07:00
Daniel Lockyer
5b2fc983c6
Added email snapshots to settings BREAD service test
refs https://github.com/TryGhost/Toolbox/issues/499

- switching to email snapshots allows us to track more of our output to check for regresssions
2023-01-18 14:19:27 +01:00
Daniel Lockyer
9ba251238a Added Content-Version header to all API requests
refs https://github.com/TryGhost/Team/issues/2400

- we've deemed it useful to start to return `Content-Version` for all
  API requests, because it becomes useful to know which version of Ghost
  a response has come from in logs
- this should also help us detect Admin<->Ghost API mismatches, which
  was the cause of a bug recently (ref'd issue)
2023-01-18 08:38:07 +01:00
Simon Backx
34d4e5c8d0
Added logging to webmention endpoint (#16137)
closes https://github.com/TryGhost/Team/issues/2424

Adds the new webmention endpoint, responds with the correct statuscode
and empty body at `https://site.ghost/webmentions/receive/`.

Also updates the head link tag to the new endpoint location. We don't
use /webmention because that could conflict with post slugs.
2023-01-17 14:26:43 +01:00
Fabien 'egg' O'Carroll
a30bbd5c69
Added webmention endpoint discovery link to ghost_head (#16126)
We've wrapped both changes in a try/catch to make sure this has no
adverse affects. The endpoint currently doesn't exist - we're only
adding this to get an idea of how much traffic we'll expect to see.

Long term we'll want to read the endpoint from the webmention service.
2023-01-16 12:32:04 +07:00
Naz
c2b18f0c87
🔥 Removed support for {{lang}} helper
refs https://github.com/TryGhost/Toolbox/issues/497
refs https://github.com/TryGhost/Toolbox/issues/406

- Removes {{lang}} helper which has been completely deprecated since Ghost 5.0. When using the helper in themes with 5.x backend the output will be empty
2023-01-13 13:12:53 +07:00
Simon Backx
7b3712a15b
Added visible theme errors in admin (#16081)
refs https://github.com/TryGhost/Team/issues/2393

- During boot and loading the active theme, we now cache the result of
the gscan validation. Cache configuration can happen in
`adapters.cache.gscan`
- We now also return non-fatal errors when activating or adding a theme.
- When the `themeErrorsNotification` feature flag is on, we fetch the
active theme (which includes the validation information) when loading
admin
- If the currently active theme has errors, we show an error
notification that can open the error modal
- Added a new endpoint: `/ghost/api/admin/themes/active/` that returns
the result of the last gscan validation of the active theme. If no cache
is available, it will run a new gscan validation.
- Added new permissions for the active action/endpoint (author, editor,
administrator)
2023-01-06 13:44:27 +01:00
Naz
3e209218d7
Made resource mismatch error more specific
refs https://github.com/TryGhost/Toolbox/issues/497

- During gscan fatal error downgrade to non-fatal some of the deprecated helpers were a bit vague to debug with no information on which exact "resource" was invalid
- Added resource name to the log for clarity. Should make life easier when debugging potential get helper misuses
2023-01-06 18:05:07 +07:00
Simon Backx
913ad18b71
Added DomainEvents.allSettled utility method (#16075)
no issue

With the increased usage of DomainEvents, it gets harder to build
reliable tests without having to resort to timeouts. This utility method
allows us to wait for all events to be processed before continuing with
the test.

This change should speed up tests and make them more reliable.

It only adds extra code when running tests and shouldn't impact
production.
2023-01-04 14:30:35 +01:00
Fabien 'egg' O'Carroll
50e99e013c
Added migrations to drop and recreate the suppressions table (#16070)
There are currently two issues with the suppressions table:
  - We have some incorrect rows
  - We have missing UNIQUE constraints

We want to completely wipe the tables and start fresh, as well as make
sure that the UNIQUE constraints are added, so we drop the table
completely, and then re-add it, which should result in an empty
suppressions table with all expected constraints.

We've also renamed the `email_address` column to `email` to match our
`users` & `members` tables
2023-01-04 17:26:57 +07:00
Simon Backx
819d0d884c
Improved email verification required checks (#16060)
fixes https://github.com/TryGhost/Team/issues/2366
refs https://ghost.slack.com/archives/C02G9E68C/p1670232405014209

Probem described in issue.

In the old MEGA flow:
- The `email_verification_required` check is now repeated inside the job

In the new email service flow:
- The `email_verification_required` is now checked (didn't happen
before)
- When generating the email batch recipients, we only include members
that were created before the email was created. That way it is
impossible to avoid limit checks by inserting new members between
creating an email and sending an email.
- We don't need to repeat the check inside the job because of the above
changes

Improved handling of large imports:
- When checking `email_verification_required`, we now also check if the
import threshold is reached (a new method is introduced in
vertificationTrigger specifically for this usage). If it is, we start
the verification progress. This is required for long running imports
that only check the verification threshold at the very end.
- This change increases the concurrency of fastq to 3 (refs
https://ghost.slack.com/archives/C02G9E68C/p1670232405014209). So when
running a long import, it is now possible to send emails without having
to wait for the import. Above change makes sure it is not possible to
get around the verification limits.

Refactoring:
- Removed the need to use `updateVerificationTrigger` by making
thresholds getters instead of fixed variables.
- Improved awaiting of members import job in regression test
2023-01-04 11:22:12 +01:00
Simon Backx
789e2c96c0
🐛 Fixed SingleUseTokens being cleared on boot (#15999)
fixes https://github.com/TryGhost/Team/issues/1996

**Issue**
Our Magic links are valid for 24 hours. After first usage, the token
lives for a further 10 minutes, so that in the case of email servers or
clients that "visit" links, the token can still be used.

The implementation of the 10 minute window uses setTimeout, meaning if
the process is interrupted, the 10 minute window is ignored completely,
and the token will continue to live for the remainder of it's 24 hour
validity period. To prevent that, the tokens are cleared on boot at the
moment.

**Solution**

To remove the boot clearing logic, we need to make sure the tokens are
only valid for 10 minutes after first use even during restarts.

This commit adds 3 new fields to the SingleUseToken model:
- updated_at: for storing the last time the token was changed/used). Not
really used atm.
- first_used_at: for storing the first time the token was used
- used_count: for storing the number of times the token has been used

Using these fields:
- A token can only be used 3 times
- A token is only valid for 10 minutes after first use, even if the
server restarts in between
- A token is only valid for 24 hours after creation (not changed)

We now also delete expired tokens in a separate job instead of on boot /
in a timeout.
2023-01-04 09:49:39 +01:00
Simon Backx
803bb18b8d Improved unit test coverage for the output mappers
no issue

Increases the unit test coverage to a bit above 60% to increase margin
2023-01-03 15:58:31 +01:00
Hannah Wolfe
5f90baf6fe
Added Revue Importer (#16012)
refs: https://www.getrevue.co/app/offboard

- Revue is stopping all paid subscriptions on 20th Dec, and shutting down on Jan 18th.
- This update allows Ghost to accept and handle the zip file Revue are providing as an export in Labs > Importer
- It will import posts (as best as we can with the data provided) and subscribers as free members
- At present it doesn't import paid subscribers, as we don't have that info, but you can disconnect Revue from your Stripe account to prevent all your subscriptions being cancelled & there's the option this can be fixed later
- There will be further updates to polish up this tooling - this is just a first pass to try to get something in people's hands

Co-authored-by: Paul Davis <PaulAdamDavis@users.noreply.github.com>
2022-12-15 17:22:54 +00:00
Simon Backx
94e85dc09e
Reduced webhook calls when updating last_seen_at for email opens (#16008)
refs https://ghost.slack.com/archives/C02G9E68C/p1670960248186789

This reverts a change that was made here:

f4fdb4fa6c (r93071549),
but it still moved the original code to a new location in the
LastSeenAtUpdater

It includes a new E2E test to make sure timezones are supported
correctly.

- By not using Bookshelf, we no longer fire webhook calls
- By not using the member repository, we don't fetch and update the
member model and the labels relation in a forUpdate transaction, which
caused deadlock issues on the labels/members_labels tables which were
hard to resolve. Until now I was unable to find the other conflicting
transaction that caused this deadlock. Moving to raw knex (instead of
Bookshelf) and only updating the last_updated_at column should remove
the deadlock issue.

This removed the test for the email service wrapper, since it started
failing for an unknown reason and the test didn't make much sense (was
added earlier only to bump test threshold).
2022-12-14 17:50:42 +01:00
Hannah Wolfe
270f288c48 Added a timeout to the get helper
- The get helper can sometimes take a long time, and in themes that have many get helpers, the request can take far too long to respond
- This adds a timeout to the get helper, so that the page render doesn't block forever
- This won't abort the request to the DB, but instead just means the page will render sooner, and without the get block
2022-12-14 15:35:07 +00:00
Rishabh
ce45571dc0 Updated email faqs in portal to show sender email address
refs https://github.com/TryGhost/Team/issues/2348

- updates email faqs to show the sender email from newsletter data
2022-12-12 15:09:32 +05:30
Daniel Lockyer
16f3ba573b
Updated ghost_head snapshots
refs de97d90cf9

- this should have been updated when I deleted some extraneous config
  that was lurking in the testing config files
2022-12-07 10:24:44 +07:00
Naz
e170f293e3
Extracted sleep method to e2e framework module
no issue

- The sleep method has been used in 8 modules reimplementing the same thing over and over again. It's usually a sign of async event processing outside of the request/response loop. It's good to have a single point of implementation for a "hack" like this, so we could track it easier and address the even processing delay in a more optimal way centrally if it ever becomes a bottleneck
2022-12-05 17:26:29 +07:00
Fabien "egg" O'Carroll
c0e91c73d3 Added unique constraint to email_spam_complaint_events table
We can fetch the same event multiple times from Mailgun so we need to
be able to protect against inserting duplicate events in the
database. This will allow us to catch duplicate errors on insert when
handling complaint events.
2022-12-01 17:27:02 +07:00
Kevin Ansfield
457c672c6a
Added URL transform for image cards in Lexical documents (#15890)
refs https://github.com/TryGhost/Team/issues/2225

- updated the `formatOnWrite` transform map for posts to include the new `nodes` and `transformMap` options used by `urlUtils` for transforming node payload data
- added `nodes` to the `lexicalLib` module that pulls in our default nodes to be passed in to the URL transform utilities
- added `urlTransformMap` to the `lexicalLib` module that maps transform type and data type to URL transform utility functions that accept a single URL argument
2022-11-29 16:57:01 +00:00
Fabien "egg" O'Carroll
ba5b8ea33d Added email_spam_complaint_events table and model
refs https://github.com/TryGhost/Team/issues/2318

As with our other events, we've disabled destroy and edit static methods
on the bookshelf model.
2022-11-29 18:13:12 +07:00
Fabien "egg" O'Carroll
83be54af42 Added suppressions table and model
refs https://github.com/TryGhost/Team/issues/2317

This table is used for persisting the email suppression list.
We don't have a member_id column because emails, not members are suppressed.
2022-11-29 18:12:24 +07:00
Simon Backx
f5045b9bf7
Added email renderer implementation draft (#15877)
fixes https://github.com/TryGhost/Team/issues/2308

- Still has some missing pieces, but mostly works.
- Uses new handlebars template for emails
- When sending emails with the new email stability flag enabled, one
test email is now sent via the default smtp ghost mailer.
2022-11-29 11:27:17 +01:00
Rishabh
64ac47f4ef Added table to store email recipient failures
refs https://github.com/TryGhost/Team/issues/2291

When sending out mails to individual recipients, its possible that recipient gets a temporary or permanent failure for receiving the mail. Temporary failures can generally get resolved after a bit when the recipient’s mail server accepts the email, unlike permanent failures. For both customer visibility and easier debugging on what went wrong while delivering to a particular recipient, we’ll store the permanent/temporary failure for a recipient.

- migration adds a new table that stores the failure information for the recipients
2022-11-29 15:19:36 +05:30
Hannah Wolfe
62cd52ff98 Improved Sentry server side error reporting
refs: https://github.com/TryGhost/Team/issues/1121
refs: 54574025e0

- The previous change to fall back to a generic error on the server side is resulting in lots of much less useful Sentry reports
- For unexpected errors, change what's sent to Sentry back to context
- This is done by adding a specific code, so we don't have to match on a string that might change
- Also add the error type, id, code & statusCode as tags to the events - these are searchable structured data
- Adding code as a tag also makes it possible to find all errors that showed the generic message
2022-11-23 12:37:24 +00:00
Hannah Wolfe
36b80f2dda Updated sentry to use @tryghost/version
- As demonstrated by my comments in the boot file, I thought sentry was already depending on the version package
- IMO it's undesirable to require package.json directly esp when we have a tool setup and ready for tis
- Added a bunch of tests to show that Sentry does roughly what we think
2022-11-23 12:37:24 +00:00
Elena Baidakova
8d9d22e5a7
Added member API for removing email from suppression list (#15867)
closes TryGhost/Team#2306
2022-11-23 14:41:00 +04:00
Simon Backx
4b4592630f
Added new email batch sending service (#15865)
fixes https://github.com/TryGhost/Team/issues/2284

New batch sending flow (still WIP). Logs the sent emails instead of actually sending them. Unit tests are coming in later commits.
2022-11-23 11:33:44 +01:00
Rishabh
5780fc2a93 Added new source and source type columns to emails table
refs https://github.com/TryGhost/Team/issues/2280

We are moving away from storing html and plaintext on email and instead will store the email data in source and source_type columns which allows us to store the email in other formats like mobiledoc and lexical. Storing in those formats allows greater flexibility for later html generation

- adds new `source` column that stores `mobiledoc`/`lexical`/`html` data for a newsletter
- adds new `source_type` column that stores one of `mobiledoc`/`lexical`/`html` to identify type of source
2022-11-23 15:04:11 +05:30
Rishabh Garg
d3267dd5b0
Added columns to store error information for email batches (#15859)
closes https://github.com/TryGhost/Team/issues/2290

Currently, if the whole batch of email fails to send we don’t capture
any errors directly tied to the batch. This makes it hard to debug which
and why a batch failed when debugging email errors. Going forward we'll
store the error information for a failing email batch directly that
allows easier debugging for batch.

- `error_status_code` : Captures statusCode returned by Mailgun,
available in error.status from the example batch error
- `error_message` : Captures short error message from Mailgun and
status, available in context object of batch error
- `error_data` : Captures while whole error json for a batch. As
mentioned in pitch, this will be huge data and we’ll figure out long
term how to best use this.
2022-11-23 13:13:49 +05:30
Sam Lord
fc291240d5 Updated importer test to use new object return format
no issue
2022-11-17 14:40:24 +00:00
Sodbileg Gansukh
78bff39c23
Update the cover image in default fixtures (#15817)
- updated the cover image to be simpler
- made the change in text fixtures as well, just to keep the fixtures in sync

Co-authored-by: Hannah Wolfe <github.erisds@gmail.com>
2022-11-15 21:19:50 +00:00
Rishabh
d4c3f86ce0 Cleaned up old member activity code usage
refs https://github.com/TryGhost/Team/issues/2216

The `membersActivity` flag was an alpha feature to test the first versions of member analytics, and is no longer active or in use. This change removes the remaining pieces of code that are setup behind that flag and are no longer in use or accessible.
2022-11-14 10:44:10 +05:30
Simon Backx
7cefd4f70b
Updated ghost head test to ignore Portal/Search version (#15777)
fixes https://github.com/TryGhost/Team/issues/2152

When updating the Portal of Search version, the snapshots will now
remain the same.
2022-11-07 15:09:26 +01:00
Kevin Ansfield
6a573d4511
Added lexical post support to email renderer (#15767)
closes https://github.com/TryGhost/Team/issues/2207

- adds conditional to the post email serializer to switch between
`mobiledocLib` and `lexicalLib` depending on which format the post
contains
2022-11-04 11:19:40 +00:00
Daniel Lockyer
c32a013087
Merged v5.22.5 into main
v5.22.5
2022-11-04 13:05:33 +07:00
Fabien "egg" O'Carroll
5a1364e46d 🐛 Fixed importer importing invalid Tier pricing data
closes https://github.com/TryGhost/Team/issues/2211

We were allowing paid Tiers to be imported with non-integer prices which was
causing the Admin to be bricked when attempting to load them. This adds some
validation to the price data of Tiers.
2022-11-04 11:27:15 +07:00
Naz
ac46c2f2e9
Fixed CORS vary header modification
refs https://github.com/TryGhost/Toolbox/issues/461

- The 'vary' header with 'Origin' value should only be set when an OPTIONS header is processed. Otherwise we are prone to leaking the vary header modification to further down in the request pipeline
2022-11-03 11:16:13 +08:00
Naz
9b2e36e4fb
Fixed CORS middleware unit test
refs https://github.com/TryGhost/Toolbox/issues/461

- The unit test was never using the "OPTIONS" request method, which did not actually trigger the full logic of the "cors" module used under the hood.
- Using the correct request method triggers all the right pathways and tests the state that's closer to the real world - for example the response does get "ended" instead of calling the "next" middleware.
2022-11-03 11:16:13 +08:00