summaryrefslogtreecommitdiff
path: root/app/models/node.rb
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-07-10 23:54:38 +0200
committererdgeist <erdgeist@erdgeist.org>2026-07-10 23:54:38 +0200
commitab392d472c15eee3618cb7c02b2b4707151598b6 (patch)
tree70743f8fa0df9b75b0debb8f2724ea947ad99175 /app/models/node.rb
parent7d6a665b896252537b8b8df2f15e204d04417231 (diff)
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.
Diffstat (limited to 'app/models/node.rb')
-rw-r--r--app/models/node.rb5
1 files changed, 5 insertions, 0 deletions
diff --git a/app/models/node.rb b/app/models/node.rb
index 82d9954..9cb4840 100644
--- a/app/models/node.rb
+++ b/app/models/node.rb
@@ -227,6 +227,11 @@ class Node < ApplicationRecord
227 227
228 if staged_parent_id && (staged_parent_id != parent_id) 228 if staged_parent_id && (staged_parent_id != parent_id)
229 new_parent = Node.find(staged_parent_id) 229 new_parent = Node.find(staged_parent_id)
230
231 if new_parent == self || self.descendants.include?(new_parent)
232 raise ActiveRecord::RecordInvalid.new(self), "Cannot move a node under itself or one of its own descendants"
233 end
234
230 self.staged_parent_id = nil 235 self.staged_parent_id = nil
231 self.save! 236 self.save!
232 self.move_to_child_of(new_parent) 237 self.move_to_child_of(new_parent)