mirror of
https://github.com/discourse/discourse.git
synced 2024-12-30 09:15:49 +08:00
baeca887d9
Previously admins could still click on topics when `suppress_secured_categories_from_admin` was set This change improves the block so admins without permission will not be allowed to click through till they add themselves to appropriate groups Keep in mind this setting is a quality of life setting and not a SECURITY setting, admins have an infinite way of bypassing visiblity limits
300 lines
11 KiB
Ruby
300 lines
11 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe TopicGuardian do
|
|
fab!(:user) { Fabricate(:user, refresh_auto_groups: true) }
|
|
fab!(:admin)
|
|
fab!(:tl3_user) { Fabricate(:trust_level_3) }
|
|
fab!(:tl4_user) { Fabricate(:trust_level_4) }
|
|
fab!(:moderator)
|
|
fab!(:category)
|
|
fab!(:group)
|
|
fab!(:private_category) { Fabricate(:private_category, group: group) }
|
|
fab!(:topic) { Fabricate(:topic, category: category) }
|
|
fab!(:private_topic) { Fabricate(:topic, category: private_category) }
|
|
fab!(:private_message_topic)
|
|
|
|
before { Guardian.enable_topic_can_see_consistency_check }
|
|
|
|
after { Guardian.disable_topic_can_see_consistency_check }
|
|
|
|
describe "#can_create_shared_draft?" do
|
|
it "when shared_drafts are disabled" do
|
|
SiteSetting.shared_drafts_allowed_groups = Group::AUTO_GROUPS[:admins]
|
|
|
|
expect(Guardian.new(admin).can_create_shared_draft?).to eq(false)
|
|
end
|
|
|
|
it "when user is a moderator and access is set to admin" do
|
|
SiteSetting.shared_drafts_category = category.id
|
|
SiteSetting.shared_drafts_allowed_groups = Group::AUTO_GROUPS[:admins]
|
|
|
|
expect(Guardian.new(moderator).can_create_shared_draft?).to eq(false)
|
|
end
|
|
|
|
it "when user is a moderator and access is set to staff" do
|
|
SiteSetting.shared_drafts_category = category.id
|
|
SiteSetting.shared_drafts_allowed_groups = Group::AUTO_GROUPS[:staff]
|
|
|
|
expect(Guardian.new(moderator).can_create_shared_draft?).to eq(true)
|
|
end
|
|
|
|
it "when user is TL3 and access is set to TL2" do
|
|
SiteSetting.shared_drafts_category = category.id
|
|
SiteSetting.shared_drafts_allowed_groups = Group::AUTO_GROUPS[:trust_level_2]
|
|
|
|
expect(Guardian.new(tl3_user).can_create_shared_draft?).to eq(true)
|
|
end
|
|
end
|
|
|
|
describe "#can_see_shared_draft?" do
|
|
it "when shared_drafts are disabled (existing shared drafts)" do
|
|
SiteSetting.shared_drafts_allowed_groups = Group::AUTO_GROUPS[:admins]
|
|
|
|
expect(Guardian.new(admin).can_see_shared_draft?).to eq(true)
|
|
end
|
|
|
|
it "when user is a moderator and access is set to admin" do
|
|
SiteSetting.shared_drafts_category = category.id
|
|
SiteSetting.shared_drafts_allowed_groups = Group::AUTO_GROUPS[:admins]
|
|
|
|
expect(Guardian.new(moderator).can_see_shared_draft?).to eq(false)
|
|
end
|
|
|
|
it "when user is a moderator and access is set to staff" do
|
|
SiteSetting.shared_drafts_category = category.id
|
|
SiteSetting.shared_drafts_allowed_groups = Group::AUTO_GROUPS[:staff]
|
|
|
|
expect(Guardian.new(moderator).can_see_shared_draft?).to eq(true)
|
|
end
|
|
|
|
it "when user is TL3 and access is set to TL2" do
|
|
SiteSetting.shared_drafts_category = category.id
|
|
SiteSetting.shared_drafts_allowed_groups = Group::AUTO_GROUPS[:trust_level_2]
|
|
|
|
expect(Guardian.new(tl3_user).can_see_shared_draft?).to eq(true)
|
|
end
|
|
end
|
|
|
|
describe "#can_see_deleted_topics?" do
|
|
it "returns true for staff" do
|
|
expect(Guardian.new(admin).can_see_deleted_topics?(topic.category)).to eq(true)
|
|
end
|
|
|
|
it "returns true for group moderator" do
|
|
SiteSetting.enable_category_group_moderation = true
|
|
expect(Guardian.new(user).can_see_deleted_topics?(topic.category)).to eq(false)
|
|
Fabricate(:category_moderation_group, category:, group:)
|
|
group.add(user)
|
|
topic.update!(category: category)
|
|
expect(Guardian.new(user).can_see_deleted_topics?(topic.category)).to eq(true)
|
|
end
|
|
|
|
it "returns true when tl4 can delete posts and topics" do
|
|
expect(Guardian.new(tl4_user).can_see_deleted_topics?(topic.category)).to eq(false)
|
|
SiteSetting.delete_all_posts_and_topics_allowed_groups = Group::AUTO_GROUPS[:trust_level_4]
|
|
expect(Guardian.new(tl4_user).can_see_deleted_topics?(topic.category)).to eq(true)
|
|
end
|
|
|
|
it "returns false for anonymous user" do
|
|
SiteSetting.delete_all_posts_and_topics_allowed_groups = Group::AUTO_GROUPS[:trust_level_4]
|
|
expect(Guardian.new.can_see_deleted_topics?(topic.category)).to be_falsey
|
|
end
|
|
end
|
|
|
|
describe "#can_recover_topic?" do
|
|
fab!(:deleted_topic) { Fabricate(:topic, category: category, deleted_at: 1.day.ago) }
|
|
it "returns true for staff" do
|
|
expect(Guardian.new(admin).can_recover_topic?(Topic.with_deleted.last)).to eq(true)
|
|
end
|
|
|
|
it "returns true for group moderator" do
|
|
SiteSetting.enable_category_group_moderation = true
|
|
expect(Guardian.new(user).can_recover_topic?(Topic.with_deleted.last)).to eq(false)
|
|
Fabricate(:category_moderation_group, category:, group:)
|
|
group.add(user)
|
|
topic.update!(category: category)
|
|
expect(Guardian.new(user).can_recover_topic?(Topic.with_deleted.last)).to eq(true)
|
|
end
|
|
|
|
it "returns true when tl4 can delete posts and topics" do
|
|
expect(Guardian.new(tl4_user).can_recover_topic?(Topic.with_deleted.last)).to eq(false)
|
|
SiteSetting.delete_all_posts_and_topics_allowed_groups = Group::AUTO_GROUPS[:trust_level_4]
|
|
expect(Guardian.new(tl4_user).can_recover_topic?(Topic.with_deleted.last)).to eq(true)
|
|
end
|
|
|
|
it "returns false for anonymous user" do
|
|
SiteSetting.delete_all_posts_and_topics_allowed_groups = Group::AUTO_GROUPS[:trust_level_4]
|
|
expect(Guardian.new.can_recover_topic?(Topic.with_deleted.last)).to eq(false)
|
|
end
|
|
end
|
|
|
|
describe "#can_edit_topic?" do
|
|
context "when the topic is a shared draft" do
|
|
let(:tl2_user) { Fabricate(:user, trust_level: TrustLevel[2]) }
|
|
|
|
before do
|
|
SiteSetting.shared_drafts_category = category.id
|
|
SiteSetting.shared_drafts_allowed_groups = Group::AUTO_GROUPS[:trust_level_2]
|
|
end
|
|
|
|
it "returns false if the topic is a PM" do
|
|
pm_with_draft = Fabricate(:private_message_topic, category: category)
|
|
Fabricate(:shared_draft, topic: pm_with_draft)
|
|
|
|
expect(Guardian.new(tl2_user).can_edit_topic?(pm_with_draft)).to eq(false)
|
|
end
|
|
|
|
it "returns false if the topic is archived" do
|
|
archived_topic = Fabricate(:topic, archived: true, category: category)
|
|
Fabricate(:shared_draft, topic: archived_topic)
|
|
|
|
expect(Guardian.new(tl2_user).can_edit_topic?(archived_topic)).to eq(false)
|
|
end
|
|
|
|
it "returns true if a shared draft exists" do
|
|
Fabricate(:shared_draft, topic: topic)
|
|
|
|
expect(Guardian.new(tl2_user).can_edit_topic?(topic)).to eq(true)
|
|
end
|
|
|
|
it "returns false if the user has a lower trust level" do
|
|
tl1_user = Fabricate(:user, trust_level: TrustLevel[1])
|
|
Fabricate(:shared_draft, topic: topic)
|
|
|
|
expect(Guardian.new(tl1_user).can_edit_topic?(topic)).to eq(false)
|
|
end
|
|
|
|
it "returns true if the shared_draft is from a different category" do
|
|
topic = Fabricate(:topic, category: Fabricate(:category))
|
|
Fabricate(:shared_draft, topic: topic)
|
|
|
|
expect(Guardian.new(tl2_user).can_edit_topic?(topic)).to eq(false)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#is_in_edit_topic_groups?" do
|
|
it "returns true if the user is in edit_all_topic_groups" do
|
|
group.add(user)
|
|
SiteSetting.edit_all_topic_groups = group.id.to_s
|
|
|
|
expect(Guardian.new(user).is_in_edit_topic_groups?).to eq(true)
|
|
end
|
|
|
|
it "returns false if the user is not in edit_all_topic_groups" do
|
|
SiteSetting.edit_all_topic_groups = Group::AUTO_GROUPS[:trust_level_4]
|
|
|
|
expect(Guardian.new(tl3_user).is_in_edit_topic_groups?).to eq(false)
|
|
end
|
|
|
|
it "returns false if the edit_all_topic_groups is empty" do
|
|
SiteSetting.edit_all_topic_groups = nil
|
|
|
|
expect(Guardian.new(user).is_in_edit_topic_groups?).to eq(false)
|
|
end
|
|
end
|
|
|
|
describe "#can_review_topic?" do
|
|
it "returns false for TL4 users" do
|
|
topic = Fabricate(:topic)
|
|
|
|
expect(Guardian.new(tl4_user).can_review_topic?(topic)).to eq(false)
|
|
end
|
|
end
|
|
|
|
describe "#can_create_unlisted_topic?" do
|
|
it "returns true for moderators" do
|
|
expect(Guardian.new(moderator).can_create_unlisted_topic?(topic)).to eq(true)
|
|
end
|
|
|
|
it "returns true for TL4 users" do
|
|
expect(Guardian.new(tl4_user).can_create_unlisted_topic?(topic)).to eq(true)
|
|
end
|
|
|
|
it "returns false for regular users" do
|
|
expect(Guardian.new(user).can_create_unlisted_topic?(topic)).to eq(false)
|
|
end
|
|
end
|
|
|
|
describe "#can_see_unlisted_topics?" do
|
|
it "is allowed for staff users" do
|
|
expect(Guardian.new(moderator).can_see_unlisted_topics?).to eq(true)
|
|
end
|
|
|
|
it "is allowed for TL4 users" do
|
|
expect(Guardian.new(tl4_user).can_see_unlisted_topics?).to eq(true)
|
|
end
|
|
|
|
it "is not allowed for lower level users" do
|
|
expect(Guardian.new(tl3_user).can_see_unlisted_topics?).to eq(false)
|
|
end
|
|
end
|
|
|
|
# The test cases here are intentionally kept brief because majority of the cases are already handled by
|
|
# `TopicGuardianCanSeeConsistencyCheck` which we run to ensure that the implementation between `TopicGuardian#can_see_topic_ids`
|
|
# and `TopicGuardian#can_see_topic?` is consistent.
|
|
describe "#can_see_topic_ids" do
|
|
it "returns the topic ids for the topics which a user is allowed to see" do
|
|
expect(
|
|
Guardian.new.can_see_topic_ids(topic_ids: [topic.id, private_message_topic.id]),
|
|
).to contain_exactly(topic.id)
|
|
|
|
expect(
|
|
Guardian.new(user).can_see_topic_ids(topic_ids: [topic.id, private_message_topic.id]),
|
|
).to contain_exactly(topic.id)
|
|
|
|
expect(
|
|
Guardian.new(moderator).can_see_topic_ids(topic_ids: [topic.id, private_message_topic.id]),
|
|
).to contain_exactly(topic.id)
|
|
|
|
expect(
|
|
Guardian.new(admin).can_see_topic_ids(topic_ids: [topic.id, private_message_topic.id]),
|
|
).to contain_exactly(topic.id, private_message_topic.id)
|
|
end
|
|
|
|
it "returns the topic ids for topics which are deleted but user is a category moderator of" do
|
|
SiteSetting.enable_category_group_moderation = true
|
|
|
|
Fabricate(:category_moderation_group, category:, group:)
|
|
group.add(user)
|
|
topic.update!(category: category)
|
|
topic.trash!(admin)
|
|
|
|
topic2 = Fabricate(:topic)
|
|
user2 = Fabricate(:user)
|
|
|
|
expect(
|
|
Guardian.new(user).can_see_topic_ids(topic_ids: [topic.id, topic2.id]),
|
|
).to contain_exactly(topic.id, topic2.id)
|
|
|
|
expect(
|
|
Guardian.new(user2).can_see_topic_ids(topic_ids: [topic.id, topic2.id]),
|
|
).to contain_exactly(topic2.id)
|
|
end
|
|
end
|
|
|
|
describe "#filter_allowed_categories" do
|
|
it "allows admin access to categories without explicit access" do
|
|
guardian = Guardian.new(admin)
|
|
list = Topic.where(id: private_topic.id)
|
|
list = guardian.filter_allowed_categories(list)
|
|
|
|
expect(list.count).to eq(1)
|
|
end
|
|
|
|
context "when SiteSetting.suppress_secured_categories_from_admin is true" do
|
|
before { SiteSetting.suppress_secured_categories_from_admin = true }
|
|
|
|
it "does not allow admin access to categories without explicit access" do
|
|
guardian = Guardian.new(admin)
|
|
list = Topic.where(id: private_topic.id)
|
|
list = guardian.filter_allowed_categories(list)
|
|
|
|
expect(list.count).to eq(0)
|
|
|
|
expect(guardian.can_see?(private_topic)).to eq(false)
|
|
end
|
|
end
|
|
end
|
|
end
|