diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-07-06 13:52:28 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-07-06 13:52:28 +0200 |
| commit | 889e15eabbe107d2642fdd8aa3f03821058c00dc (patch) | |
| tree | 5016fbf2fd673063c90608ae36406bd350dd34a2 | |
| parent | 9e63a6bec1b4ccc45dd684f7b6a941b75f9b9cf0 (diff) | |
Fix shared preview links breaking after a second publish
A token's page could stop being node.head_id (superseded by a newer
draft) while still being published_at.present? - the old check only
compared against the current head, so a superseded page fell through
to direct rendering instead of redirecting, serving a stale frozen
snapshot indefinitely instead of the current live content.
Also handles scheduled publishing correctly: a page can be head_id but
not yet public? (published_at in the future) - that case must still
render directly, not redirect into a 404 on the not-yet-live public
URL.
| -rw-r--r-- | app/controllers/shared_previews_controller.rb | 9 | ||||
| -rw-r--r-- | test/models/page_test.rb | 35 |
2 files changed, 41 insertions, 3 deletions
diff --git a/app/controllers/shared_previews_controller.rb b/app/controllers/shared_previews_controller.rb index a8a540f..d482466 100644 --- a/app/controllers/shared_previews_controller.rb +++ b/app/controllers/shared_previews_controller.rb | |||
| @@ -1,9 +1,14 @@ | |||
| 1 | class SharedPreviewsController < ApplicationController | 1 | class SharedPreviewsController < ApplicationController |
| 2 | def show | 2 | def show |
| 3 | @page = Page.find_by!(preview_token: params[:token]) | 3 | @page = Page.find_by!(preview_token: params[:token]) |
| 4 | node = @page.node | ||
| 4 | 5 | ||
| 5 | if @page.node && @page.node.head_id == @page.id | 6 | was_published = @page.published_at.present? |
| 6 | redirect_to node_path(@page.node) | 7 | superseded = was_published && node && node.head_id != @page.id |
| 8 | currently_public = was_published && node && node.head_id == @page.id && @page.public? | ||
| 9 | |||
| 10 | if superseded || currently_public | ||
| 11 | redirect_to node_path(node) | ||
| 7 | return | 12 | return |
| 8 | end | 13 | end |
| 9 | 14 | ||
diff --git a/test/models/page_test.rb b/test/models/page_test.rb index afba8b5..ad2742f 100644 --- a/test/models/page_test.rb +++ b/test/models/page_test.rb | |||
| @@ -142,5 +142,38 @@ class PageTest < ActiveSupport::TestCase | |||
| 142 | update = updates2009.children.create!( :slug => "my-first-update" ) | 142 | update = updates2009.children.create!( :slug => "my-first-update" ) |
| 143 | assert_equal "update", update.draft.template_name | 143 | assert_equal "update", update.draft.template_name |
| 144 | end | 144 | end |
| 145 | 145 | ||
| 146 | test "a page scheduled for future publication is not yet public even after being published" do | ||
| 147 | node = Node.root.children.create!(slug: "preview-scheduled-test") | ||
| 148 | draft = node.find_or_create_draft(@user1) | ||
| 149 | draft.title = "Scheduled test" | ||
| 150 | draft.published_at = 1.day.from_now | ||
| 151 | draft.save! | ||
| 152 | token = draft.ensure_preview_token! | ||
| 153 | |||
| 154 | node.publish_draft! | ||
| 155 | page = Page.find_by(preview_token: token) | ||
| 156 | |||
| 157 | assert_equal page.id, page.node.head_id | ||
| 158 | assert_not page.public? | ||
| 159 | end | ||
| 160 | |||
| 161 | test "a superseded page is no longer the head, even though it was once published" do | ||
| 162 | node = Node.root.children.create!(slug: "preview-superseded-test") | ||
| 163 | first_draft = node.find_or_create_draft(@user1) | ||
| 164 | first_draft.title = "First version" | ||
| 165 | first_draft.save! | ||
| 166 | first_token = first_draft.ensure_preview_token! | ||
| 167 | node.publish_draft! | ||
| 168 | |||
| 169 | second_draft = node.find_or_create_draft(@user1) | ||
| 170 | second_draft.title = "Second version" | ||
| 171 | second_draft.save! | ||
| 172 | node.publish_draft! | ||
| 173 | |||
| 174 | first_page = Page.find_by(preview_token: first_token) | ||
| 175 | |||
| 176 | assert_not_equal first_page.id, first_page.node.head_id | ||
| 177 | assert first_page.published_at.present? | ||
| 178 | end | ||
| 146 | end | 179 | end |
