summaryrefslogtreecommitdiff
path: root/test/models/node_test.rb
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-07-31 18:14:30 +0200
committererdgeist <erdgeist@erdgeist.org>2026-07-31 18:14:30 +0200
commit464af1625349d557f688da9f845471ef8b80a5f9 (patch)
treeaab415abf115f20ccbcdfad49c27ce5d1bd61134 /test/models/node_test.rb
parent8c6a6516e1dc5c1b4f12740a6f7b32765b530bb7 (diff)
Gate live-content changes on restricted surfaces
publish_draft!, trash!, destroy_from_trash!, attach_asset! and Asset#destroy_witnessed! now refuse unless the acting user holds redaktion, and only when the subject is on a restricted surface: the front page, the updates tree that feeds ~100k subscribers, or disclosure. Drafting, autosaving, tagging and creating stay free everywhere for everyone. Enforcement is in the models rather than the controllers, since attach_asset! and the rest are reachable from rake tasks and internal paths. It follows the errors.add-plus-bare-raise pattern the rest of Node already uses, so every existing RecordInvalid rescue reports it with a localised message; only assets_controller#destroy needed a rescue added. A nil user is treated as a system context and bypasses the gate. The default nil on three of those verbs is what makes that reachable, and removing those defaults once every call site passes a user is the next tightening.
Diffstat (limited to 'test/models/node_test.rb')
-rw-r--r--test/models/node_test.rb68
1 files changed, 68 insertions, 0 deletions
diff --git a/test/models/node_test.rb b/test/models/node_test.rb
index c1316ea6..f57f83bf 100644
--- a/test/models/node_test.rb
+++ b/test/models/node_test.rb
@@ -936,4 +936,72 @@ class NodeTest < ActiveSupport::TestCase
936 I18n.t("activerecord.errors.models.node.attributes.base.trash_the_trash") 936 I18n.t("activerecord.errors.models.node.attributes.base.trash_the_trash")
937 end 937 end
938 end 938 end
939
940 test "restricted? covers the root node, the restricted subtrees and their descendants" do
941 assert Node.root.restricted?, "the front page aggregates the feed"
942
943 updates = Node.root.children.create!(:slug => "updates")
944 assert updates.restricted?
945 year = updates.children.create!(:slug => "2026")
946 assert year.reload.restricted?
947 post = year.children.create!(:slug => "some-post")
948 assert post.reload.restricted?
949
950 disclosure = Node.root.children.create!(:slug => "disclosure")
951 assert disclosure.restricted?
952
953 plain = Node.root.children.create!(:slug => "club")
954 assert_not plain.restricted?
955 child = plain.children.create!(:slug => "erfas")
956 assert_not child.reload.restricted?
957 end
958
959 test "restricted? does not match a prefix that is merely a substring" do
960 decoy = Node.root.children.create!(:slug => "updatesomething")
961 assert_not decoy.restricted?
962 end
963
964 test "publishing a restricted node is refused without the redaktion role" do
965 editor = User.create!(:login => "guard_editor", :email => "gd@example.com",
966 :password => "secret", :password_confirmation => "secret")
967 updates = Node.root.children.create!(:slug => "updates")
968 node = updates.children.create!(:slug => "guarded-post")
969 node.reload.draft.update!(:title => "Entwurf")
970
971 error = assert_raises(ActiveRecord::RecordInvalid) { node.publish_draft!(editor) }
972 assert_includes error.message,
973 I18n.t("activerecord.errors.models.node.attributes.base.not_permitted")
974 assert_nil node.reload.head
975 end
976
977 test "publishing a restricted node succeeds with the redaktion role" do
978 red = User.create!(:login => "guard_red", :email => "gr2@example.com",
979 :password => "secret", :password_confirmation => "secret",
980 :roles => ["redaktion"])
981 updates = Node.root.children.create!(:slug => "updates")
982 node = updates.children.create!(:slug => "allowed-post")
983 node.reload.draft.update!(:title => "Entwurf")
984
985 node.publish_draft!(red)
986 assert_not_nil node.reload.head
987 end
988
989 test "publishing outside the restricted subtrees needs no role" do
990 editor = User.create!(:login => "guard_free", :email => "gf@example.com",
991 :password => "secret", :password_confirmation => "secret")
992 node = Node.root.children.create!(:slug => "guard-free-post")
993 node.reload.draft.update!(:title => "Entwurf")
994
995 node.publish_draft!(editor)
996 assert_not_nil node.reload.head
997 end
998
999 test "a nil user is a system context and bypasses the gate" do
1000 updates = Node.root.children.create!(:slug => "updates")
1001 node = updates.children.create!(:slug => "system-post")
1002 node.reload.draft.update!(:title => "Entwurf")
1003
1004 node.publish_draft!
1005 assert_not_nil node.reload.head
1006 end
939end 1007end