diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pleroma/user.ex | 14 | ||||
-rw-r--r-- | lib/pleroma/user/query.ex | 4 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 75 | ||||
-rw-r--r-- | lib/pleroma/web/common_api/activity_draft.ex | 16 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex | 1 |
5 files changed, 94 insertions, 16 deletions
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 477237756..b451202b2 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -832,6 +832,7 @@ defmodule Pleroma.User do def set_cache(%User{} = user) do Cachex.put(:user_cache, "ap_id:#{user.ap_id}", user) Cachex.put(:user_cache, "nickname:#{user.nickname}", user) + Cachex.put(:user_cache, "friends_ap_ids:#{user.nickname}", get_user_friends_ap_ids(user)) {:ok, user} end @@ -847,9 +848,22 @@ defmodule Pleroma.User do end end + def get_user_friends_ap_ids(user) do + from(u in User.get_friends_query(user), select: u.ap_id) + |> Repo.all() + end + + @spec get_cached_user_friends_ap_ids(User.t()) :: [String.t()] + def get_cached_user_friends_ap_ids(user) do + Cachex.fetch!(:user_cache, "friends_ap_ids:#{user.ap_id}", fn _ -> + get_user_friends_ap_ids(user) + end) + end + def invalidate_cache(user) do Cachex.del(:user_cache, "ap_id:#{user.ap_id}") Cachex.del(:user_cache, "nickname:#{user.nickname}") + Cachex.del(:user_cache, "friends_ap_ids:#{user.ap_id}") end @spec get_cached_by_ap_id(String.t()) :: User.t() | nil diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex index ec88088cf..ac77aab71 100644 --- a/lib/pleroma/user/query.ex +++ b/lib/pleroma/user/query.ex @@ -54,13 +54,13 @@ defmodule Pleroma.User.Query do select: term(), limit: pos_integer() } - | %{} + | map() @ilike_criteria [:nickname, :name, :query] @equal_criteria [:email] @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 diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index c67b3335d..8b170b7f8 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -270,9 +270,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do ), {:ok, activity} <- insert(create_data, local, fake), {:fake, false, activity} <- {:fake, fake, activity}, + {:quick_insert, false, activity} <- {:quick_insert, quick_insert?, activity}, _ <- increase_replies_count_if_reply(create_data), _ <- increase_poll_votes_if_vote(create_data), - {:quick_insert, false, activity} <- {:quick_insert, quick_insert?, activity}, {:ok, _actor} <- increase_note_count_if_public(actor, activity), :ok <- maybe_federate(activity) do {:ok, activity} @@ -700,12 +700,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do do: [opts["user"].ap_id | User.following(opts["user"])] ++ public, else: public + opts = Map.put(opts, "user", opts["user"]) + from(activity in Activity) |> maybe_preload_objects(opts) |> maybe_preload_bookmarks(opts) |> maybe_set_thread_muted_field(opts) |> restrict_blocked(opts) - |> restrict_recipients(recipients, opts["user"]) + |> restrict_recipients(recipients, opts) |> where( [activity], fragment( @@ -740,7 +742,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do @spec fetch_public_activities(map(), Pagination.type()) :: [Activity.t()] def fetch_public_activities(opts \\ %{}, pagination \\ :keyset) do - opts = Map.drop(opts, ["user"]) + opts = + opts + |> Map.put("reply_user", opts["user"]) + |> Map.delete("user") [Constants.as_public()] |> fetch_activities_query(opts) @@ -976,13 +981,65 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_tag(query, _), do: query - defp restrict_recipients(query, [], _user), do: query + defp reply_recipients(user, "following") do + [user.ap_id | User.get_cached_user_friends_ap_ids(user)] + end + + defp reply_recipients(user, "self"), do: [user.ap_id] + + defp restrict_recipients(query, [], _opts), do: query + + defp restrict_recipients( + query, + recipients, + %{"user" => nil, "reply_user" => user, "reply_visibility" => visibility} + ) + when not is_nil(user) and visibility in ["following", "self"] do + reply_recipients = reply_recipients(user, visibility) - defp restrict_recipients(query, recipients, nil) do - from(activity in query, where: fragment("? && ?", ^recipients, activity.recipients)) + from([activity, object] in query, + where: + fragment( + "? && ? AND (?->>'inReplyTo' IS NULL OR array_remove(?, ?) && ? OR ? = ?)", + ^recipients, + activity.recipients, + object.data, + activity.recipients, + activity.actor, + ^reply_recipients, + activity.actor, + ^user.ap_id + ) + ) end - defp restrict_recipients(query, recipients, user) do + defp restrict_recipients(query, recipients, %{"user" => nil}) do + from(activity in query, + where: fragment("? && ?", ^recipients, activity.recipients) + ) + end + + defp restrict_recipients(query, recipients, %{"user" => user, "reply_visibility" => visibility}) + when visibility in ["following", "self"] do + reply_recipients = reply_recipients(user, visibility) + + from( + [activity, object] in query, + where: + fragment( + "? && ? AND (?->>'inReplyTo' IS NULL OR array_remove(?, ?) && ?)", + ^recipients, + activity.recipients, + object.data, + activity.recipients, + activity.actor, + ^reply_recipients + ), + or_where: activity.actor == ^user.ap_id + ) + end + + defp restrict_recipients(query, recipients, %{"user" => user}) do from( activity in query, where: fragment("? && ?", ^recipients, activity.recipients), @@ -1254,13 +1311,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do skip_thread_containment: Config.get([:instance, :skip_thread_containment]) } + opts = Map.put(opts, "user", opts["user"]) + Activity |> maybe_preload_objects(opts) |> maybe_preload_bookmarks(opts) |> maybe_preload_report_notes(opts) |> maybe_set_thread_muted_field(opts) |> maybe_order(opts) - |> restrict_recipients(recipients, opts["user"]) + |> restrict_recipients(recipients, opts) |> restrict_tag(opts) |> restrict_tag_reject(opts) |> restrict_tag_all(opts) diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex index c1cd15bb2..244cf2be5 100644 --- a/lib/pleroma/web/common_api/activity_draft.ex +++ b/lib/pleroma/web/common_api/activity_draft.ex @@ -84,14 +84,18 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do %__MODULE__{draft | attachments: attachments} end - defp in_reply_to(draft) do - case Map.get(draft.params, "in_reply_to_status_id") do - "" -> draft - nil -> draft - id -> %__MODULE__{draft | in_reply_to: Activity.get_by_id(id)} - end + defp in_reply_to(%{params: %{"in_reply_to_status_id" => ""}} = draft), do: draft + + defp in_reply_to(%{params: %{"in_reply_to_status_id" => id}} = draft) when is_binary(id) do + %__MODULE__{draft | in_reply_to: Activity.get_by_id(id)} end + defp in_reply_to(%{params: %{"in_reply_to_status_id" => %Activity{} = in_reply_to}} = draft) do + %__MODULE__{draft | in_reply_to: in_reply_to} + end + + defp in_reply_to(draft), do: draft + defp in_reply_to_conversation(draft) do in_reply_to_conversation = Participation.get(draft.params["in_reply_to_conversation_id"]) %__MODULE__{draft | in_reply_to_conversation: in_reply_to_conversation} diff --git a/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex b/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex index b3c58005e..a2ac9301e 100644 --- a/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex @@ -100,6 +100,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do |> Map.put("local_only", local_only) |> Map.put("blocking_user", user) |> Map.put("muting_user", user) + |> Map.put("user", user) |> ActivityPub.fetch_public_activities() conn |