New: can_see_groups? method for better perf

This commit is contained in:
romanrizzi 2019-05-29 19:40:43 -03:00 committed by Guo Xiang Tan
parent e7ee556e87
commit 2fa8df7cd2
3 changed files with 129 additions and 1 deletions

View File

@ -15,7 +15,7 @@ class UserSearch
@limit = opts[:limit] || 20 @limit = opts[:limit] || 20
@groups = opts[:groups] @groups = opts[:groups]
@guardian = Guardian.new(@searching_user) @guardian = Guardian.new(@searching_user)
@groups.each { |group| @guardian.ensure_can_see_group!(group) } if @groups @guardian.ensure_can_see_groups!(@groups) if @groups
end end
def scoped_users def scoped_users

View File

@ -208,6 +208,25 @@ class Guardian
true true
end end
def can_see_groups?(groups)
return false if groups.blank?
return true if groups.all? { |g| g.visibility_level == Group.visibility_levels[:public] }
return true if is_admin?
return true if is_staff? && groups.all? { |g| g.visibility_level == Group.visibility_levels[:staff] }
return false if user.blank?
memberships = GroupUser.where(group: groups, user_id: user.id).pluck(:owner)
return false if memberships.empty? || memberships.length < groups.size
if !memberships.all?
return false if groups.all? { |g| g.visibility_level == Group.visibility_levels[:owners] }
return false if groups.all? { |g| g.visibility_level == Group.visibility_levels[:staff] }
end
true
end
# Can we impersonate this user? # Can we impersonate this user?
def can_impersonate?(target) def can_impersonate?(target)
target && target &&

View File

@ -3038,6 +3038,115 @@ describe Guardian do
end end
describe '#can_see_groups?' do
it 'correctly handles owner visibile groups' do
group = Group.new(name: 'group', visibility_level: Group.visibility_levels[:owners])
member = Fabricate(:user)
group.add(member)
group.save!
owner = Fabricate(:user)
group.add_owner(owner)
group.reload
expect(Guardian.new(admin).can_see_groups?([group])).to eq(true)
expect(Guardian.new(moderator).can_see_groups?([group])).to eq(false)
expect(Guardian.new(member).can_see_groups?([group])).to eq(false)
expect(Guardian.new.can_see_groups?([group])).to eq(false)
expect(Guardian.new(owner).can_see_groups?([group])).to eq(true)
end
it 'correctly handles the case where the user does not own every group' do
group = Group.new(name: 'group', visibility_level: Group.visibility_levels[:owners])
group2 = Group.new(name: 'group2', visibility_level: Group.visibility_levels[:owners])
group2.save!
member = Fabricate(:user)
group.add(member)
group.save!
owner = Fabricate(:user)
group.add_owner(owner)
group.reload
expect(Guardian.new(admin).can_see_groups?([group, group2])).to eq(true)
expect(Guardian.new(moderator).can_see_groups?([group, group2])).to eq(false)
expect(Guardian.new(member).can_see_groups?([group, group2])).to eq(false)
expect(Guardian.new.can_see_groups?([group, group2])).to eq(false)
expect(Guardian.new(owner).can_see_groups?([group, group2])).to eq(false)
end
it 'correctly handles staff visibile groups' do
group = Group.new(name: 'group', visibility_level: Group.visibility_levels[:staff])
member = Fabricate(:user)
group.add(member)
group.save!
owner = Fabricate(:user)
group.add_owner(owner)
group.reload
expect(Guardian.new(member).can_see_groups?([group])).to eq(false)
expect(Guardian.new(admin).can_see_groups?([group])).to eq(true)
expect(Guardian.new(moderator).can_see_groups?([group])).to eq(true)
expect(Guardian.new(owner).can_see_groups?([group])).to eq(true)
expect(Guardian.new.can_see_groups?([group])).to eq(false)
end
it 'correctly handles member visibile groups' do
group = Group.new(name: 'group', visibility_level: Group.visibility_levels[:members])
member = Fabricate(:user)
group.add(member)
group.save!
owner = Fabricate(:user)
group.add_owner(owner)
group.reload
expect(Guardian.new(moderator).can_see_groups?([group])).to eq(false)
expect(Guardian.new.can_see_groups?([group])).to eq(false)
expect(Guardian.new(admin).can_see_groups?([group])).to eq(true)
expect(Guardian.new(member).can_see_groups?([group])).to eq(true)
expect(Guardian.new(owner).can_see_groups?([group])).to eq(true)
end
it 'correctly handles the case where the user is not a member of every group' do
group1 = Group.new(name: 'group', visibility_level: Group.visibility_levels[:members])
group2 = Group.new(name: 'group2', visibility_level: Group.visibility_levels[:members])
group2.save!
member = Fabricate(:user)
group1.add(member)
group1.save!
owner = Fabricate(:user)
group1.add_owner(owner)
group1.reload
expect(Guardian.new(moderator).can_see_groups?([group1, group2])).to eq(false)
expect(Guardian.new.can_see_groups?([group1, group2])).to eq(false)
expect(Guardian.new(admin).can_see_groups?([group1, group2])).to eq(true)
expect(Guardian.new(member).can_see_groups?([group1, group2])).to eq(false)
expect(Guardian.new(owner).can_see_groups?([group1, group2])).to eq(false)
end
it 'correctly handles public groups' do
group = Group.new(name: 'group', visibility_level: Group.visibility_levels[:public])
expect(Guardian.new.can_see_groups?([group])).to eq(true)
end
it 'correctly handles there case where not every group is public' do
group1 = Group.new(name: 'group', visibility_level: Group.visibility_levels[:public])
group2 = Group.new(name: 'group', visibility_level: Group.visibility_levels[:private])
expect(Guardian.new.can_see_groups?([group1, group2])).to eq(false)
end
end
context 'topic featured link category restriction' do context 'topic featured link category restriction' do
before { SiteSetting.topic_featured_link_enabled = true } before { SiteSetting.topic_featured_link_enabled = true }
let(:guardian) { Guardian.new } let(:guardian) { Guardian.new }