mirror of
https://github.com/discourse/discourse.git
synced 2026-08-08 17:53:55 +08:00
Previously managing topic timers was staff + TL4 only. This moves the logic to a group site setting so that other groups can set timers.
440 lines
17 KiB
Ruby
Vendored
440 lines
17 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe TopicGuardian do
|
|
fab!(:user) { Fabricate(:user, refresh_auto_groups: true) }
|
|
fab!(:admin)
|
|
fab!(:tl3_user, :trust_level_3)
|
|
fab!(:tl4_user, :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 false for a category group moderator who cannot see the topic" do
|
|
SiteSetting.enable_category_group_moderation = true
|
|
mod_group = Fabricate(:group)
|
|
cat_mod_user = Fabricate(:user)
|
|
private_cat = Fabricate(:private_category, group: Fabricate(:group))
|
|
private_t = Fabricate(:topic, category: private_cat, deleted_at: 1.day.ago)
|
|
Fabricate(:category_moderation_group, category: private_cat, group: mod_group)
|
|
mod_group.add(cat_mod_user)
|
|
|
|
expect(Guardian.new(cat_mod_user).can_recover_topic?(private_t)).to eq(false)
|
|
end
|
|
|
|
it "returns true for a category group moderator who can see the topic" do
|
|
SiteSetting.enable_category_group_moderation = true
|
|
mod_group = Fabricate(:group)
|
|
cat_mod_user = Fabricate(:user)
|
|
private_cat = Fabricate(:private_category, group: mod_group)
|
|
private_t = Fabricate(:topic, category: private_cat, deleted_at: 1.day.ago)
|
|
Fabricate(:category_moderation_group, category: private_cat, group: mod_group)
|
|
mod_group.add(cat_mod_user)
|
|
|
|
expect(Guardian.new(cat_mod_user).can_recover_topic?(private_t)).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 "#can_delete_topic?" do
|
|
it "returns false for an unauthenticated user" do
|
|
expect(Guardian.new.can_delete_topic?(topic)).to be_falsey
|
|
end
|
|
|
|
it "returns false for a regular user" do
|
|
expect(Guardian.new(Fabricate(:user)).can_delete_topic?(topic)).to be_falsey
|
|
end
|
|
|
|
it "returns true for a moderator" do
|
|
expect(Guardian.new(moderator).can_delete_topic?(topic)).to be_truthy
|
|
end
|
|
|
|
it "returns true for an admin" do
|
|
expect(Guardian.new(admin).can_delete_topic?(topic)).to be_truthy
|
|
end
|
|
|
|
it "returns false for static doc topics" do
|
|
tos_topic = Fabricate(:topic, user: Discourse.system_user)
|
|
SiteSetting.tos_topic_id = tos_topic.id
|
|
expect(Guardian.new(admin).can_delete_topic?(tos_topic)).to be_falsey
|
|
end
|
|
|
|
it "returns false when topic is trashed" do
|
|
topic.stubs(:trashed?).returns(true)
|
|
expect(Guardian.new(admin).can_delete_topic?(topic)).to be_falsey
|
|
end
|
|
|
|
it "returns false when topic is category topic" do
|
|
topic.stubs(:is_category_topic?).returns(true)
|
|
expect(Guardian.new(admin).can_delete_topic?(topic)).to be_falsey
|
|
end
|
|
|
|
it "returns true for own topic with no replies" do
|
|
topic.update_attribute(:posts_count, 1)
|
|
topic.update_attribute(:created_at, Time.zone.now)
|
|
expect(Guardian.new(topic.user).can_delete_topic?(topic)).to be_truthy
|
|
end
|
|
|
|
it "returns false for own topic with replies" do
|
|
topic.update!(posts_count: 2, created_at: Time.zone.now)
|
|
expect(Guardian.new(topic.user).can_delete_topic?(topic)).to be_falsey
|
|
end
|
|
|
|
it "returns false for own topic within cooldown period" do
|
|
topic.update!(posts_count: 1, created_at: 48.hours.ago)
|
|
expect(Guardian.new(topic.user).can_delete_topic?(topic)).to be_falsey
|
|
end
|
|
|
|
it "returns true for user in allowed groups" do
|
|
SiteSetting.delete_all_posts_and_topics_allowed_groups = Group::AUTO_GROUPS[:trust_level_4]
|
|
expect(Guardian.new(tl4_user).can_delete_topic?(topic)).to be_truthy
|
|
end
|
|
|
|
it "returns false for user not in allowed groups" do
|
|
SiteSetting.delete_all_posts_and_topics_allowed_groups = Group::AUTO_GROUPS[:trust_level_4]
|
|
expect(Guardian.new(tl3_user).can_delete_topic?(topic)).to be_falsey
|
|
end
|
|
|
|
context "when category group moderation is enabled" do
|
|
fab!(:group_user)
|
|
|
|
before { SiteSetting.enable_category_group_moderation = true }
|
|
|
|
it "returns false if user is not a member of the appropriate group" do
|
|
expect(Guardian.new(group_user.user).can_delete_topic?(topic)).to be_falsey
|
|
end
|
|
|
|
it "returns true if user is a member of the appropriate group" do
|
|
Fabricate(:category_moderation_group, category: topic.category, group: group_user.group)
|
|
|
|
expect(Guardian.new(group_user.user).can_delete_topic?(topic)).to be_truthy
|
|
end
|
|
|
|
it "returns false for a category group moderator who cannot see the topic" do
|
|
mod_group = Fabricate(:group)
|
|
cat_mod_user = Fabricate(:user)
|
|
private_cat = Fabricate(:private_category, group: Fabricate(:group))
|
|
private_t = Fabricate(:topic, category: private_cat)
|
|
Fabricate(:category_moderation_group, category: private_cat, group: mod_group)
|
|
mod_group.add(cat_mod_user)
|
|
|
|
expect(Guardian.new(cat_mod_user).can_delete_topic?(private_t)).to be_falsey
|
|
end
|
|
|
|
it "returns true for a category group moderator who can see the topic" do
|
|
mod_group = Fabricate(:group)
|
|
cat_mod_user = Fabricate(:user)
|
|
private_cat = Fabricate(:private_category, group: mod_group)
|
|
private_t = Fabricate(:topic, category: private_cat)
|
|
Fabricate(:category_moderation_group, category: private_cat, group: mod_group)
|
|
mod_group.add(cat_mod_user)
|
|
|
|
expect(Guardian.new(cat_mod_user).can_delete_topic?(private_t)).to be_truthy
|
|
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 blank" do
|
|
SiteSetting.edit_all_topic_groups = ""
|
|
|
|
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_set_topic_timer?" do
|
|
it "uses topic_timers_allowed_groups and requires topic visibility" do
|
|
expect(Guardian.new(admin).can_set_topic_timer?(topic)).to eq(true)
|
|
expect(Guardian.new(moderator).can_set_topic_timer?(topic)).to eq(true)
|
|
expect(Guardian.new(tl4_user).can_set_topic_timer?(topic)).to eq(true)
|
|
expect(Guardian.new(tl3_user).can_set_topic_timer?(topic)).to eq(false)
|
|
|
|
group.add(user)
|
|
SiteSetting.topic_timers_allowed_groups = group.id.to_s
|
|
|
|
inaccessible_private_topic =
|
|
Fabricate(:topic, category: Fabricate(:private_category, group: Fabricate(:group)))
|
|
|
|
expect(Guardian.new(user.reload).can_set_topic_timer?(topic)).to eq(true)
|
|
expect(Guardian.new(tl4_user).can_set_topic_timer?(topic)).to eq(false)
|
|
expect(Guardian.new(user).can_set_topic_timer?(inaccessible_private_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
|