From 889e15eabbe107d2642fdd8aa3f03821058c00dc Mon Sep 17 00:00:00 2001 From: erdgeist Date: Mon, 6 Jul 2026 13:52:28 +0200 Subject: 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. --- app/controllers/shared_previews_controller.rb | 9 +++++-- 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 @@ class SharedPreviewsController < ApplicationController def show @page = Page.find_by!(preview_token: params[:token]) + node = @page.node - if @page.node && @page.node.head_id == @page.id - redirect_to node_path(@page.node) + was_published = @page.published_at.present? + superseded = was_published && node && node.head_id != @page.id + currently_public = was_published && node && node.head_id == @page.id && @page.public? + + if superseded || currently_public + redirect_to node_path(node) return end 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 update = updates2009.children.create!( :slug => "my-first-update" ) assert_equal "update", update.draft.template_name end - + + test "a page scheduled for future publication is not yet public even after being published" do + node = Node.root.children.create!(slug: "preview-scheduled-test") + draft = node.find_or_create_draft(@user1) + draft.title = "Scheduled test" + draft.published_at = 1.day.from_now + draft.save! + token = draft.ensure_preview_token! + + node.publish_draft! + page = Page.find_by(preview_token: token) + + assert_equal page.id, page.node.head_id + assert_not page.public? + end + + test "a superseded page is no longer the head, even though it was once published" do + node = Node.root.children.create!(slug: "preview-superseded-test") + first_draft = node.find_or_create_draft(@user1) + first_draft.title = "First version" + first_draft.save! + first_token = first_draft.ensure_preview_token! + node.publish_draft! + + second_draft = node.find_or_create_draft(@user1) + second_draft.title = "Second version" + second_draft.save! + node.publish_draft! + + first_page = Page.find_by(preview_token: first_token) + + assert_not_equal first_page.id, first_page.node.head_id + assert first_page.published_at.present? + end end -- cgit v1.3