no issue
When switching the oembed service to async/await the error handling was not correctly refactored. `this.errorHandler(url)` was returning a curried function so it could be used as `.catch(this.errorHandler(url))` but that's not how it's being used after the async/await change meaning we were returning a function rather than the result of that function.
- `this.errorHandler(url)` is now only used in one place where `url` is available so removed the method and moved the body of the curried function inline into the `catch` handler
- added a message to the logged error so it's more clear what the log refers to
no issue
- `startsWith` method is way easier to read and understand. also, **probably** has better performance comparing to building up a regexp and then matching
refs https://github.com/TryGhost/Toolbox/issues/135
- When instantiating new Urls/Resources object in the UrlService's init on every test suite start it was loosing track of past events (softReset wasn't doing the cleanup properly). Not initializing new classes "fixes" the problem partially, by not loosing track of those event listeners. The real fix should be proper even listener cleanup on every soft reset!
refs https://github.com/TryGhost/Toolbox/issues/135
- Allows to turn off overwriting urls/resources JSON file caches on testing environment. This is needed to have predictable state when running multiple test suites that stop the Ghost process and try to persiste URL cache.
refs https://github.com/TryGhost/Toolbox/issues/135
- This extracts the file storage knowledge out of the URL Service an allows to have optional features based on the environment - for example turning off writing cache for when running tests
refs https://github.com/TryGhost/Toolbox/issues/135
- To be able to reliably start ghost instance without a frontend the process needs access to urls/resources caches
- Storing the configuration in "paths" for now as there's no better place for it untill we are able to mock the content folder in pre-boot
refs https://github.com/TryGhost/Toolbox/issues/135
- These flags are meant to control initialization of sections of the boot sequence depending on the needs - with or without bakend (API)/frontend (public handlebars site)
- Ideally these flags should not be passed deep into the components, and if the are (like in the web/parent/app case) it's a smell that we need to move things up into the boot process!
refs https://github.com/TryGhost/Toolbox/issues/136
- `cheerio` isn't needed during the boot but it takes time and memory to
load the library
- this commit moves `cheerio` requires later into the code to when they
are needed
no issue
- if we encounter an unexpected error whilst fetching embed details we return a generic validation error so we're not leaking any details about the URL that is being hit, however that meant the error logs were only showing validation errors making debugging difficult
- added explicit logging of the unexpected error before throwing the generic validation error
refs https://github.com/TryGhost/Team/issues/1211
Added ?format=json to the URL in an attempt to mitigate any issues with
weird caching and receiving HTML rather than JSON.
Used `type` in place of `card_type` to closer follow how the bookmark
card/embed works.
Removed the html & width/heihgt properties which are not needed at all.
refs https://github.com/TryGhost/Team/issues/1217
- moved top-level `tenorApiKey` to `tenor:apiKey` and added `tenor:contentFilter`
- added base config to `defaults.json`
- updated `public-config.js` and API output serializer to use the new top-level `tenor` key
refs https://github.com/TryGhost/Toolbox/issues/127
- New instances or Urls and Resources during init were messing up test suites without an obvious solution. Moved them to only be triggered when the cache is present.
- Note the e2e-frontend tests are failing if thie initialization happens every time when init is called. There seems to be some reliance on Resources being the same intsance between "softReset" which seems wrong, but wasn't able to track it down definitevely
refs https://github.com/TryGhost/Toolbox/issues/127
- The resource cache is needed to have quick and reproducible state of the resouces tied to the urls instead of waiting for the db queries to finish.
- Allows to use UrlService without any database connection at all - useful for unit testing
- At the moment there's no way to see in the logs when the URL Service finally finishes
- This is the moment when Ghost stops serving 503s
- Adding this log line so it's clear to see, which migh be useful whilst were refactorising
refs https://github.com/TryGhost/Toolbox/issues/127
- The "withUrlOptions" is used internally in the constructor by the frontend's routers. To avoid passing around a whole function from the frontend routers duplicated the functionality from there.
refs 5a62253466
- The UrlService was relying on a "hidden" identifier field that was passed along with a router object. Now it's passed as an explicit parameter from the "frontend" to the backend's UrlService
refs https://github.com/TryGhost/Toolbox/issues/127
- Passing around whole instance of a frontend router was an overkill when there are only 3 static pieces of information that needed to be loaded. Extracting the router out makes the UrlGenerator way more readable, tests slimer, and the memory footpring of the process should be slightly lighter
- The toString overloading didn't make sense at the time of this refactor, maybe if there's a concrete usecase we could resurect it in a form of passing in a router's name or something.
refs https://github.com/TryGhost/Toolbox/issues/127
- This is an effor t to define a precise set of data needed for the UrlGenerator to function, which should help with decoupling it from the frontend routes
- This is almost the last piece to free us up from the massive "router" object that has been passed around
refs https://github.com/TryGhost/Toolbox/issues/127
- This is an effor t to define a precise set of data needed for the UrlGenerator to function, which should help with decoupling it from the frontend routes
refs https://github.com/TryGhost/Toolbox/issues/127
- This is an effor t to define a precise set of data needed for the UrlGenerator to function, which should help with decoupling it from the frontend routes
refs https://github.com/TryGhost/Team/issues/1211
Instead of rendering the HTML as an embed - we will send back the
necessary data. This will allow us to keep all the knowledge of HTML
structure in the Koenig repository.
refs https://github.com/TryGhost/Toolbox/issues/125
- The url loader is not fully working and is in very experimental mode. The aim is to ship this version to allow other team members to play with the feature in limited use-cases like testing evnironment
refs https://github.com/TryGhost/Toolbox/issues/116
- This should allow testing in a bit easier manner and would place the file into a more suitable directory
- ideally we'd put an alfa flag bahind this new "cached routes" feature to have less consequences to deal with if we have to back out
refs https://github.com/TryGhost/Toolbox/issues/116
- This is a PoC to check out how viable this approach is and if it's worth merging into main as a very quick win
- The `urls.json` is in a bad place right now should probably live in a data folder
refs https://github.com/TryGhost/Toolbox/issues/125
- Config initialization for the URL Resouces is a separate stage which doesn't have to be bundled along with resouce fetching method
- It gives even more flexibility when composing different ways to get the "resources" loaded into memory: right now it's from the DB but could come from a cache
refs https://github.com/TryGhost/Toolbox/issues/125
- The "init" method pattern is not used across the codebase and it's pretty standard to start the service in this way. Previous description was outdated and misguiding
refs https://github.com/TryGhost/Toolbox/issues/125
- The "fetchResources" method did way to many things extracted event listener setup logic to a separate method
- This allows to call out these stages as needed if we retreive resources separately from a cache of some sort and don't need to wait for the database response
refs https://github.com/TryGhost/Toolbox/issues/125
- The "fetchResources" is only used from one place and does way to many things at once:
- Fetches resources from the DB-
- Hooks up event listeners
- Starts the queue
- These are three different things, and should be three different methods ideally
refs https://github.com/TryGhost/Team/issues/1217
- add `tenorApiKey` to `publicConfig.config()
- update canary config endpoint output serializer to include `tenorApiKey` when the `gifsCard` labs flag is enabled
refs https://github.com/TryGhost/Team/issues/1211
This adds the initial custom OEmbed provider for OpenSea NFT's - we're
using the new custom provider functionality so that we can easily change
the logic here without affecting the core functionality.
refs https://github.com/TryGhost/Team/issues/1211
In order to override the default OEmbeds for OpenSea NFT's we need a way
to provide out own OEmbed data. We will want this in future too for
custom Twitter embeds, so this has been built in a way which allows
extension.
refs https://github.com/TryGhost/Team/issues/1212
This now emits the event when the service is reconfigured, rather than
when we issue the reconfigure command, which causes the event and the
action to be run in the wrong order. This would then cause knock on effects
of having the database in an undefined state - with stripe data in not linked
to the current Stripe account.
refs https://github.com/TryGhost/Toolbox/issues/95
- The ThemeStorage was never supposed to inherit image specific mehods. The LocalStorageBase is all it needs, might be even too much
- Look mum no saveRaw!
closes https://github.com/TryGhost/Toolbox/issues/111
- Just like with invalid JSON redirects files we should return a BadRequestError instead of throwing a generic 500 when the redirects.yaml file fails parsing
refs https://github.com/TryGhost/Team/issues/1115
This feature is now GA, and the flag has been hardcoded to `true`, here we clean up the
remaining references as they're no longer needed.
refs 91efa4605c
- When the instance is booted without any redirects files configured it's not supposed to error but rather default to an "empty" [] redirects configuration.
- Ideally the logic shoudl not contain try/catch block at all and fail as soon as there's any error during the initialization. This wasn't changed at this time due to possible break of existing Ghost instances
refs https://linear.app/tryghost/issue/CORE-84/have-a-look-at-the-eggs-redirects-refactor-branch
- The problem this change is addressing is inability to override config values once the code is extracted into a class+DI pattern
- The work around is restarting the instance with the configuration testing expected behavior - in this case missing or existing types of redirects files
refs https://github.com/TryGhost/Members/commit/9e59f5a9
Since we have a DynamicRedirectManager for handling adding/removing
redirects at runtime, we no longer need the custom-redirects middleware.
The redirects service does however need an init method now to add the
custom redirects at Ghost boot, so it's been refactored into our Class &
DI pattern.
no-issue
This removes the logic to check if stripe connect is allowed into the
stripe connect service, which makes the feature easier to maintain, as
well as fixes the v3 API - which previously did not have this check.
no issue
The way GA flags were introduced means that they stop existing in the `'labs'` setting in the db and are instead forced to always return `true` when checking the flag in the labs service. However, Admin which uses the flags fetches them via the `/settings/` API endpoint which was only returning the raw labs setting db value meaning GA flags appeared to be disabled unless the flag had previously been enabled and no settings save had occured.
- updated the settings bread service to replace the labs setting value with the JSON stringified output of `labs.getAll()` which is the ultimate source-of-truth for a feature being enabled/disabled
- extracted `browse()` behaviour to an internal `_formatBrowse()` method so we can apply the same filtering/modification for output of `browse()` and `edit()`
Co-authored-by: Fabien O'Carroll <fabien@allou.is>
no issue
- author line was appearing as "Author One,Author Two,..." with no space
- fixed the generation of `post.authors` when serializing a post before it's rendered for email
no issue
- if the verification threshold is 0, `_.get(..)` becomes falsy so we
fallback to Infinity
- this is not correct - we only want to default to Infinity if the value
is not set
- this commit explicitly compares the config value to `undefined` and sets
the fallback accordingly
no issue
- following on from f4fb0fcbaa,
this commit moves around some package requires in Ghost
- these are often niche packages that do something in a subsystem of
Ghost, and are not necessarily be needed to boot the application
- these packages use non-negligible CPU and memory when they are
required, so it makes sense to lazy-require them
- the concern here is that we obscure the code too much by moving
random requires further into code, but the changes are small and the
improvements big
- this commit bring the boot time since 4.19.0 down ~31% and initial
memory usage down by a total of ~12%
closes https://github.com/TryGhost/Team/issues/1172
Custom theme settings sync and cache population had been left to complete in the background as it wasn't essential for it to be complete for the front-end to start. However that was causing problems for the API where theme activation and custom theme settings list requests happen very close together, with the latter often not containing the theme settings data when it is expected to.
- changed `activationBridge.*` methods to `async` so they can `await` the completion of custom theme settings sync before activating a theme
refs https://linear.app/tryghost/issue/CORE-1/multiple-adapters-per-type
- There's a need to support multiple adapter variations per given adapter type (storage, sso, etc.)
- With the introduced changes we can specify a version of an adapter that should be fetched based on `:feature` postfix. For example:
`adapterManager.getAdapter('storage')` - would return the default adapter listed under "active" configuration
`adapterManager.getAdapter('storage:videos') - would return an adapter configured for videos *feature*
- Here's an example configuration for a custom video storage:
```
"storage": {
"active": "LocalFileStorage",
"videos": "ghost-storage-custom-video",
"ghost-storage-custom-video": {
"custom": "configHere"
}
}
```
refs https://github.com/TryGhost/Team/issues/1149
Ghost allows different themes to have the same `name` value in `package.json` but gives them a custom name based on the zip file used to upload it. The custom theme settings service however was always using the package.json name meaning that when syncing a theme with a duplicate name it was overwriting the settings for all other themes.
- bumped `@tryghost/custom-theme-settings-service` which changes the `.activateTheme()` signature to accept a theme name as the first argument
- updated our calls to `.activateTheme()` to pass Ghost's known theme name as the first argument so we're always syncing with the correct `theme` field value in the `custom_theme_settings` table
refs https://github.com/TryGhost/Team/issues/1138
Portal offer urls use offer id to load offer details UI and stripe checkout in frontend. This endpoint allows portal to fetch offer details from offer id to create Portal UI with relevant details for potential members.
no-issue
The MembersAPI using the OfferRepository coupled it to the internals of
the Offers Module - instead we pass the "external" API - so that we can
change the internals, and not have to update the MembersAPI's usage.
no-issue
Because we only called `init` if the labs flag is enabled, when starting
up a site without the flag enabled - the listener for adding redirects
wasn't active. So new Offers would not have their redirects setup.
- Ghost has a set of core packages that it is safe to require directly in any file - tpl is one of them!
- This keeps the DI signature smaller and easier to reason about
refs https://github.com/TryGhost/Team/issues/1104
- bumped `@tryghost/custom-theme-settings-service` so it throws a more appropriate `ValidationError` when setting keys don't exist or a select value is not known
- changed the custom theme settings service to have a `.init()` method which creates an instance of the service under `.api` so that we're able to create the instance at a particular point in the boot process when we know the models have been initialised
- there were problems in tests because the service was being initialised through the require chain before models were initialised through the boot process
- fixed incorrect `camelCase` of resource name in API responses
refs: #13380
- The i18n package is deprecated. It is being replaced with the tpl package.
Co-authored-by: Aleksander Chromik <aleksander.chromik@footballco.com>
refs: #13380
- The i18n package is deprecated. It is being replaced with the tpl package.
Co-authored-by: Aleksander Chromik <aleksander.chromik@footballco.com>
refs https://github.com/TryGhost/Team/issues/1090
This updates the Members & Offers modules to provide support for using
Offers in Stripe Checkout.
Members module now needs a handle to the Offers module repository, and
as such we have had to reorder the services boot order.
refs https://github.com/TryGhost/Team/issues/1083
This adds the Offers service which will allow us to build out an Admin
API to communicate with it. As well as wiring up the redirects to the
site app.
refs #13380
The i18n package is deprecated. It is being replaced with the tpl package.
Co-authored-by: Aleksander Chromik <aleksander.chromik@footballco.com>
refs: #13380
- The i18n package is deprecated. It is being replaced with the tpl package.
Co-authored-by: Aleksander Chromik <aleksander.chromik@footballco.com>
refs: #13380
- The i18n package is deprecated. It is being replaced with the tpl package.
Co-authored-by: Aleksander Chromik <aleksander.chromik@footballco.com>
refs https://github.com/TryGhost/Team/issues/1083
The Offers service is going to need access to the StripeAPIService too,
so we need to move it out of the @tryghost/members-api module and make
it accessible to both.
refs https://linear.app/tryghost/issue/CORE-86/fix-failing-site-instance-when-redirects-file-is-invalid
refs 260a47da83
- Added validation logic to catch redirects files having invalid RegEx expressions when they are introduced into the system (on upload)
- This way the error happening in the refed commit would have not happened as the validator would not have passed it through
- Moved up the "Router" declaration in custom-redirects as it needs to happen before any other bit of logic has a chance to throw
no issue
If Ghost was booted or a theme activated with the `customThemeSettings` flag disabled but with a theme that has custom settings, enabling the flag later on wouldn't show the settings in Admin or make the settings available in the front-end. Similarly, disabling `customThemeSettings` when Ghost had been booted/or theme activated with it enabled meant that settings were still available on the front-end.
- added an event listener for `settings.labs.edited` that fully re-activates a theme so that it's passed through gscan again and the custom theme settings passed back are included/excluded based on the flag value and any required settings sync with the database is performed
refs https://linear.app/tryghost/issue/CORE-35/refactor-route-and-redirect-settings
- When the yaml parser is injected through a DI it's easier to test and later on the redirects service initialization would use same pattern with exactly the same yamlParse funciton
- Next step is getting yaml parser into an outside module
- Also simplified getSettingFilePath method while swapping to an updated yaml parser implementation. Now this method function is exactly like the one used in redirects
refs https://linear.app/tryghost/issue/CORE-35/refactor-route-and-redirect-settings
refs 5715aa2155 (diff-48644be82a9b957e5e627bf7b0f2f73cdb1d63851ffad68c7c178c5886495bb8R52-R57)
- Simplified the yaml parser implementation to take in a single parameter, this move will allove to simplify the logic in the route settings + opens a door to unify handling with redirects yaml parsing!
- We loose the "filename" from the error information but that was a generic "routes.yaml" anyway and would be thrown only when somebody uploaded a routes.yaml file (no real added value).
- The debug statement should be moved to contain related filepath+other info to the calling module instead
- An additional error handler was borrowed from the redirects yaml parsing logic that was introduced in a referenced commit - it still makes sense to keep it for routes.yaml configuration
refs https://linear.app/tryghost/issue/CORE-35/refactor-route-and-redirect-settings
- It's a step to making the module follow class+DI pattern before fully extracting it into an external libarary
- Reminder, doing in Ghost repo instead of substituting big chunks all at once to have clear history of how the service evolved prior to the extraction into external lib!
refs https://linear.app/tryghost/issue/CORE-35/refactor-route-and-redirect-settings
- Ensure settings had only one method but would benefit from class+DI pattern before extracting it into an outside module.
- The logic is now also less coupled with "routes" and single source/destination paths. It's all configureable instead and might be reused if similar pattern is needed for example with redirect settings defaults.
refs https://github.com/TryGhost/Team/issues/1090
This updates the members-api to allow passing an Offer ID when creating
a Stripe Checkout Session. This will be used for the 1-day version of
Offers.
- i18n is an old pattern we are getting rid of in favour of tpl
- after removing i18n from helpers, there wasn't many usages of i18n left in the frontend, this removes whats left!
- this was done on a branch at the same time as Naz's commits removing i18n from the settings-related files
- hence some of these changes are minor amends to add additional messages/change names, rather than just straightup i18n->tpl
- it's a merge of both our refactors :)
refs https://linear.app/tryghost/issue/CORE-35/refactor-route-and-redirect-settings
- There's no reason for the boot to block the event by loading route settings sychronously
- The only leftover use of a sync loader might also be refactored in some way to avoid blocking the event loo - for example by caching the value on the service layer.
refs https://linear.app/tryghost/issue/CORE-35/refactor-route-and-redirect-settings
- The only allowed route settings name is 'routes.yaml', which removes a need to parameterize the function as the location is permanent anyway
- Simplifying the function in any possible way before extracting the common bits into an external lib
refs https://linear.app/tryghost/issue/CORE-35/refactor-route-and-redirect-settings
- Frontend is not meant to know about the underlying source of the "routes" configuration, so any reads/edits/validations are being moved into a backend service. This should also simplify the coupling of the backend with the frontend where the latter will get a JSON blob with all needed configuration during the boot
- Nother problem the "get" method had was hiding an underlying function it was doing - reading the file from the filesystem SYNCRONOUSLY. It might be a thing we need to do during the "web" app initialization, but there's no clear need to do this in a sync fassion during the bootup for example. Also having a more explicit name should help :)
refs https://linear.app/tryghost/issue/CORE-35/refactor-route-and-redirect-settings
refs c1c9bf0866
- Actions logic related to file system operations (like ensuring files exist) should be done on the backend. Now the route settings initialization logic lives on the backend it makes sense to keep the file closer to the source.
- The move is the opposite to the one refed in the commit with a
difference that the file now lives in "route-settings"
refs https://github.com/TryGhost/Team/issues/1070
- added `@tryghost/custom-theme-settings-service` as a dependency
- `core/server/services/custom-theme-settings` creates an instance of the new service passing in the model used for storing the setting keys/values and a cache instance
- requiring `core/shared/services/custom-theme-settings-cache` creates a cache instance, it has no dependencies so can be required anywhere and the first require will initialize the shared instance
- updated the theme activation bridge to trigger the theme settings service to sync the newly activated theme settings and populate the cache
- updated theme validation to pass `labs` through as an option so that we get custom theme settings back as part of the checked theme as that's what is passed to the custom theme settings service
refs https://github.com/TryGhost/Team/issues/694
refs https://linear.app/tryghost/issue/CORE-13
- The index file in services/settings was containning logic and started throwing an additional lint warning due to module length.
- The extracted secret settings utils were used in multiple places and were a good candidate to live in it's own small module
refs https://github.com/TryGhost/Team/issues/694
refs https://linear.app/tryghost/issue/CORE-13
- The controller code is not meant to contain complex business logic. Removed complexity in settings.edit method
- Have separated the regular editing from "Stripe Data" editing to keep the dependency on the members service still in the controller reducing coupling of the settings BREAD service to the minimum.
- The stripeConnectData passed into `edit` method still feels out of place (maybe it should be passed as an array already that's ready to be merged with the rest of settings, but that was left for another refactor in the future)
refs https://github.com/TryGhost/Team/issues/694
refs https://linear.app/tryghost/issue/CORE-13
- The controller code is not meant to contain complex business logic.
Reduced complexity in the settings.read method
- Broke the usual "xxxService" naming pattern here in favor of "xxxBREADService" pattern that members package has been experimenting with recently (0469707f2e/packages/members-api/lib/services/member-bread.js (L25)). This naming choice was made because we already had a "SettingsService" and it would've become quite convoluted distinguishing the naming or doing renames for the sake of having a new temporary location for read/edit/add methods
- Also duplicated `hideValueIfSecret` method code with an intention to move it fully into the BREAD service once the refactoring is completed
refs https://github.com/TryGhost/Team/issues/1055
We use the models defined in Ghost as our database connection to store
the analytic events. So we must pass this down to the Members module so
that we can store the events
refs https://github.com/TryGhost/Ghost/security/advisories/GHSA-wfrj-qqc2-83cm
refs https://github.com/advisories/GHSA-48ww-j4fc-435p
- a vulnerability in `nodemailer` means that the `sendmail` transport is
vulnerable to command injection for flags passed to the `sendmail`
binary
- updating to the latest version of Nodemailer required creating
`@tryghost/nodemailer`, which is a wrapper around Nodemailer and
several plugins that used to be in the core
- this commit switches to using that package, and fixes up some small
code + test changes
refs https://github.com/TryGhost/Team/issues/1047
Rendering segmented emails uses `cheerio` to parse and re-render the html but this had a side-effect of converting the `$#39;` char code to the more modern `$apos;` code resulting in Outlook not understanding quotes inside inlined CSS and showing the raw char code if it appeared in the email contents.
- extracted our handling of the unsupported char codes from the main email html generation into a function so that it can be re-used when generating segmented html
refs https://github.com/TryGhost/Team/issues/694
refs https://linear.app/tryghost/issue/CORE-10/tackle-integrationsjs
- The controller code is not meant to contain complex business logic.
- Added a test case checking 'PUT' endpoint for integrations to ensure
proper 'NotFound' handling. Found that previous implemenation was
buggy - threw a 500 as 'models.Integration.NotFoundError' that was removed
in previous commit didn't catch a needed error.
no issue
It was possible for authenticated/trusted admin users to make GET requests to localhost via the oembed service by crafting a redirect that used 0.0.0.0.
- added the 0.* default route/routing block to the private IP regex used to block requests when we're contacting external sites
- added an additional IP or localhost check in the oembed service when fetching bookmark card data
refs https://github.com/TryGhost/Ghost/pull/13276
- when removing the labs flag a conditional in the email processor checking for the labs flag being enabled was replaced with a check for a member segment being present. This meant that email batches with `member_segment: null` representing all members that didn't have content specifically aimed at them were not having the segmented content stripped before sending
refs https://github.com/TryGhost/Team/issues/694
- The controller code is not meant to contain complex business logic.
- Kept the pattern used in all modules under services/themes. The install module shold be refactored into a class with DI pattern when touched next.
refs baccbb4942
refs https://github.com/TryGhost/Team/issues/694
- The change is here to remove yet another ESLint method complexity error
- The custom error handling complexity was introduced here in a referenced commit without an obvious reason. The specifics of how the "sendTestEmail" method handles errors should not leak out from the method, if there are errors in the response they should be handled internally and the method would uniformly reject with a single error.
refs https://github.com/TryGhost/Team/issues/694
- The code complexity in the email preview's read controller method was breaking the complexity rule in ESLint. To reduce the complexity extracted common parts into mega service
refs https://github.com/TryGhost/Team/issues/1007
- `:root` selector wasn't working as expected and ended up matching HRs within content
- switched to wrapping the post html inside a `<body>` element before parsing so that we have a proper top-level element for direct child selectors to match against