modqueue: fix the disapproved: metatag showing posts outside the queue.

Fix a bug where filtering the modqueue by the `disapproved:<reason>` tag
would return posts outside the modqueue.
This commit is contained in:
evazion
2022-09-29 22:30:14 -05:00
parent d51cc17eaf
commit 559bf1ae0a
4 changed files with 49 additions and 4 deletions

View File

@@ -9,6 +9,22 @@ module Searchable
relation.where(all.where_clause.invert.ast)
end
# Combine two relations like `ActiveRecord::Relation#and`, but allow structurally incompatible relations.
def and_relation(relation)
q = all
raise "incompatible FROM clauses: #{q.to_sql}; #{relation.to_sql}" if !q.from_clause.empty? && q.from_clause != relation.from_clause
raise "incompatible GROUP BY clauses: #{q.to_sql}; #{relation.to_sql}" if !q.group_values.empty? && q.group_values != relation.group_values
q = q.select(q.select_values + relation.select_values) if !relation.select_values.empty?
q = q.from(relation.from_clause.value) if !relation.from_clause.empty?
q = q.joins(relation.joins_values + q.joins_values) if relation.joins_values.present?
q = q.where(relation.where_clause.ast) if relation.where_clause.present?
q = q.group(relation.group_values) if relation.group_values.present?
q = q.order(relation.order_values) if relation.order_values.present? && !relation.reordering_value
q = q.reorder(relation.order_values) if relation.order_values.present? && relation.reordering_value
q
end
# Search a table column by an Arel operator.
#
# @see https://github.com/rails/rails/blob/master/activerecord/lib/arel/predications.rb

View File

@@ -1391,7 +1391,7 @@ class Post < ApplicationRecord
post_query = PostQuery.normalize(query, current_user: user, tag_limit: tag_limit, safe_mode: safe_mode)
post_query.validate_tag_limit!
posts = post_query.with_implicit_metatags.posts
merge(posts)
and_relation(posts)
end
def search(params, current_user)
@@ -1409,7 +1409,7 @@ class Post < ApplicationRecord
)
if params[:tags].present?
q = q.user_tag_match(params[:tags], current_user)
q = q.where(id: user_tag_match(params[:tags], current_user).select(:id))
end
if params[:order].present?

View File

@@ -58,6 +58,16 @@ class ModqueueControllerTest < ActionDispatch::IntegrationTest
assert_equal([], response.parsed_body.pluck("id"))
end
should "filter the disapproved:<reason> metatag correctly" do
post1 = create(:post, is_pending: true)
post2 = create(:post, is_deleted: true)
create(:post_disapproval, post: post2, reason: "poor_quality")
get_auth modqueue_index_path(search: { tags: "disapproved:poor_quality" }), @admin, as: :json
assert_response :success
assert_equal([], response.parsed_body.pluck("id"))
end
should "include appealed posts in the modqueue" do
@appeal = create(:post_appeal)
get_auth modqueue_index_path, @admin

View File

@@ -1,8 +1,8 @@
require 'test_helper'
class PostQueryBuilderTest < ActiveSupport::TestCase
def assert_tag_match(posts, query, current_user: CurrentUser.user, tag_limit: nil, **options)
assert_equal(posts.map(&:id), Post.user_tag_match(query, current_user, tag_limit: tag_limit, **options).pluck("posts.id"))
def assert_tag_match(posts, query, relation: Post.all, current_user: CurrentUser.user, tag_limit: nil, **options)
assert_equal(posts.map(&:id), relation.user_tag_match(query, current_user, tag_limit: tag_limit, **options).pluck("posts.id"))
end
def assert_search_error(query, current_user: CurrentUser.user, **options)
@@ -1481,6 +1481,25 @@ class PostQueryBuilderTest < ActiveSupport::TestCase
assert_tag_match([post2, post1], "id:#{post1.id} or rating:q")
end
should "work on a relation with pre-existing scopes" do
post1 = create(:post, rating: "g", is_pending: true, tag_string: ["1girl"])
post2 = create(:post, rating: "s", is_flagged: true, tag_string: ["1boy"])
create(:post_disapproval, post: post2, reason: "poor_quality")
assert_tag_match([post1], "1girl", relation: Post.pending)
assert_tag_match([post1], "1girl", relation: Post.in_modqueue)
assert_tag_match([post1], "1boy", relation: Post.in_modqueue)
assert_tag_match([post2, post1], "comments:0", relation: Post.in_modqueue)
assert_tag_match([post2, post1], "comments:0 notes:0", relation: Post.in_modqueue)
assert_tag_match([post2], "-1girl", relation: Post.in_modqueue)
assert_tag_match([post2], "disapproved:poor_quality", relation: Post.in_modqueue)
assert_tag_match([], "rating:g", relation: Post.where(rating: "e"))
assert_tag_match([], "id:#{post1.id}", relation: Post.where(id: 0))
assert_tag_match([], "order:artcomm", relation: Post.in_modqueue)
end
should "not allow conflicting order metatags" do
assert_search_error("order:score ordfav:a")
assert_search_error("order:score ordfavgroup:a")