TryGhost / Ghost

Independent technology for modern publishing, memberships, subscriptions and newsletters.
https://ghost.org
MIT License
47.39k stars 10.34k forks source link

Ghost fires updated webhooks before save/update is fully completed - Edit lock, unable to save #18626

Closed mheland closed 1 year ago

mheland commented 1 year ago

Issue Summary

Alternate heading: "Trigger happy Ghost shoots itself in the foot"

When integrating external services it appears that Ghost fires the Page Updated / Post Updated webhook before the save is fully completed. If the integration immediately modifies the Post/Page over admin-API v3 Ghost will generate a Edit Lock error and post can not be saved.

Have been able to replicate this on GhostPro & digitalpress.blog hosting - does not happen on a single-ghost-no-cdn VPS installation DigitalOcean/Hetzner etc...

edit-lock

Steps to Reproduce

  1. Add integrations with webhooks triggering on Page Updated / Post Updated
  2. Make the integration instantly modify the post/page over admin-API, ex assign a tag, update Twitter/Facebook image etc
  3. Create post - add media and cards to the post - things that take time to process/save.
  4. Attempt save, update or publish post - Edit Lock "Someone else is updating this page" triggers.

Expected results: Post / Page is updated. Actual results: Ghost reports Edit lock - "Someone else is editing this page" unable to save edits. Disabling the webhook resolves the problem.

Ghost Version

5.68.0

Node.js Version

Docker on my VPS ghost:5-alpine

How did you install Ghost?

VPS - Docker / Debian

Database type

MySQL 8

Browser & OS version

No response

Relevant log / error output

Pls see screenshot attached
Unable to see logs on GhostPro, support case with Bob @Ghost identified this issue...

=== Saving the post and triggering webhook
84.243.57.21 - - [14/Oct/2023:10:12:59 +0000] "PUT /ghost/api/admin/posts/652a69a0b1e08a0001b9f13e/?formats=mobiledoc%2Clexical HTTP/1.1" 200 1251 "https://my.vps/ghost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"

Integration updates the post six seconds later....
159.89.30.148 - - [14/Oct/2023:10:13:06 +0000] "PUT /ghost/api/v3/admin/posts/652a69a0b1e08a0001b9f13e HTTP/1.1" 200 5395 "-" "GuzzleHttp/7"

Code of Conduct

kevinansfield commented 1 year ago

This is expected, the web hook is firing at the right time but you're modifying a post whilst it's still open in the editor and therefore causing the editor and the server state to become out of sync in the same way as if someone else was editing the post. In this case someone else is editing the post, it's just that it's a bot rather than a real person.

Whilst a post is a draft any changes are continually saved, each of those saves will trigger the post updated web hook.

Having an external tool modifying a post on every save will always cause this issue. I would suggest updating your external integration to only make changes when a post is published, although even then you'll run into the same issue if you continue to make changes in the editor after publishing. The web hooks system is designed to trigger changes in external systems, not to facilitate modifications of posts/pages whilst they are being edited.

mheland commented 1 year ago

Hi Kevin, the strange thing is that the integration/hooks works on my VPS, does not generate a Edit Lock error, the integration updates Twitter/Facebook cards in the background on every save/update, even when in Draft mode, and when editing published posts.

On GhostPro / digitalpress.blog hosting enabling the integration throws the Edit Lock error.

I'm talking to the people who made the integration (placid.app) - are there any new flags in the admin-API v3 to not request an edit lock or similar?

Possibly related to GhostPro / digitalpress.blog using storage adapters and CDN's?

kevinansfield commented 1 year ago

I can't explain how it's working on your VPS because if what you say the integration is doing is successful it will always break the ability to edit posts if it does it's thing whilst the post is open in the editor. Storage adapters, CDNs, or specific hosting setups won't have any effect as the out-of-sync detection is part of Ghost's core.

The flow looks like this:

  1. The admin area saves and gets the updated post back with an updated_at value that matches what's on the server
  2. The integration triggers and performs a new save causing the updated_at value to update on the server - there's no way for the admin area to know about this change
  3. The admin area saves again but will send the updated_at value that it got in step 1
  4. The server detects the mismatch and throws the error because it shows an unintentional overwrite of the last person to edit's work
mheland commented 1 year ago

Thank you, seems I have an edge-case. Reminds me of previous job with Linux digital signage hardware where we had random reboots. A Linux kernel dev at $200/hr in a room with 50 mediaplayers, waiting for the the reboot to trigger on one of them. We called it the Neutrino Observatory. Pls close this and I'll continue talking to Placid to see if we can fix this. Tx /m