search: add unaliased:<tag> metatag.

* Add unaliased:<tag> metatag. This allows you to search for a tag
  without applying aliases. This is mainly useful for debugging purposes
  and for searching for large tags that are in the process of being
  aliased but haven't had all their posts moved yet.

* Remove the "raw" url param from the posts index page. The "raw" param
  also caused the search to ignore aliases, but it was undocumented and
  exploitable. It was possible to use the raw param to view private
  favorites since favorites are treated like a hidden tag.
This commit is contained in:
evazion
2020-04-30 12:14:28 -05:00
parent 986bc6e314
commit 2cbe4d3672
7 changed files with 31 additions and 12 deletions

View File

@@ -10,7 +10,7 @@ class PostsController < ApplicationController
end
else
tag_query = params[:tags] || params.dig(:post, :tags)
@post_set = PostSets::Post.new(tag_query, params[:page], params[:limit], raw: params[:raw], random: params[:random], format: params[:format])
@post_set = PostSets::Post.new(tag_query, params[:page], params[:limit], random: params[:random], format: params[:format])
@posts = authorize @post_set.posts, policy_class: PostPolicy
respond_with(@posts) do |format|
format.atom

View File

@@ -24,6 +24,7 @@ class PostQueryBuilder
ordpool note comment commentary id rating locked source status filetype
disapproved parent child search embedded md5 width height mpixels ratio
score favcount filesize date age order limit tagcount pixiv_id pixiv
unaliased
] + COUNT_METATAGS + COUNT_METATAG_SYNONYMS + CATEGORY_COUNT_METATAGS
ORDER_METATAGS = %w[
@@ -157,6 +158,8 @@ class PostQueryBuilder
favorites_include(value)
when "ordfav"
ordfav_matches(value)
when "unaliased"
unaliased_matches(value)
when "user"
user_matches(:uploader, value)
when "approver"
@@ -198,6 +201,15 @@ class PostQueryBuilder
Post.where("posts.tag_index @@ to_tsquery('danbooru', E?)", query)
end
def unaliased_matches(tag)
# don't let users use unaliased:fav:1 to view private favorites
if tag =~ /\Afav:\d+\z/
Post.none
else
tags_include(tag)
end
end
def attribute_matches(value, field, type = :integer)
operator, *args = parse_metatag_value(value, type)
Post.where_operator(field, operator, *args)

View File

@@ -1,14 +1,13 @@
module PostSets
class Post
MAX_PER_PAGE = 200
attr_reader :page, :raw, :random, :post_count, :format, :tag_string, :query
attr_reader :page, :random, :post_count, :format, :tag_string, :query
def initialize(tags, page = 1, per_page = nil, raw: false, random: false, format: "html")
def initialize(tags, page = 1, per_page = nil, random: false, format: "html")
@query = PostQueryBuilder.new(tags)
@tag_string = tags
@page = page
@per_page = per_page
@raw = raw.to_s.truthy?
@random = random.to_s.truthy?
@format = format.to_s
end
@@ -101,8 +100,6 @@ module PostSets
if is_random?
temp = get_random_posts
elsif raw
temp = ::Post.raw_tag_match(tag_string).order("posts.id DESC").where("true /* PostSets::Post#posts:1 */").paginate(page, :count => post_count, :limit => per_page)
else
temp = ::Post.tag_match(tag_string).where("true /* PostSets::Post#posts:2 */").paginate(page, :count => post_count, :limit => per_page)
end

View File

@@ -7,7 +7,7 @@ class PostPresenter
return "<em>none</em>".html_safe
end
if !options[:show_deleted] && post.is_deleted? && options[:tags] !~ /status:(?:all|any|deleted|banned)/ && !options[:raw]
if !options[:show_deleted] && post.is_deleted? && options[:tags] !~ /status:(?:all|any|deleted|banned)/
return ""
end

View File

@@ -11,7 +11,7 @@ module PostSetPresenters
end
posts.each do |post|
html << PostPresenter.preview(post, options.merge(:tags => @post_set.tag_string, :raw => @post_set.raw))
html << PostPresenter.preview(post, options.merge(:tags => @post_set.tag_string))
html << "\n"
end
@@ -19,7 +19,7 @@ module PostSetPresenters
end
def not_shown(post, options)
!options[:show_deleted] && post.is_deleted? && @post_set.tag_string !~ /status:(?:all|any|deleted|banned)/ && !@post_set.raw
!options[:show_deleted] && post.is_deleted? && @post_set.tag_string !~ /status:(?:all|any|deleted|banned)/
end
def none_shown(options)

View File

@@ -3,9 +3,6 @@
<section id="search-box">
<h1>Search</h1>
<%= form_tag(path, method: "get", id: "search-box-form") do %>
<% if params[:raw] %>
<%= hidden_field_tag :raw, params[:raw] %>
<% end %>
<% if params[:random] %>
<%= hidden_field_tag :random, params[:random] %>
<% end %>

View File

@@ -951,6 +951,19 @@ class PostQueryBuilderTest < ActiveSupport::TestCase
assert_tag_match([post], "filesize:1048576b")
end
should "return posts for an unaliased:<tag> search" do
post = create(:post, tag_string: "gray_eyes fav:self")
create(:tag_alias, antecedent_name: "gray_eyes", consequent_name: "grey_eyes")
assert_tag_match([], "gray_eyes")
assert_tag_match([post], "-gray_eyes")
assert_tag_match([post], "unaliased:gray_eyes")
assert_tag_match([], "-unaliased:gray_eyes")
assert_tag_match([], "unaliased:fav:#{CurrentUser.id}")
end
should "not perform fuzzy matching for an exact filesize search" do
post = create(:post, file_size: 1.megabyte)