diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-07-31 20:41:05 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-07-31 20:41:05 +0200 |
| commit | 3b4e1423635fd9f33ae760312e438cc1e484662e (patch) | |
| tree | 0dd81aaf26ab5e4d7e178563f120b3e203c4dc0b /app/models | |
| parent | 683526b38442a9873d83a542b5cba1d15efc14d5 (diff) | |
Show the gate before it refuses, and check the destination
nodes#show renders publish and trash as disabled_action spans with a hint
naming what an editor can still do, matching how locked_by_other already
reads. Editing and reverting stay live: drafting is free everywhere.
Diffstat (limited to 'app/models')
| -rw-r--r-- | app/models/node.rb | 23 | ||||
| -rw-r--r-- | app/models/user.rb | 6 |
2 files changed, 22 insertions, 7 deletions
diff --git a/app/models/node.rb b/app/models/node.rb index ac3a6160..188b6c17 100644 --- a/app/models/node.rb +++ b/app/models/node.rb | |||
| @@ -236,7 +236,7 @@ class Node < ApplicationRecord | |||
| 236 | # Return nil if nothing to publish and no staged changes | 236 | # Return nil if nothing to publish and no staged changes |
| 237 | return nil unless self.draft || staged_slug || staged_parent_id | 237 | return nil unless self.draft || staged_slug || staged_parent_id |
| 238 | 238 | ||
| 239 | guard_live_change!(current_user) | 239 | guard_live_change!(current_user, :target_path => prospective_unique_name) |
| 240 | 240 | ||
| 241 | if in_trash? || trash_node? | 241 | if in_trash? || trash_node? |
| 242 | errors.add(:base, :publish_in_trash) | 242 | errors.add(:base, :publish_in_trash) |
| @@ -574,10 +574,8 @@ class Node < ApplicationRecord | |||
| 574 | false | 574 | false |
| 575 | end | 575 | end |
| 576 | 576 | ||
| 577 | def restricted? | 577 | def self.restricted_path? name |
| 578 | return true if root? | 578 | name = name.to_s |
| 579 | |||
| 580 | name = unique_name.to_s | ||
| 581 | return false if name.empty? | 579 | return false if name.empty? |
| 582 | 580 | ||
| 583 | CccConventions::RESTRICTED_SUBTREES.any? do |prefix| | 581 | CccConventions::RESTRICTED_SUBTREES.any? do |prefix| |
| @@ -585,6 +583,17 @@ class Node < ApplicationRecord | |||
| 585 | end | 583 | end |
| 586 | end | 584 | end |
| 587 | 585 | ||
| 586 | def restricted? | ||
| 587 | root? || self.class.restricted_path?(unique_name) | ||
| 588 | end | ||
| 589 | |||
| 590 | def prospective_unique_name | ||
| 591 | target_parent = staged_parent_id ? Node.find_by(:id => staged_parent_id) : parent | ||
| 592 | return nil unless target_parent | ||
| 593 | |||
| 594 | [target_parent.unique_name.presence, staged_slug.presence || slug].compact.join("/") | ||
| 595 | end | ||
| 596 | |||
| 588 | # Returns immutable node id for all new nodes so that the atom feed entry ids | 597 | # Returns immutable node id for all new nodes so that the atom feed entry ids |
| 589 | # stay the same eventhough the slug or positions changes. | 598 | # stay the same eventhough the slug or positions changes. |
| 590 | # Can be removed after a year or so ;) | 599 | # Can be removed after a year or so ;) |
| @@ -697,9 +706,9 @@ class Node < ApplicationRecord | |||
| 697 | 706 | ||
| 698 | private | 707 | private |
| 699 | 708 | ||
| 700 | def guard_live_change! user | 709 | def guard_live_change! user, target_path: nil |
| 701 | return if user.nil? | 710 | return if user.nil? |
| 702 | return if user.may_change_live?(self) | 711 | return if user.may_change_live?(self) && user.may_change_live_at?(target_path) |
| 703 | 712 | ||
| 704 | errors.add(:base, :not_permitted) | 713 | errors.add(:base, :not_permitted) |
| 705 | raise ActiveRecord::RecordInvalid.new(self) | 714 | raise ActiveRecord::RecordInvalid.new(self) |
diff --git a/app/models/user.rb b/app/models/user.rb index e8c3b9bb..bf0f40ee 100644 --- a/app/models/user.rb +++ b/app/models/user.rb | |||
| @@ -110,6 +110,12 @@ class User < ApplicationRecord | |||
| 110 | redaktion? | 110 | redaktion? |
| 111 | end | 111 | end |
| 112 | 112 | ||
| 113 | def may_change_live_at?(path) | ||
| 114 | return true if path.nil? | ||
| 115 | return true unless Node.restricted_path?(path) | ||
| 116 | redaktion? | ||
| 117 | end | ||
| 118 | |||
| 113 | def deactivate!(actor:) | 119 | def deactivate!(actor:) |
| 114 | return false if alumni? | 120 | return false if alumni? |
| 115 | transaction do | 121 | transaction do |
