search: fix searches for private favgroups raising privilege errors.

Change favgroup:<name> searches to return no results instead of raising
a UserPrivilege error when an unpermitted user searches for a private
favgroup.

Partial fix for #4389.
This commit is contained in:
evazion
2020-04-16 18:55:53 -05:00
parent 3aa80c8dc4
commit f8d420d6c0
4 changed files with 46 additions and 23 deletions

View File

@@ -485,12 +485,14 @@ class PostQueryBuilder
relation = relation.joins("JOIN (#{pool_posts.to_sql}) pool_posts ON pool_posts.post_id = posts.id").order("pool_posts.pool_index ASC") relation = relation.joins("JOIN (#{pool_posts.to_sql}) pool_posts ON pool_posts.post_id = posts.id").order("pool_posts.pool_index ASC")
end end
q[:favgroups_neg].to_a.each do |favgroup| q[:favgroup_neg].to_a.each do |favgroup_name|
relation = relation.where.not(id: FavoriteGroup.where(id: favgroup.id).select("unnest(post_ids)")) favgroup = FavoriteGroup.visible(CurrentUser.user).name_or_id_matches(favgroup_name, CurrentUser.user)
relation = relation.where.not(id: favgroup.select("unnest(post_ids)"))
end end
q[:favgroups].to_a.each do |favgroup| q[:favgroup].to_a.each do |favgroup_name|
relation = relation.where(id: FavoriteGroup.where(id: favgroup.id).select("unnest(post_ids)")) favgroup = FavoriteGroup.visible(CurrentUser.user).name_or_id_matches(favgroup_name, CurrentUser.user)
relation = relation.where(id: favgroup.select("unnest(post_ids)"))
end end
q[:upvoter].to_a.each do |upvoter| q[:upvoter].to_a.each do |upvoter|
@@ -782,18 +784,12 @@ class PostQueryBuilder
q[:ordpool] = g2 q[:ordpool] = g2
when "-favgroup" when "-favgroup"
favgroup = FavoriteGroup.find_by_name_or_id!(g2, CurrentUser.user) q[:favgroup_neg] ||= []
raise User::PrivilegeError unless Pundit.policy!([CurrentUser.user, nil], favgroup).show? q[:favgroup_neg] << g2
q[:favgroups_neg] ||= []
q[:favgroups_neg] << favgroup
when "favgroup" when "favgroup"
favgroup = FavoriteGroup.find_by_name_or_id!(g2, CurrentUser.user) q[:favgroup] ||= []
raise User::PrivilegeError unless Pundit.policy!([CurrentUser.user, nil], favgroup).show? q[:favgroup] << g2
q[:favgroups] ||= []
q[:favgroups] << favgroup
when "-fav" when "-fav"
favuser = User.find_by_name(g2) favuser = User.find_by_name(g2)

View File

@@ -52,7 +52,7 @@ module PostSets
name = Tag.has_metatag?(tag_array, :favgroup) name = Tag.has_metatag?(tag_array, :favgroup)
return nil unless is_single_tag? && name.present? return nil unless is_single_tag? && name.present?
@favgroup ||= FavoriteGroup.find_by_name_or_id(name, CurrentUser.user) @favgroup ||= FavoriteGroup.visible(CurrentUser.user).find_by_name_or_id(name, CurrentUser.user)
end end
def has_explicit? def has_explicit?

View File

@@ -89,14 +89,18 @@ class FavoriteGroup < ApplicationRecord
self.name = FavoriteGroup.normalize_name(name) self.name = FavoriteGroup.normalize_name(name)
end end
def self.find_by_name_or_id(name, user) def self.name_or_id_matches(name, user)
if name =~ /\A\d+\z/ if name =~ /\A\d+\z/
find_by(id: name) where(id: name)
else else
user.favorite_groups.where_iequals(:name, normalize_name(name)).first where(creator: user).where_iequals(:name, normalize_name(name))
end end
end end
def self.find_by_name_or_id(name, user)
name_or_id_matches(name, user).first
end
def self.find_by_name_or_id!(name, user) def self.find_by_name_or_id!(name, user)
find_by_name_or_id(name, user) or raise ActiveRecord::RecordNotFound find_by_name_or_id(name, user) or raise ActiveRecord::RecordNotFound
end end

View File

@@ -2092,12 +2092,35 @@ class PostTest < ActiveSupport::TestCase
end end
should "return posts for the favgroup:<name> metatag" do should "return posts for the favgroup:<name> metatag" do
favgroups = FactoryBot.create_list(:favorite_group, 2, creator: CurrentUser.user) post1 = create(:post)
posts = favgroups.map { |g| FactoryBot.create(:post, tag_string: "favgroup:#{g.name}") } post2 = create(:post)
post3 = create(:post)
assert_tag_match([posts[0]], "favgroup:#{favgroups[0].name}") favgroup1 = create(:favorite_group, creator: CurrentUser.user, post_ids: [post1.id])
assert_tag_match([posts[1]], "-favgroup:#{favgroups[0].name}") favgroup2 = create(:favorite_group, creator: CurrentUser.user, post_ids: [post2.id])
assert_tag_match([], "-favgroup:#{favgroups[0].name} -favgroup:#{favgroups[1].name}") favgroup3 = create(:favorite_group, creator: create(:user), post_ids: [post3.id], is_public: false)
assert_tag_match([post1], "favgroup:#{favgroup1.id}")
assert_tag_match([post2], "favgroup:#{favgroup2.name}")
assert_tag_match([], "favgroup:#{favgroup3.name}")
assert_tag_match([], "favgroup:dne")
assert_tag_match([post3, post2], "-favgroup:#{favgroup1.id}")
assert_tag_match([post3, post1], "-favgroup:#{favgroup2.name}")
assert_tag_match([post3, post2, post1], "-favgroup:#{favgroup3.name}")
assert_tag_match([post3, post2, post1], "-favgroup:dne")
assert_tag_match([post3], "-favgroup:#{favgroup1.name} -favgroup:#{favgroup2.name}")
as(favgroup3.creator) do
assert_tag_match([post1], "favgroup:#{favgroup1.id}")
assert_tag_match([post2], "favgroup:#{favgroup2.id}")
assert_tag_match([post3], "favgroup:#{favgroup3.id}")
assert_tag_match([], "favgroup:#{favgroup1.name}")
assert_tag_match([], "favgroup:#{favgroup2.name}")
assert_tag_match([post3], "favgroup:#{favgroup3.name}")
end
end end
should "return posts for the user:<name> metatag" do should "return posts for the user:<name> metatag" do