refs https://github.com/TryGhost/Ghost/issues/12633
Adds new stats endpoints for showing member dashboard, which fetches aggregate date over member events tables to form relevant datasets -
- Adds new endpoint for tracking MRR of site over time - `/members/stats/mrr`
- Adds new endpoint for tracking subscribers on site over time - `/members/stats/subscribers`
- Adds new endpoint for tracking gross volume of site over time - `/members/stats/gross_volume`
- Adds new endpoint for tracking member count on site over time - `/members/stats/count`
refs https://github.com/TryGhost/Ghost/issues/12608
- adds `admin/canary/themes/install` endpoint to the Admin API
- requires two query params. `source` must be set to "github". `ref` should refer to a GitHub repo in the format "{org}/{repo}"
- downloads zip archive for the repo from github
- runs downloaded zip through the same process as uploaded zips
no-issue
This removes all references to the members labs setting, any code that was run conditionally behind this flag now runs unconditionally.
* Removed usage of Members labs flag
* Removed tests for Members disabled
* Added dynamic keypair generation for when setting is missing
refs #12568
- DI pattern through constructor allows for very clear separation of concerns and makes it easy to extract the class into a separate module
refs #12568
- When the server is in maintenance mode (e.g. during migration) it needs to serve a 503 page. Previously this role was delegated to the "frontend" which tightly coupled server bootup and frontend.
- With a dedicated HTTP application serving up 503 server is no longer coupled to the frontend during maintenance
ref #10898
- The redirects configuration's `to` & `from` URL parameters used to ignore it's query string parameters, which resulted in unexpected behavior
- Current changeset only partially fixes the issue. Now `to` URL's query parameters always take precedence over incoming query parameters and the rest of query parameters are passed through.
refs #12402
- With bumped version of job-manager it offloads job procesing into separate worker thread. Having jobs run out of main Ghost process even loop allows for safe job execution, which does not block Ghost from serving requests or performing other functions without a delay
- Added experimental data access to 'testmode' jobs. This should serve as an illustration of how to access data from the job layer
no issue
- These changes should allow easy testing of scheduled jobs and provide an implementation example for future jobs within Ghost
- Added experimental support to run jobs based on functions defined in modules
- Extendeded testmode "schedule" endpoint with an optional job name parameter which picks up job from "jobs" folder
- Adjusted scheduleJob method use and passed "schedule" as first parameter
- Bumped job-manager version to allow for all new functionality
no issue
- Living in separate folder will allow adding more testmode specific modules (for example test jobs)
- Mimicks the folder structure of how v2/canary routes are structured better
no issue
- We need an ability to early test scheduled jobs to refine the new feature and it's API. Should be used with caution
- To schedule an example scheduled job every 30 seconds run following request: `curl http://localhost:2368/ghost/api/schedule/every%2030%20seconds`
refs #11085
- Incorrect usage error was logged to the output when there was no recirecst configuration file present in the system. Previously an empty string was returned in such situation, resulting in "ENOENT" error, which was ignored through special handling.
- The fix resembles logic in redirects async getter function where empty array is returned when the config file does not exits.
- Attempting to read unexistent config should not ever happen and will be handled on the config service layer, this is why special "ENOENT" handling has been removed
closes#11085
- Ghost has been using YAML format for other configurations (e.g. routes). The plan is to move to this format for all user-edited settings files. By default JSON format is still used in Ghost Admin API v2/v3, but will be changed to YAML in API v4. Check referenced issue for more context.
- New format supports all the features available before. The main noticeable change is the structure of config file. It is now grouped by redirect HTTP code instead of specifying `"permanent": true | false` attribute for each config property. Example format for YAML config:
```
302:
/from-url/: /to-url/
301:
/category/([a-z0-9\-]+)/i: /tag/$1/
/v([0-9\.]+)/docs/([a-z0-9\-]+)/i: /docs/$2/
```
- Added 2 new endpoints: `POST redirects/upload` and `GET redirects/download`. These serve as an alias to current GET/POST `/redirects/json. "upload/download" naming pattern is introduced to match the convention with other resources that can be uploaded and downloaded (images, themes etc.). `/redirects/json` endpoints will be removed in Admin API v4
- The parsing code from `custom-redirects.js` has been moved to `frontend/services/redirects/settings.js`. This location is more appropriate for this logic and eventually `custom-redirects.js` middlewear might be moved into "frontend" as this middlewear plays a role mostly effecting that area.
no refs
[Portal](https://github.com/TryGhost/Portal) is a new drop-in script to make the bulk of Ghost membership features work on any theme out of the box, which was under a developer flag so far. This release removes the flag for Portal and makes it included as default for any members-enabled Ghost site. The Portal script is backward compatible with old public members script and existing Members-enabled themes should notice no change.
- Removes Portal config flag as Portal is now enabled by default
- Removes old members script as Portal is backward compatible with it
- Changes `{{content}}` helper to show default CTA in case of restricted content access
- `accent_color` setting is no more behind the dev experiment flag and included by default
- Adds migration to switch off Portal button setting for all existing sites which don't have Portal enabled in beta
no issue
- centralises definition of max width and allows customisation if needed
- allows for passing of the config value through to rendering libraries
no issue
- standard browse/read/add/edit/destroy API endpoints for snippets resource
- updates `@tryghost/admin-api-schema` dependency to version that includes snippet definition and schemas
closes#12244
As per RFC 6454 the Origin header MUST be set to the string 'null' when
in a "privacy-sensitive" context. We were not handling this string and
this was causing errors. This commit updates all checks of the 'Origin'
header to treat the value 'null' as if the header was not present.
ref: https://tools.ietf.org/html/rfc6454#section-7.3
no issue
- Updated magic link generation and validation methods for email update API to handle new support address
- Updated importer to ignore the new support address as it can only be updated via verification
- Updated members service to listen on settings edit for new support/reply address fields as well
- Updated tests to include the new settings
refs #12127
- Adds new `editSubscription` endpoint for members admin API which allows updating individual subscription for a member - `PUT /members/:id/subscriptions/:subscription_id/`
- `editSubscription` has same permissions as member's `edit` endpoint
- Currently allows toggling of cancellation at period end for an active subscription
- Bottom line - we need to manage shutting down gracefully when doing long-running tasks
- To achieve that, we're going to use job queues
In this commit:
- added new @tryghost/job-manager dependency
- added a minimal job service, that handles in passing things like logging and (maybe later) config
- job service is wired up to server shutdown, so that the queue finishes before the server exits
- also added a new job endpoint to testmode so that it's easy to test job behaviour without needing to do real work
- A simple way to test behaviours without having to do complex interactions to e.g. generate errors or slow requests
- Makes it easier to test the new shutdown behaviour, among other things
no issue
- Webhooks API has been stabilized with latest changes and there are no breaking changes planned for v3. The change has strictly "informative" purpose
- Changed variable naming from "whitelisted" to "allowlisted" to follow updated naming convention (refs. https://mysqlhighavailability.com/mysql-terminology-updates/)
no issue
- Changes introduced to both API v3 and v2
- Makes sure to use the same integration_id as authenticated integration for the webhook's data.
- Makde it is impossible to create orphaned webhooks using token authentication
- Allowed only parent integration to edit it's children webhooks. Throwing permission error otherwise
closes https://github.com/TryGhost/Ghost/issues/11944
- updates `@tryghost/image-transform` to version that exposes `canTransformFiles()` which checks for `sharp` availibility
- updates `@tryghost/kg-default-cards` to version that accepts a `canTransformImage()` method as an option
- updates our `mobiledoc` lib to pass a `canTransformImage()` function that returns false if sharp is unavailable, the image extension is not supported, or the storage engine in use does not support image transforms
- updates `populateImageSizes` to fetch image sizes when transforms are unavailable as the render/not-render is now handled in the renderer and we don't need to worry about adding size information to the mobiledoc source
no-issue
pr: https://github.com/TryGhost/Ghost/pull/11930
- Upgraded @tryghost/members-api to 0.23.0
This version includes a new method hasActiveStripeSubscriptions
- Added /admin/members/hasActiveStripeSubscriptions
This can be used to determine whether or not we should allow removing
the stripe keys.
- Added /admin/settings/stripe/connect
This can be used to delete a Stripe Connect integration, provided
there are not active subscriptions
- There were various cases where it was possible to trigger a private site to display a 404 instead of redirecting to /private/
- Private mode was also not always displaying the correct robots.txt
- This PR includes tests for all cases in test/frontend-acceptance/default_routes_spec.js & where possible the unit tests have also been updated for completeness
- Fixing the 404 issues required
- Better handling of paths using req.path instead of req.url in filterPrivateRoutes
- Additional error handling, to cover the case that a tag/author RSS feed does not exist
- Fixing the robots.txt required the order of middleware to be changed, so that private blogging gets a chance to render first
- NOTE private blogging is the only app with a setupMiddleware function so nothing else is affected
no-issue
This issue only occurs when using custom redirects with a subdirectory
setup, and the path to be redirected from is expressed as a regex, and
the url that is being redirected to is not an external url.
The issue has a few components:
- Redirect paths as a regex generally use the ^ to ensure that they
match the beginning of the path.
- The path that the regex is matched against conditionally excludes the
subdirectory, specifically, the subdirectory is excluded for external
urls
These combined means you end up with a regex like /^\/custom-redirect/
and a path like /subdir/custom-redirect, these will not match/replace
correctly, and you'll end in an infinite redirect loop.
The fix here is to *always* remove the subdirectory when testing regex's
and then conditionally adding it back *only* for the redirect, and only
if it is an internal redirect
no issue
- The intention is to move away from using file type names in URLs. This endpoint is meant to correspond to current `POST /members/csv` endpoint, that is planned to be renamed into `/members/upload`. And the `GET /members/csv` to be renamed to `/members/download` respectively.
no issue
- This endpoint is meant to be used for validation of imported members
- Main function at the moment is to validate if stripe_customer_id present in the dataset exists in connected Stripe account
no issue
- adds a set of hardcoded "content image sizes" to the base config
- adjusts `handle-image-sizes` middleware to always allow the hardcoded content image sizes to be genreated
- updates `@tryghost/kg-card-factory` to allow passthrough of options to card renderers
- updates `@tryghost/kg-default-cards` to add `srcset` output for image and gallery cards
refs https://github.com/TryGhost/Ghost/issues/11414
Confirms if the fromAddress for sending member emails is valid and accessible using magic link flow, allowing owners to update full from address including domain change.
- Extends member service to handle magic link generation and validation for email update
- Updates existing setting endpoint to not directly update from address
- Adds new endpoint to send magic link to new address
- Adds new endpoint for validating the magic link when clicked and update the new email for from address
- Adds new email template for from address update email
no-issue
In order to issue a redirect we need access to the "raw" req/res
objects, which is why we must return the function which gets access to
them.
The members service is used to create the auth url and to update the
users session.
no issue
- node was complaining the package was missing after the sanitize-html update [1]
- the update removed an old version of lodash which supported the dot importing
method
- our code relied on this subdependency to work, but the structure has since
been updated
[1]: https://github.com/TryGhost/Ghost/pull/11867
- Represents that logging is shared across all parts of Ghost at present
* moved core/server/lib/common/logging to core/shared/logging
* updated logging path for generic imports
* updated migration and schema imports of logging
* updated tests and index logging import
* 🔥 removed logging from common module
* fixed tests
* moved `server/config` to `shared/config`
* updated config import paths in server to use shared
* updated config import paths in frontend to use shared
* updated config import paths in test to use shared
* updated config import paths in root to use shared
* trigger regression tests
* of course the rebase broke tests
no issue
- moves members stats generation for the admin graph from the client to the server
- outputs a basic totals count across a requested date range of 30, 90, 365 days, or all time. See below for the response shape
- leaves heavy lifting of the counts to the SQL engines - tested on a dataset of 100k members and query performance is <100ms
```
GET /ghost/api/canary/members/stats/?days=30
{
total: 100000,
total_in_range: 20000,
total_on_date: {
'2020-04-25': 19000,
'2020-04-26': 19500,
// continues until today's date
},
new_today: 200
}
```
no issue
- Removes global bodyParser middleware for membersApp and adds it to specific endpoints
- Removes global boolParser middleware for membersApp
We added bodayParser middleware to memebrsApp in [this](fe3eab1836) commit to read json requests for members update endpoint, but that had issues with stripe webhook parsing for `/webhooks` endpoint as stripe expects raw data to be passed down.
- Allows member logged in with valid session to update their profile info - name, email, subscribed(newsletter subscription status)
- Adds new util method for formatted member response on the endpoints
- Adds common middlewares for body/bool parser and maintenance
- Adds `subscribed` status to member response
no issue
- Adds new endpoint on integration to refresh admin/content api key secret
- Allows owner/admin to refresh their content or admin API keys for an integration via Ghost Admin
- Adds a new `refreshed` event to actions table for anytime an api_key secret is refreshed
- Added a wrapper around express.Router to our shared/express util
- Also export static and _express
- Use this shared util everywhre, meaning express is only used directly in this one file
- ATM this file is mostly an experiment / debug helper, it might be removed again later
- The aim is to have a minimal framework wrapping express that allows us to:
- reduce our usage of express() in favour of Router()
- unify some of our duplicated logic
- fix some structural issues e.g. Sentry
- make it easier to understand the codebase
- Meant to cleanup the old api/canary/members earlier, removed now as it's unused
- Also removed all the duplicate references to labs.members in various places
- Clarify that the parent app has 2 distinct parts: backend and frontend
- Frontend app takes members and site apps + the frontend SSL redirect middleware
- Backend app already has admin + API (and the SSL redirect needs significant work)
- There's a lot more to do here, but this increases clarity
- create a new app for the /members/ endpoint
- moved all /members/ routes and middleware onto this app
- helps to separate members and frontend/site logic so we can start to decouple things more
refs #10898
- Execute string replacement on external paths
- Take non-top-level base URLs into consideration (to avoid #10776 dups)
- Added tests for all of the above cases
- Magic link token handling doesn't need to be global, this couples the system to the frontend, which isn't necessary
- Instead, we create a session from the token, and redirect to the frontend
- Move res.locals.members setting into existing middleware function instead of having it separate
- The existing createSessionFromToken was actually doing two things behind the scenes
1. Handling the ?token from the magic link and creating an actual session (mounted globally, which is not necessary)
2. Loading an existing session so that a member is logged in to the frontent
- IMO 1. is part of members, and doesn't need to be global
- IMO 2. is part of the frontend. It does need to be global but should NOT be hidden away behind the token middleware, as it wasn't clear what this was doing
- All var declarations are now const or let as per ES6
- All comma-separated lists / chained declarations are now one declaration per line
- This is for clarity/readability but also made running the var-to-const/let switch smoother
- ESLint rules updated to match
How this was done:
- npm install -g jscodeshift
- git clone https://github.com/cpojer/js-codemod.git
- git clone git@github.com:TryGhost/Ghost.git shallow-ghost
- cd shallow-ghost
- jscodeshift -t ../js-codemod/transforms/unchain-variables.js . -v=2
- jscodeshift -t ../js-codemod/transforms/no-vars.js . -v=2
- yarn
- yarn test
- yarn lint / fix various lint errors (almost all indent) by opening files and saving in vscode
- grunt test-regression
- sorted!
no issue
- Handlebars now throws an Error for misuse errors within the if/unless
helpers, but our error handling checks for a TypeError
- this would skip using an IncorrectUsageError and ends up throwing a GhostError
- this commit removes the TypeError check and switches to using the
Handlebars error message
- added core/shared to watched folders in grunt
- moved sentry to shared
- moved express initialisation to a shared file
- always set trust proxy + sentry error handler
- use this new express init everywhere, and remove duplicate trust proxy and sentry error handler code
- renamed the parentApp in index.js to ghostApp, to reduce confusion with the layer that is named parentApp
- renamed the adminApp inside of parentApp to backendApp to reflect the fact it's both admin+api
- renamed a bunch more variables there to be backend, rather than admin
- renamed the api index.js file to app.js and created a new index which is an actual index
closes#11766, refs 7284227f1
- when we changed from host to hostname, more changed than just using the x-forwarded-host if trusted because express req.hostname does not return the port
- this causes issues with an infinite redirect if you try to set a different admin host with a port
- added a test to demonstrate the case, that didn't fail due to an error in the test logic
- switched from redirecting based on req.hostname to using req.vhost.host which has the correct trusted, requested value that we should rely on
- simplified the comparison logic to explicitly compare host with host
- This code was a little verbose, which made it hard to see what was happening (it still is a bit)
- Used destructuring to reduce the code
- Renamed a few variables
- we had urlRedirects, urlRedirects.adminRedirect and adminRedirects
- all do kinda similar things, but for different contexts so for now I've done a minimal renaming for clarity
- and updated some comments!!
- also removed totally unnecessary if res.isAdmin clause, as we don't use that, and it was never true
- cache-control had some logic in it for private blogging + similar logic exists for members in site/app
- having it in 2 places is weird, and having it inside the mw makes the mw less generic/reusable
- instead of requiring config inside the middleware, we pass config in for the one case where this is used
- fixed tests that didn't test anything 🙈
- Moved normalize image mw from shared to api as it is not shared (except within the API)
- This file is only used in one part of the app, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
- Moved upload validation mw from shared to api as it is not shared (except within the API)
- Co-located the code with the upload middleware, as it's small and gives us a nice API of .upload.single and .upload.validation
- This file is only used in one part of the app, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
- These two functions have no dependencies and are only used in valiation/upload
- Co-locating the code makes it easier to move
- Exported them with a new module.exports._test pattern - we'll see about whether this is a good idea
- This is one of many similar changes needed to make it easier to refactor to the existing setup
- Moved upload mw from shared to api as it is not shared (except within the API)
- This file is only used in one part of the app, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
- Moved update-user-last-seen from shared to api as it is not shared (except within the API)
- This file is only used in one part of the app, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
- Moved api cors from shared to api as it is not shared (except within the API)
- This file is only used in one part of the app, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
- Moved version-match from shared to api as it is not shared (except within the API)
- This file is only used in one part of the app, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
refs https://github.com/TryGhost/members.js/issues/6
This exposes an endpoint on site url (`/members/ssr/member`) to get member's data in exchange for their session/identity on a theme when they are logged in. It essentially uses the same logic and data which is passed down to theme through handlebar helpers, and is used by members.js script to load member data.
- Moved ghost-locals from shared to parent as it is not shared
- This file is only used in one place, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
- This allows shared middleware to be unhooked from the parent app
- Moved emit-events from shared to parent as it is not shared
- This file is only used in one place, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
- Moved log-request from shared to parent as it is not shared
- This file is only used in one place, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
- Moved request-id from shared to parent as it is not shared
- This file is only used in one place, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
- Have a consistent structure so we can co-locate an app with its own middleware
- This is another small step in sorting out the giant mess that was web/shared/middleware
- Moved serve-public-file from shared to site as it is not shared
- This file is only used in one place, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
refs 717567995b
- We should not be using relative URLs inside the admin panel anymore
- Removes a usage of "shared" middleware which isn't truly shared
- Moved handle-image-sizes from shared to site as it is not shared
- This file is only used in one place, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
- Moved static-theme from shared to site as it is not shared
- This file is only used in one place, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
- Moved serve-favicon from shared to site as it is not shared
- This file is only used in one place, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
- Moved admin-redirects from shared to site as it is not shared
- This file is only used in one place, this updates the code structure to reflect this
- This is one of many similar changes needed to make it easier to refactor to the existing setup
fixes#11740
- there was a discrepancy in the use of `private_blog` within the
code, and `private_block` in the default config
- this commit switches the code to `block` in order to avoid breaking
existing configs
- the helper dir also contained some code used with helpers - utils and helper-helpers?
- the goal here was for helpers to be the only thing in their folder so we can look at moving them out
- all other code has been moved to services/themes for now, which is not the right place either
- services/themes is a catch-all for theme storage, loading, validation, rendering and more, needs to be broken down
no-issue
* Added default for getting origin of request
This function is used to attach the origin of the request to the
session, and later check that requests using the session are coming from
the same origin. This protects us against CSRF attacks as requests in
the browser MUST originate from the same origin on which the user
logged in.
Previously, when we could not determine the origin we would return
null, as a "safety" net.
This updates the function to use a secure and sensible default - which
is the origin of the Ghost-Admin application, and if that's not set -
the origin of the Ghost application.
This will make dealing with magic links simpler as you can not always
guaruntee the existence of these headers when visiting via a hyperlink
* Removed init fns and getters from session service
This simplifies the code here, making it easier to read and maintain
* Moved express-session initialisation to own file
This is complex enough that it deserves its own module
* Added createSessionFromToken to session service
* Wired up the createSessionFromToken middleware
- moved image.manipulation lib to a new package called @tryghost/image-transform
- new package has an updated API signature, so the method calls have changed but the underlying code is identical
- removed the optional sharp dependency from Ghost, as this is now optionally required by the image-transform module
- Apps are marked as removed in 3.0, never officially launched and have been deprecated for at least 2 years.
- We've slowly removed bits that got in our way or were insecure over time meaning they mostly didn't work
- This cleans up the remainder of the logic
- The tables should be cleaned up in a future major
- Apps are marked as removed in 3.0, never officially launched and have been deprecated for at least 2 years.
- We've slowly removed bits that got in our way or were insecure over time meaning they mostly didn't work
- This cleans up the remainder of the logic
- The tables should be cleaned up in a future major
no-issue
This adds two new endpoints, one at /ghost/.well-known/jwks.json for exposing
a public key, and one on the canary api /identities, which allows the
Owner user to fetch a JWT.
This token can then be used by external services to verify the domain
* Added ghost_{public,private}_key settings
This key can be used for generating tokens for communicating with
external services on behalf of Ghost
* Added .well-known directory to /ghost/.well-known
We add a jwks.json file to the .well-known directory which exposes a
public JWK which can be used to verify the signatures of JWT's created
by Ghost
This is added to the /ghost/ path so that it can live on the admin
domain, rather than the frontend. This is because most of its
uses/functions will be in relation to the admin domain.
* Improved settings model tests
This removes hardcoded positions in favour of testing that a particular
event wasn't emitted which is less brittle and more precise about what's
being tested
* Fixed parent app unit tests for well-known
This updates the parent app unit tests to check that the well-known
route is mounted. We all change proxyquire to use `noCallThru` which
ensures that the ubderlying modules are not required. This stops the
initialisation logic in ./well-known erroring in tests
https://github.com/thlorenz/proxyquire/issues/215
* Moved jwt signature to a separate 'token' propery
This structure corresponds to other resources and allows to exptend with
additional properties in future if needed
no issue
- Adds 'GET /members/:id/signin_urls' endpoint to Admin API allowing to fetch login URL for member. This URL allows to log in as a member which is useful in situations when you need to impersonate a member (for example to debug some issue they are having)
- Added member_signin_urls permission with migrations. Only the "Owner" user can read "signin_urls" resource. Admin and other users will be denied access
refs 91984b54ca
- For request effieciency we should be using a minified file just like we did previously with `ghost-sdk.js`
- Modified 'max-age' caching header to 1 year for both minified and non-minified files as thay won't affect dev environment and should be beneficial for self-hosting instances that don't use minification
- Along the way corrected an extra 301 redirect because `/public/member.js` path wasn't using a bakslach in the end.
no issue
- This functionality allows member to update their billing information, like credit card information.
- Adds handler to update Stripe billing when element with `data-members-edit-billing` attribute is present on the page. Additional `data-members-success` and `data-members-cancel` attributes could be used to control the redirects on billing update success or failure. They work in the same fission as for 'members-plan' (https://ghost.org/docs/members/checkout-buttons/#redirects)
no issue
- some errors weren't being reported because they were being passed to
Sentry before our middleware could populate the error information
- this commit inserts the Sentry middleware into these steps
no issue
- when `servePublicFile` middleware serves an image it resulted in a "Cannot set headers after they are sent to the client" error because `next()` was erroneously called for successful requests which then tripped the `prettyUrls` middleware which tries to perform a redirect
- only calling `next()` when an error is present allows errors to be picked up by later middleware but successful requests end in the `servePublicFile` middleware
no issue
* Updated sendEmailWithMagicLink syntax
* Updated label name selection from theme
* Updated migration version for labels
* Added labels to export/import of members
* Added member labels sanitization for case-insensitive duplicates
* Fixed tests
* Fixed label serialization bug on import
* Bumped @tryghost/members-api to 0.15.0
* Fixed lint
* Cleanup
no issue
- serving of our public asset images was broken
- we were reading the binary file in as a string so we could do url transforms, this meant data was lost/corrupted and browsers could not display the served data
- we were using the wrong mime-type for pngs which meant browsers were triggering downloads rather than displaying images (at least when accessed directly)
- updates uses of `servePublicFile` to have the correct png mimetype
- adjusts `servePublicFile` to treat any mime type starting with `image` as a binary file, passing the file directly through express using `res.sendFile` and skipping the in-memory content caching which is mostly only useful for text files with URL transforms
no issue
- if a request was sent for an resized image URL that didn't contain a
file extension, the code would eventually end up throwing a 500
- this commit checks for this case and returns a 404
This reverts commit 6e024331eb.
Temporarily reverting whilst we investigate an issue with Sentry and running Ghost via Ghost-CLI.
Ghost-CLI initiated boot was failing when Sentry was installed due to what appears to be `process.cwd()` returning `undefined` here https://github.com/TryGhost/Ignition/blob/master/lib/config/index.js#L26
no issue
- requests for resized images with a trailing slash would end up
throwing a EISDIR error because it got through to writing an
image buffer to a directory
- we want to cut this off early and disallow trailing slashes
no issue
- The helper allows generating HTML needed to cancel or continue the member's subscription depending on subscription state.
- Added public members endpoint to allow updating subscription's `cancel_at_period_end` attribute available at: `PUT /api/canary/members/subscriptions/:id/`
- Added client-side hook to allow calling subscription cancellation. Allows to create elements with `data-members-cancel-subscription` / `data-members-continue-subscription` attributes which would call subscription update.
- Updated schema and added migration for `current_period_end` column
- As discussed we only add a single column to subscriptions table to avoid preoptimizing for future cases
- Added {{cancel_link}} helper
- Added error handling for {{cancel_link}} when members are disabled
- Added test coverage for {{cancel_link}} helper
- Bumped @tryghost/members-api version to 0.10.2. Needed to use `updateSubscription` middleware
- Bumped gscan to 3.2.0. Needed to recognize new {{cancel_link}} helper
no-issue
Our function for determining cors options created a new instance of URL
without wrapping it in a try/catch which meant any failures to parse the
URL bubbled down as a 500 error.
500 errors are commonly used for alerting at the infrastructure level,
and this error is definitely one caused by a badly configured client, so
we wrap the construction and crap out with a Bad Request Error (HTTP
400) if it fails.
no-issue
This name `login` was misleading as this middleware didn't login
members, that was handled by the `authentication` middleware,
specifically `exchangeTokenForSession`
We want to allow admin users to trigger a retry of failed emails without having to go through the unpublish/republish dance.
- fixed resource identifier in email permissions migration so email permissions are added correctly
- added new email permissions migration so that beta releases can be upgraded without rollback (will be a no-op for any non-beta upgrades)
- added `/emails/:id/retry/` canary Admin API endpoint
- follows same URL pattern as theme activation
- only triggers mega service retry endpoint if the email has a `'failed'` status
no issue
- In order to keep site/app.js module tidy and less coupled with members module we need to extract some of the functionality where it belongs conceptually
- Added "members enabled check" middleware to stripe webhook endpoint
- Reshuffled members middleware so that siteApp is in control of mounting points. This is meant to be a more explicit way to see which endpoints are being handled by members middleware
- Extracted member-specific public file middleware
- Unified use of `labs.member` alias method. Done for code style consistency
- Added basic members' test suite. This is a base we could work from when more modifications are needed
- Removed route handler for unexisting members file "members-theme-bindings.js". Calling this route otherwise causes a 500. Looks like a leftover from 49672a1e4d
no issue
- adds new router to the frontend for handling unsubscribe
- default template lives in `core/server/frontend/views/unsubscribe.hbs`
- `{{error}}` is present and contains the error message when unsubscribe fails
- `{{member}}` is present and contains the member email
- updated unsubscribe url to match the new format
- This is a fairly temporary state
- It at least removes the themeService require from inside the routingService
- Requires us to pass the routingService the desired API Version...
- We're working towards having the entire frontend respect the theme API version by having it passed around everywhere
no issue
When using certain proxy setups that result in `host` and `x-forwarded-host` being different, it became impossible to access Ghost because all routes showed generic 404 pages.
- `vhost` module that we are using to separate front-end and admin urls does not use express' `req.hostname` so it does not pick up the `x-forwarded-host` url that express' `'trust proxy'` config gives us
- switched to the forked `@tryghost/vhost-middleware` package which has a one-line change to use `req.hostname || req.host`
- added `'trust proxy'` config to the admin express app and switched to using `req.hostname` in our redirect code to avoid infinite redirect loops
refs https://github.com/TryGhost/Ghost/pull/11152
- Added subscribers table drop migration
- Removed subscribers from schema
- Removed subscribers controllers/routes/regression tests
- Removed subscriber related API code
- Removed subscribers from internal apps
- Removed subscriber importer
- Removed subscriber model
- Removed subscriber related permissions
- Removed webhook code related to subscribers
- When upgrading to v3 it is on the site admin to migrate all zapps or any other webhook clients to use members
- Removed subscriber-specific translation
- Removed subscriber lab flag
no issue
- Improved error handling for member creation. We should be returning 422s instead of 500 when possible
- Wrapped `members.add` method with Bluebird promise. Wrapping is needed to be able to use `.reflect()` in CSV export method
- Added proper members CSV fixture
no issue
- Added Regression full test coverage for members Admin API
- Added `POST /members` endpoint
- Added members schema definition + validation
- Added ability to pass through send_email/emal_type options to members API
* Updated scheduler to use v2 API by default
* Updated scheduling for post/page resource types
* Extended base method to take options param with token and jwt options
* Updated token expiration to 6 hours after publish/blog start time to allow retries
- Currently, we create a request ID for internal use if one isn't set & this is used in logs
- If a custom request ID is set via X-Request-ID header, this gets logged, however, we don't return this with the response
- Means that a custom ID gets lost on the way back out, and makes tracing requests through a system trickier
- This change ensures that if X-Request-ID is set on the request, it is also set on the response so that requests can be properly traced
- It's easy to set this in e.g. nginx so that the feature becomes available - Ghost doens't need to do this
- Note: also split request id handling out into new middleware
no-issue
This also adds a basic check before handing of to the members-ssr
module, this should make logs a little less noisy and only log warnings
if a token was passed and that token was invalid/incorrect.
no issue
- v0.1 is ☠️ so there's no longer any use of client auth
- removes all code related to `clients` and `client_trusted_domains`
- noops the "add backup client" migration in 1.7 because the referenced fixture no longer exists causing migrations and consequently all regression tests to fail
no issue
- adds `config:redirects` config option that defaults to `true`
- when set to `false`
- `/ghost/` will 404 on the front-end when a separate admin url is configured
- all `{resource}/edit/` URLs on the front-end will 404
no issue
- Removed v0.1 controllers
- Removed 0.1 API unit tests
- Removed 0.1 API app and mount point
- Removed leftover use of v0.1 in entry-lookup test suite
- Removed frontend client API enpoints and related code (middleware)
- Fixed prev/next test suites to use v2 API
- Set default API version to explicit v2 in UrlUtils
- Removed v0.1 API regex from public files middleware
no issue
- we used to redirect paths such as `/logout/` and `/signin/` to the admin but they are no longer desired
- with the introduction of members these URLs can be confused with front-end member related actions
- we want to be able to optionally "turn off" redirects to the admin to help mask the admin url when it's configured to be separate to the front-end
no issue
- `vhost` as used in b46f9b1dc2 does not pass down the `trust proxy` setting to child apps so it's required to be called explicitly in each child app
- fixed URLs being output as http:// instead of https:// when the front-end is accessed with `x-forwarded-proto: 'https'`
no issue
- added our theme error handling middleware to {admin}/content/ so that cache headers are properly set for 404s
- only registered {admin}/content when a separate admin url is configured so that we're not overriding {site}/content
no issue
- Session controllers were using API v1 http method which bypassed "frame" introduced with API v2.
- Changes here are just a long-awaited cleanup to allow completely remove v0.1 code
no issue
- As v0.1 API is dropped there is no need to keep an API client around
- Removed references to ghost-sdk in regression test suite
- Removed routes to /public/ghost-sdk.js
- Removed reference to ghost-sdk in grunt build process
refs https://github.com/TryGhost/Ghost/issues/11083
- the `/api/v2/admin/site/` endpoint is "public" and as such was not using the `authAdminApi` middleware stack so it did not act like other API endpoints with protocol or trailing-slash redirects
- adds `publicAdminApi` middleware array and uses it for the `/site/` endpoint in both v2 and canary API versions
closes https://github.com/TryGhost/Ghost/issues/11078
Problem:
- the admin client makes an XHR request to the `/private/` endpoint when a private site is configured
- when a separate admin URL is configured this was causing 500 errors in the admin client because missing CORS headers on the endpoint was causing browsers to abort the request
- browsers will also look at the CORS headers on any resources that are the result of a redirect and abort the request if they do not allow cross-origin requests, this means allowing all requests on `/private/` is not enough
Solution:
- uses the `cors` middleware with a dynamic options function for the whole of the front-end site app
- dynamic options function allows the following requests through:
- same-origin (browsers and non-browser agents will not send an `Origin` header)
- origin is `localhost` or `127.0.0.1` with any protocol and port
- origin matches the configured `url` hostname+port on any protocol
- origin matches the configured `admin:url` hostname+port on any protocol
no issue
- when too many login attempts were detected for the `/private/` form we were throwing 500 errors instead of the more appropriate 429 error that we use everywhere else for "too many request" type errors
no-issue
* Installed members-api@0.5.0 members-ssr@0.3.1
* Supported multiple members-forms
* Used members canary api
* Added GET handler to /members/ssr for id token
The identity token will be used to ensure that a payment is linked to the correct member
* Added stripe.js to ghost_head when members enabled
* Added basic support for linking to stripe checkout
* Removed listener to title and icon settings changes
* Added stripe subscription config
closes#10060
- Implemented scheduling for posts and pages
- Added cache invalidation when scheduling
- Refactored admin token eneration function to accept existing key as parameter in tests
- Added Ghost Scheduler Integration fixture
- Added fixture for permissions for post publish action
- Migrated getScheduled method to v2
- Did not add support for 'from' and 'to' parameters as they were not used by DefaultScheduler
- This method needs rethinking in a long run as it's an ugly hack and should rather become proper endpoint that returns JSON data instead of models
- Removed unused auth middleware from v2 routes
- Added internal scheduler role
- Implemetnted transactions in v2 frame
- This takes into account scenario mentioned in c93f03b87e
- Specifically:
>if two queries happening in a transaction we have to signalise
knex/mysql that we select for an update
otherwise the following case happens:
you fetch posts for an update
a user requests comes in and updates the post (e.g. sets title to "X")
you update the fetched posts, title would get overriden to the old one
refs #10060
- Migrated authentication.resetPassword method to v2
- Migrated authentication.acceptInvitation method to v2
- Migrated authentication.setup method to v2
- Added missing test coverage for "setupUpdate" method
- Migrated authentication.updateSetup method to v2
- Migrated authentication.isInvitation method to v2
- Migrated authentication.isSetup method to v2
- Removed unused 'setup.completed' event as it wasn's used anywhere in the system and has been complicating the logic unnecessarily
- Without the event, it's possible to simplify sendNotification method to just use email address of the user
- Added email sending check to v0.1 test suite
- Refactored sendNotification method to just use email address as parameter
- Renamed sendNotification to sendWelcomeMail
- The only thing the method does now is sending welcome mail, so new naming seems natural :)
no-issue
Previously we were using the error logger, which is probably a bit
extreme for these errors. This also removes the stacktrace from the logs
so we don't enter fresh hell whilst developing/looking through logs.
refs #10932
Previously we were only applying the cors middleware to the options
preflight request, which meant that if the request errored, the cors
headers would not be applied, resulting in the client being unable to
read response data. This applies the cors middleware to _all_ requests
to the Admin API.