mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-04-20 02:03:59 +02:00
Merge c53fb342b6
into 78550a6322
This commit is contained in:
commit
d9817b9714
5 changed files with 84 additions and 25 deletions
lib
philomena
philomena_query/ecto
philomena_web/plugs
|
@ -49,8 +49,8 @@ defmodule Philomena.Filters.Filter do
|
|||
|> validate_required([:name])
|
||||
|> validate_my_downvotes(:spoilered_complex_str)
|
||||
|> validate_my_downvotes(:hidden_complex_str)
|
||||
|> validate_query(:spoilered_complex_str, &Query.compile(&1, user: user))
|
||||
|> validate_query(:hidden_complex_str, &Query.compile(&1, user: user))
|
||||
|> validate_query(:spoilered_complex_str, &Query.compile(&1, user: user, filter: true))
|
||||
|> validate_query(:hidden_complex_str, &Query.compile(&1, user: user, filter: true))
|
||||
|> unsafe_validate_unique([:user_id, :name], Repo)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
defmodule Philomena.Images.Query do
|
||||
alias PhilomenaQuery.Parse.Parser
|
||||
alias Philomena.Repo
|
||||
alias Philomena.Filters.Filter
|
||||
import Ecto.Query
|
||||
|
||||
defp gallery_id_transform(_ctx, value) do
|
||||
case Integer.parse(value) do
|
||||
|
@ -12,6 +14,29 @@ defmodule Philomena.Images.Query do
|
|||
end
|
||||
end
|
||||
|
||||
defp filter_id_transform(%{filter: true}, _value),
|
||||
do: {:error, "Filter queries inside filters are not allowed."}
|
||||
|
||||
defp filter_id_transform(%{user: user} = ctx, value) do
|
||||
with {value, ""} <- Integer.parse(value),
|
||||
{:ok, filter} <- Map.fetch(ctx.filters, value),
|
||||
true <- Canada.Can.can?(user, :show, filter) do
|
||||
ctx = Map.merge(ctx, %{filter: true})
|
||||
|
||||
{:ok,
|
||||
%{
|
||||
bool: %{
|
||||
must_not: [
|
||||
%{terms: %{tag_ids: filter.hidden_tag_ids}},
|
||||
invalid_filter_guard(ctx, filter.hidden_complex_str)
|
||||
]
|
||||
}
|
||||
}}
|
||||
else
|
||||
_ -> {:error, "Invalid filter `#{value}`."}
|
||||
end
|
||||
end
|
||||
|
||||
defp user_my_transform(%{user: %{id: id}}, "faves"),
|
||||
do: {:ok, %{term: %{favourited_by_user_ids: id}}}
|
||||
|
||||
|
@ -59,8 +84,8 @@ defmodule Philomena.Images.Query do
|
|||
defp user_my_transform(_ctx, _value),
|
||||
do: {:error, "Unknown `my' value."}
|
||||
|
||||
defp invalid_filter_guard(ctx, search_string) do
|
||||
case parse(user_fields(), ctx, PhilomenaQuery.Parse.String.normalize(search_string)) do
|
||||
defp invalid_filter_guard(%{user: user} = ctx, search_string) do
|
||||
case parse(fields_for(user), ctx, PhilomenaQuery.Parse.String.normalize(search_string)) do
|
||||
{:ok, query} -> query
|
||||
_error -> %{match_all: %{}}
|
||||
end
|
||||
|
@ -92,9 +117,12 @@ defmodule Philomena.Images.Query do
|
|||
~W(faved_by orig_sha512_hash sha512_hash uploader source_url original_format mime_type file_name),
|
||||
bool_fields: ~W(animated processed thumbnails_generated),
|
||||
ngram_fields: ~W(description),
|
||||
custom_fields: ~W(gallery_id),
|
||||
custom_fields: ~W(gallery_id filter_id),
|
||||
default_field: {"namespaced_tags.name", :term},
|
||||
transforms: %{"gallery_id" => &gallery_id_transform/2},
|
||||
transforms: %{
|
||||
"gallery_id" => &gallery_id_transform/2,
|
||||
"filter_id" => &filter_id_transform/2
|
||||
},
|
||||
aliases: %{
|
||||
"faved_by" => "favourited_by_users",
|
||||
"faved_by_id" => "favourited_by_user_ids"
|
||||
|
@ -138,28 +166,56 @@ defmodule Philomena.Images.Query do
|
|||
)
|
||||
end
|
||||
|
||||
defp parse(fields, context, query_string) do
|
||||
fields
|
||||
|> Parser.new()
|
||||
|> Parser.parse(query_string, context)
|
||||
defp parse_filter_ids(query_string),
|
||||
do:
|
||||
Regex.scan(~r/\bfilter_id:(\d+)/, query_string, capture: :all_but_first)
|
||||
|> List.flatten()
|
||||
|> Enum.map(&String.to_integer/1)
|
||||
|> Enum.filter(&(&1 <= 2_147_483_647))
|
||||
|
||||
defp load_filters([], _context), do: {:ok, %{}}
|
||||
|
||||
defp load_filters(_ids, %{filter: true}),
|
||||
do: {:error, "Filter queries inside filters are not allowed."}
|
||||
|
||||
defp load_filters(ids, _context) do
|
||||
filters =
|
||||
Filter
|
||||
|> where([f], f.id in ^ids)
|
||||
|> Repo.all()
|
||||
|> Map.new(&{&1.id, &1})
|
||||
|
||||
{:ok, filters}
|
||||
end
|
||||
|
||||
defp prepare_context(context, query_string) do
|
||||
with {:ok, filters} <- query_string |> parse_filter_ids() |> load_filters(context) do
|
||||
{:ok, Map.merge(context, %{filters: filters})}
|
||||
end
|
||||
end
|
||||
|
||||
defp parse(fields, context, query_string) do
|
||||
case prepare_context(context, query_string) do
|
||||
{:ok, context} ->
|
||||
fields
|
||||
|> Parser.new()
|
||||
|> Parser.parse(query_string, context)
|
||||
|
||||
{:error, error} ->
|
||||
{:error, error}
|
||||
end
|
||||
end
|
||||
|
||||
defp fields_for(nil), do: anonymous_fields()
|
||||
defp fields_for(%{role: role}) when role in ~W(user assistant), do: user_fields()
|
||||
defp fields_for(%{role: role}) when role in ~W(moderator admin), do: moderator_fields()
|
||||
defp fields_for(_), do: raise(ArgumentError, "Unknown user role.")
|
||||
|
||||
def compile(query_string, opts \\ []) do
|
||||
user = Keyword.get(opts, :user)
|
||||
watch = Keyword.get(opts, :watch, false)
|
||||
filter = Keyword.get(opts, :filter, false)
|
||||
|
||||
case user do
|
||||
nil ->
|
||||
parse(anonymous_fields(), %{user: nil, watch: watch}, query_string)
|
||||
|
||||
%{role: role} when role in ~W(user assistant) ->
|
||||
parse(user_fields(), %{user: user, watch: watch}, query_string)
|
||||
|
||||
%{role: role} when role in ~W(moderator admin) ->
|
||||
parse(moderator_fields(), %{user: user, watch: watch}, query_string)
|
||||
|
||||
_ ->
|
||||
raise ArgumentError, "Unknown user role."
|
||||
end
|
||||
parse(fields_for(user), %{user: user, watch: watch, filter: filter}, query_string)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -62,6 +62,9 @@ defmodule PhilomenaQuery.Ecto.QueryValidator do
|
|||
{:ok, _} <- callback.(value) do
|
||||
changeset
|
||||
else
|
||||
{:error, msg} ->
|
||||
add_error(changeset, attr, "is invalid: #{msg}")
|
||||
|
||||
_ ->
|
||||
add_error(changeset, attr, "is invalid")
|
||||
end
|
||||
|
|
|
@ -55,7 +55,7 @@ defmodule PhilomenaWeb.FilterForcedUsersPlug do
|
|||
defp compile_filter(user, search_string) do
|
||||
search_string
|
||||
|> String.normalize()
|
||||
|> Query.compile(user: user)
|
||||
|> Query.compile(user: user, filter: true)
|
||||
|> case do
|
||||
{:ok, query} -> query
|
||||
_error -> %{match_all: %{}}
|
||||
|
|
|
@ -51,7 +51,7 @@ defmodule PhilomenaWeb.ImageFilterPlug do
|
|||
defp invalid_filter_guard(user, search_string) do
|
||||
search_string
|
||||
|> String.normalize()
|
||||
|> Query.compile(user: user)
|
||||
|> Query.compile(user: user, filter: true)
|
||||
|> case do
|
||||
{:ok, query} -> query
|
||||
_error -> %{match_all: %{}}
|
||||
|
|
Loading…
Add table
Reference in a new issue