From ab392d472c15eee3618cb7c02b2b4707151598b6 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Fri, 10 Jul 2026 23:54:38 +0200 Subject: Prevent a staged parent move from crashing on its own descendant publish_draft! called move_to_child_of before validating the new parent at all. Staging a node under one of its own descendants created a real, if transient, cycle in parent_id the instant that save landed -- and update_unique_names_of_children's after_save callback, which recurses down through parent_id with no cycle check and no depth limit, bounced between the two nodes forever, crashing the whole process with a SystemStackError rather than just producing bad data. Now rejected up front with a normal ActiveRecord::RecordInvalid. --- test/models/node_test.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'test/models') diff --git a/test/models/node_test.rb b/test/models/node_test.rb index 280614e..5626384 100644 --- a/test/models/node_test.rb +++ b/test/models/node_test.rb @@ -499,4 +499,16 @@ class NodeTest < ActiveSupport::TestCase node.autosave!({title: "v3"}, user) assert_equal [[:head, :draft], [:draft, :autosave]], node.available_layer_pairs # state D end + + test "publishing a staged move under one's own descendant is rejected, not allowed to crash" do + a = Node.root.children.create!(:slug => "cycle_guard_a") + b = a.children.create!(:slug => "cycle_guard_b") + + a.staged_parent_id = b.id + + assert_raises(ActiveRecord::RecordInvalid) { a.publish_draft! } + + a.reload + assert_equal Node.root.id, a.parent_id + end end -- cgit v1.3