refs: https://github.com/TryGhost/Team/issues/759
- No matter what, a handlebars helper outputs a string. So if you return true, you'll always get 'true'.
- SafeStrings are handlebars's way of passing around a string whilst also maintaining a record of the original value e.g. new SafeString(true) results in {string: true}
- We need this for the match helper, so that we know when doing a comparison that we're meant to be comparing against a boolean true, not a string true
- Therefore, we need to putput SafeStrings, but also process them when passed in
The logic
- Figuring out the correct logic here has been a little tricky but essentially:
- {{match safestring}} with a single arg, will return true for any truthy value
- {{match safestring "=" true}} does a direct comparison with the original value of the safe string, so if it was a boolean true, the match will be true else false
- {{match (match something) "=" true}} will therefore work for any level of nesting
- this can result in slightly inconsistent results, but feels correct and documentable
This is documented extensively through the test cases
refs https://linear.app/tryghost/issue/CORE-103/decouple-internal-frontend-code-from-url-module
- We need to decouple all frontend services from URL service as much as possible. "bootstrap" module is now a central point to substitute (proxy really) function previously done by the URL service and this move changes direct usage of URL service to "bootstraps" internal proxy function
refs https://linear.app/tryghost/issue/CORE-103/decouple-internal-frontend-code-from-url-module
- By becoming a parameter in the routing bootstrap process URL is Service no longer a "require" inside the frontend controllers but rather becomes a part of the "internal API" of the bootstrapper. This is not the end form of it, rather a step closer to decouplint routing from the URL serivce.
- The bootstrap module needs a facelift to have cleaner distinction between init/start methods. This is left for another time
refs https://github.com/TryGhost/Team/issues/1106
- updated schema validation to add `'boolean'` as an allowed `type` value
- added `format()` and `parse()` methods to `CustomThemeSetting` model to match `Settings` model behaviour for boolean-type settings
refs https://github.com/TryGhost/Team/issues/1132
This will be used to store Offer Redemptions, which will be used to list
the Offers which a Member has redeemed, as well as the number of times
an Offer has been redeemed.
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.
refs https://github.com/TryGhost/Team/issues/1131
This will allow Ghost Admin to display separate lists of active and
archived Offers! We must pass the options through so that the
OffersService is able to handle the filter passed in the request.
no issue
Boot-time metrics are really valuable for understanding how releases affect the performance of Ghost. The new @tryghost/metrics package lets us ship these metrics to different sources using the same configuration framework as @tryghost/logging introduced.
no-issue
Because adding and editing Offers can update the redirects for Ghost, we
should ensure that any site cache is cleared so as to not conflict with
Offer redirects.
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 c33b596e9c
- initializing the themes service before the custom theme settings service meant that `customThemeSettings.api` was not available when it's called as part of theme initialization
- swapped the boot order around so that the supporting service initialization is performed before the full themes service is initialized
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: #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>
closes https://github.com/TryGhost/Team/issues/1125
refs 3c822e0457
- Email-only is not considered a general availability feature and can be used without special flags.
- It allows to publish a new post type "email only" that only goes out as an email newletter and is available through an undescoverable URL (does not appear anywhere publicly similarly to preview posts) on the site.
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: #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
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: TryGhost#13380
- The i18n package is deprecated. It is being replaced with the tpl package.
- Important Note: invalidFile error message does not have fields for variables, but it is being passed variables.
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.
* Replaced i18n.t w/ tpl helper in invites.js
* Replaced i18n.t w/ tpl helper in labels.js
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: 9d7049cd3
- I missed that the amp_content helper was meant to be async when refactoring
- I have updated our proper amp acceptance tests to catch the content not rendering as this is a regression, this should definitely have been caught
- Added missing async property to amp_content helper to fix the issue
refs: #13380
- The i18n package is deprecated. It is being replaced with the tpl package.
- The changed files are under `core/server/api/v2` and `core/server/api/v3`.
refs: #13380
The i18n package is deprecated. It is being replaced with the tpl package.
The files changed are under `core/server/api/v2` and `core/server/api/v3`.
refs: #13380
The i18n dependency is deprecated, it's being replaced by the tpl one.
The `tags.js` files changed is under the following folders:
- core/server/api/canary/
- core/server/api/v2/
- core/server/api/v3/
refs: #13380
- The i18n package is deprecated. It is being replaced with the tpl package.
The files changed is under `core/server/api/v2` and `core/server/api/v3`.
refs: #13380
- The i18n package is deprecated. It is being replaced with the tpl package.
Replace the deprecated dependency `i18n` with `tpl` in the following files under
`core/server/api/v2/`:
- authors-public.js
- pages-public.js
- session.js
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>
- The helper registration code is "framework" code and very specific
- At the moment the "theme engine" is full of lots of disparate theme related stuff
- I'm trying to make the frontend framework code clearer and also expand it to make it more useful
- The helper system now also exposes 3 methods allowing you to register a directory, a helper or an alias
- I've updated the codebase to use these both for our core helpers and for "apps"
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
refs: #13380
- This is part of the ongoing push to get rid of the deprecated i18n.t calls
- In this case, it highlights just how little work we've done on API errors - we should have a full list of action messages, but there's just 1 :(
- This is initial ground work to enable us to do a full error audit
- We want to prevent Ghost admin from ever showing any unhandled errors
- Additionally we want to ensure all handled errors are well worded & have context+help
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: #13380
The i18n package is deprecated. It is being replaced with the tpl
package.
* Replaced i18n.t w/ tpl helper in email
* Replaced i18n.t w/ tpl helper in integrations
refs: #13380
- this is to replace i18n.t with tpl because i18n.t is deprecated
- Replaced i18n.t with tpl helper in email-post.js
- Replaced i18n.t with tpl helper in email-preview.js
* Replaced i18n.t w/ tpl helper in users
refs: #13380
The i18n package is deprecated. It is being replaced with the tpl package.
* Replaced i18n.t w/ tpl helper in authentication
refs: #13380
The i18n package is deprecated. It is being replaced with the tpl package.
Co-authored-by: Kenneth Fitzgerald <fitzgeraldkd@gmail.com>
refs https://github.com/TryGhost/Team/issues/1088
- adds schema for new offers table
- adds permission fixtures for new offers table
- adds migrations for new table and permissions
Co-authored-by: Fabien O'Carroll <fabien@allou.is>
refs: https://github.com/TryGhost/Ghost/issues/13380
- this is a refactor we are looking to do everywhere
- this commit is a reference for how to do the refactor: in small minimal pieces
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://github.com/TryGhost/Team/issues/1101
- description field in Admin is being moved to an area which has a live preview so we want to be able to pass this through as a preview param
- uses `d` rather than `description` to follow the shorter param names pattern
refs https://github.com/TryGhost/Team/issues/1097
- added `customThemeSettingKeys` as an argument to `preview.handle()` because we can't know which keys should be allowed through up-front
- added `custom` as a supported setting in the preview header data
- `custom` should be a JSON object containing any custom theme settings
- we parse the object but only set properties on `@custom` that are known custom theme setting keys
- if parsing fails or it's not an object then no custom data is set
- updated `updateLocalTemplateOptions()` to pull `.custom` off of the preview data and pass it through so it's accessible on `@custom` as an override to the saved custom data
refs https://github.com/TryGhost/Team/issues/1097
globalTemplateOptions are supposed to be static with localTemplateOptions being merged in per-request, however the per-request preview data was being extracted and set in the global options. Comments suggest that the global data should be static and eventually updated via other means, the usage of the request object to get per-request preview data is working against that.
- adjusted the preview handler to return an object rather than changing properties by reference on a passed in object
- moved preview data fetching out of `getSiteData()` used in `updateGlobalTemplateOptions()` and into `updateLocalTemplateOptions()` so that we're not relying on the request object in `updateGlobalTemplateOptions()`
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.
- The original intention of the proxy was to collect up all the requires in our helpers into one place
- This has since been expanded and used in more places, in more ways
- In hindsight there are now multiple different types of requires in the proxy:
- One: true frontend rendering framework requires (stuff from deep inside theme-engine)
- Two: data manipulation/sdk stuff, belongs to the frontend, ways to process API data
- Three: actual core stuff from Ghost, that we wish wasn't here / needs to be passed in a controlled way
- This commit pulls out One into a new rendering service, so at least that stuff is managed independently
- This draws the lines clearly between what's internal to the frontend and what isn't
- It also highlights that the theme-engine needs to be divided up / refactored so that we don't have these deep requires
refs https://linear.app/tryghost/issue/CORE-35/refactor-route-and-redirect-settings
refs 7528ec8c3b
- The way the custom redirects middleware was organized made it extremely hard to unit test it (had to stub the redirects service methods etc). With a new organization it's possible to provide needed redirects configs to the method which makes the actual redirects Router logic testable and the code less coupled with redirects services
- This was meant to be an attempt to extract more of the slow redirects regression tests, which failed. Instead found this weak spot that could be improved and gained:
- shaved 4s of time as two slow regression test cases are now gone
- there's now a base to build upon when getting more coverage for the custom redirects middleware
refs https://github.com/TryGhost/Team/issues/1070
- bumped `@tryghost/custom-theme-settings-service` for access to `.updateSettings()`
- added `PUT /custom_theme_settings` route that delegates to `customThemeSettingsService.updateSettings()` to perform the db and cache updates
- invalidates the cache in Ghost because a theme setting change will mean the front-end output will change
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.
refs https://github.com/TryGhost/Team/issues/1086
- bumps portal to handle offers link which redirects to stripe checkout with coupon applied
- uses hardcoded coupon value for prototype
- The frontend proxy is meant to be a way to pass critical internal pieces of Ghost core into the frontend
- These fundamental @tryghost packages are shared and can be required directly, hence there's no need to pass them via the proxy
- Reducing the surface area of the proxy reduces the proxies API
- This makes it easier to see what's left in terms of decoupling the frontend, and what will always need to be passed (e.g. api)
Note on @tryghost/social-urls:
- this is a small utility that helps create URLs for social profiles, it's a util for working with data on the frontend aka part of the sdk
- I think there should be many of these small helpers and we'll probably want to bundle them for the frontend at some point
- for now, I'm leaving these as part of the proxy, as need to figure out where they belong
- 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://linear.app/tryghost/issue/CORE-35/refactor-route-and-redirect-settings
- 'knowSettings' was based on a "configurable" array of settings that might be configured in Ghost. The multitude never happened! The only setting the frontend takes care of is routes.yaml file (redirects is also kind of a setting but is a separate concept for now).
- Having just one type of file to deal with allows to simplify implementation significantly, which helps before a big refactor
refs https://linear.app/tryghost/issue/CORE-35/refactor-route-and-redirect-settings
- This is a micro-step towards getting rid of multiple "knownSettings" concept. Since the introduction of an array of knowSettings there was never-ever a need to handle anything but a single `routes.yaml` file. Getting rid of this concept first to have a simpler module. Next step would be getting rid of filesystem reads/writes in the "frontend"
refs https://github.com/TryGhost/Team/issues/1070
- bumped `@tryghost/custom-theme-settings-service` to get access to `.listSettings()` method
- added GET `/api/canary/admin/theme_settings/` route behind `'customThemeSettings'` feature flag that uses the custom theme settings service to return settings resources that are a combination of the theme-provided definition and the saved value
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/1070
- stores values of custom theme settings
- will be merged with full settings data parsed from themes for API output
- will be cached and made available for lookup in themes to avoid db roundtrips
- stores type of custom theme settings so we can coerce values and know if the type has changed when syncing
- records will be synced with themes upon activation
refs https://github.com/TryGhost/Ghost/security/advisories/GHSA-65p7-pjj8-ggmr
This updates the signup/signin flow for members to no longer support the
email address change flow - which had missing authentication. It has
been replaced with a dedicated email change flow, and Portal has been
updated to use it.
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 brought up to sync v3 controller code to the changes that were done in v4. Didn't touch v2 controller as it had slight API differences, so avoided going on another trip into the unknown
- Migrating v3 controller was pretty straigh forward as it's an exact copy of the v4 one (at least for the methods that were extracted)
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/Team/issues/1063
Member activity is a labs alpha feature which aims at capturing member events for site owner if switched on. The event metadata captures the site page/post where the event originates from, and the post/page id is included as content of new ghost analytics meta tag. The meta tag is only aded on the site if member activity is switched on from labs.
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
no-issue
We're seeing problems with large sites taking a long time to run this
migration. The aim here is to refactor it so that it is faster to run.
We've achieved that by reducing the number of database queries needed,
firstly by selecting members with a join to their events (rather than
fetching the events on a member-by-member basis) we also batch the
necessary updates to further reduce db query time.
closes: CORE-34
refs: https://github.com/TryGhost/Team/issues/1044
- this is a super basic fix, it adds a max nodes concept and limits the node in each sub-sitemap to 50k by default
- this will prevent the error in google console
- a better fix is in progress, but we want to at least solve the errors ASAP
refs https://github.com/TryGhost/Team/issues/1053
This table is going to be completely deleted at some point in the
future. It serves as a persistent datastore for a spike into collection
analytic events for members. We've opted for a generic table, rather
than a table for each event, so that we can push the DB to the limit in
terms of the length of the table, and find out performance issues A$AP
closes: CORE-33
Two bugs:
- lodash isEmpty and handlebars util isEmpty are not the same
- I literally had the truthy and falsy cases the wrong way around 🙈
Notes:
- I have, for now, copied the isEmpty util from handlebars. It's so small it doesn't seem worth trying to require the util right now, although in future it'd be nice if that was easier to do
- Adding the management for the conditional being a SafeString allows the match helper to be a subexpression of itself, I can see this pattern being useful later in combo with the any and all helpers
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