X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fuser%2Fquery.ex;h=ac77aab7134769f4b525c0df9ca4f9304bd9dc1a;hb=f3a1f9c3bbb7321876a09b3846b5e10ecf4af94f;hp=2baf016cfd3f3ecb7f269eb8f6e7faa0e92b63da;hpb=c1e011624d33052d4d473ebfb4e0c1ff7d2327dd;p=akkoma diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex index 2baf016cf..2440bf890 100644 --- a/lib/pleroma/user/query.ex +++ b/lib/pleroma/user/query.ex @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors +# Copyright © 2017-2020 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.User.Query do @@ -28,6 +28,8 @@ defmodule Pleroma.User.Query do """ import Ecto.Query import Pleroma.Web.AdminAPI.Search, only: [not_empty_string: 1] + + alias Pleroma.FollowingRelationship alias Pleroma.User @type criteria :: @@ -40,26 +42,28 @@ defmodule Pleroma.User.Query do external: boolean(), active: boolean(), deactivated: boolean(), + need_approval: boolean(), is_admin: boolean(), is_moderator: boolean(), super_users: boolean(), + invisible: boolean(), + internal: boolean(), followers: User.t(), friends: User.t(), recipients_from_activity: [String.t()], - nickname: [String.t()], + nickname: [String.t()] | String.t(), ap_id: [String.t()], order_by: term(), select: term(), limit: pos_integer() } - | %{} + | map() @ilike_criteria [:nickname, :name, :query] @equal_criteria [:email] - @role_criteria [:is_admin, :is_moderator] @contains_criteria [:ap_id, :nickname] - @spec build(criteria()) :: Query.t() + @spec build(Query.t(), criteria()) :: Query.t() def build(query \\ base_query(), criteria) do prepare_query(query, criteria) end @@ -77,7 +81,9 @@ defmodule Pleroma.User.Query do end defp prepare_query(query, criteria) do - Enum.reduce(criteria, query, &compose_query/2) + criteria + |> Map.put_new(:internal, false) + |> Enum.reduce(query, &compose_query/2) end defp compose_query({key, value}, query) @@ -87,6 +93,10 @@ defmodule Pleroma.User.Query do where(query, [u], ilike(field(u, ^key), ^"%#{value}%")) end + defp compose_query({:invisible, bool}, query) when is_boolean(bool) do + where(query, [u], u.invisible == ^bool) + end + defp compose_query({key, value}, query) when key in @equal_criteria and not_empty_string(value) do where(query, [u], ^[{key, value}]) @@ -97,18 +107,22 @@ defmodule Pleroma.User.Query do end defp compose_query({:tags, tags}, query) when is_list(tags) and length(tags) > 0 do - Enum.reduce(tags, query, &prepare_tag_criteria/2) + where(query, [u], fragment("? && ?", u.tags, ^tags)) end - defp compose_query({key, _}, query) when key in @role_criteria do - where(query, [u], fragment("(?->? @> 'true')", u.info, ^to_string(key))) + defp compose_query({:is_admin, bool}, query) do + where(query, [u], u.is_admin == ^bool) + end + + defp compose_query({:is_moderator, bool}, query) do + where(query, [u], u.is_moderator == ^bool) end defp compose_query({:super_users, _}, query) do where( query, [u], - fragment("?->'is_admin' @> 'true' OR ?->'is_moderator' @> 'true'", u.info, u.info) + u.is_admin or u.is_moderator ) end @@ -117,8 +131,13 @@ defmodule Pleroma.User.Query do defp compose_query({:external, _}, query), do: location_query(query, false) defp compose_query({:active, _}, query) do - where(query, [u], fragment("not (?->'deactivated' @> 'true')", u.info)) - |> where([u], not is_nil(u.nickname)) + User.restrict_deactivated(query) + |> where([u], u.approval_pending == false) + end + + defp compose_query({:legacy_active, _}, query) do + query + |> where([u], fragment("not (?->'deactivated' @> 'true')", u.info)) end defp compose_query({:deactivated, false}, query) do @@ -126,22 +145,50 @@ defmodule Pleroma.User.Query do end defp compose_query({:deactivated, true}, query) do - where(query, [u], fragment("?->'deactivated' @> 'true'", u.info)) - |> where([u], not is_nil(u.nickname)) + where(query, [u], u.deactivated == ^true) end - defp compose_query({:followers, %User{id: id, follower_address: follower_address}}, query) do - where(query, [u], fragment("? <@ ?", ^[follower_address], u.following)) + defp compose_query({:confirmation_pending, bool}, query) do + where(query, [u], u.confirmation_pending == ^bool) + end + + defp compose_query({:need_approval, _}, query) do + where(query, [u], u.approval_pending) + end + + defp compose_query({:followers, %User{id: id}}, query) do + query |> where([u], u.id != ^id) + |> join(:inner, [u], r in FollowingRelationship, + as: :relationships, + on: r.following_id == ^id and r.follower_id == u.id + ) + |> where([relationships: r], r.state == ^:follow_accept) end - defp compose_query({:friends, %User{id: id, following: following}}, query) do - where(query, [u], u.follower_address in ^following) + defp compose_query({:friends, %User{id: id}}, query) do + query |> where([u], u.id != ^id) + |> join(:inner, [u], r in FollowingRelationship, + as: :relationships, + on: r.following_id == u.id and r.follower_id == ^id + ) + |> where([relationships: r], r.state == ^:follow_accept) end defp compose_query({:recipients_from_activity, to}, query) do - where(query, [u], u.ap_id in ^to or fragment("? && ?", u.following, ^to)) + following_query = + from(u in User, + join: f in FollowingRelationship, + on: u.id == f.following_id, + where: f.state == ^:follow_accept, + where: u.follower_address in ^to, + select: f.follower_id + ) + + from(u in query, + where: u.ap_id in ^to or u.id in subquery(following_query) + ) end defp compose_query({:order_by, key}, query) do @@ -156,14 +203,15 @@ defmodule Pleroma.User.Query do limit(query, ^limit) end - defp compose_query(_unsupported_param, query), do: query - - defp prepare_tag_criteria(tag, query) do - or_where(query, [u], fragment("? = any(?)", ^tag, u.tags)) + defp compose_query({:internal, false}, query) do + query + |> where([u], not is_nil(u.nickname)) + |> where([u], not like(u.nickname, "internal.%")) end + defp compose_query(_unsupported_param, query), do: query + defp location_query(query, local) do where(query, [u], u.local == ^local) - |> where([u], not is_nil(u.nickname)) end end