X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Factivity_pub%2Factivity_pub.ex;h=85fa83e2b55c0b716dc56ebf44057bdef0fc5bf7;hb=c9b418e5477229017b3750c55cf3ea3d03b7e609;hp=1880607805ae7859f40a282f2cdc241e331f4bb1;hpb=922abcda61298a7bca48894cb9a51a52fdeab1ed;p=akkoma diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 188060780..85fa83e2b 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors +# Copyright © 2017-2019 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.ActivityPub.ActivityPub do @@ -56,10 +56,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end end + defp check_remote_limit(%{"object" => %{"content" => content}}) do + limit = Pleroma.Config.get([:instance, :remote_limit]) + String.length(content) <= limit + end + + defp check_remote_limit(_), do: true + def insert(map, local \\ true) when is_map(map) do with nil <- Activity.normalize(map), map <- lazy_put_activity_defaults(map), :ok <- check_actor_is_active(map["actor"]), + {_, true} <- {:remote_limit_error, check_remote_limit(map)}, {:ok, map} <- MRF.filter(map), :ok <- insert_full_object(map) do {recipients, _, _} = get_recipients(map) @@ -84,7 +92,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do def stream_out(activity) do public = "https://www.w3.org/ns/activitystreams#Public" - if activity.data["type"] in ["Create", "Announce"] do + if activity.data["type"] in ["Create", "Announce", "Delete"] do Pleroma.Web.Streamer.stream("user", activity) Pleroma.Web.Streamer.stream("list", activity) @@ -95,16 +103,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do Pleroma.Web.Streamer.stream("public:local", activity) end - activity.data["object"] - |> Map.get("tag", []) - |> Enum.filter(fn tag -> is_bitstring(tag) end) - |> Enum.map(fn tag -> Pleroma.Web.Streamer.stream("hashtag:" <> tag, activity) end) + if activity.data["type"] in ["Create"] do + activity.data["object"] + |> Map.get("tag", []) + |> Enum.filter(fn tag -> is_bitstring(tag) end) + |> Enum.map(fn tag -> Pleroma.Web.Streamer.stream("hashtag:" <> tag, activity) end) - if activity.data["object"]["attachment"] != [] do - Pleroma.Web.Streamer.stream("public:media", activity) + if activity.data["object"]["attachment"] != [] do + Pleroma.Web.Streamer.stream("public:media", activity) - if activity.local do - Pleroma.Web.Streamer.stream("public:local:media", activity) + if activity.local do + Pleroma.Web.Streamer.stream("public:local:media", activity) + end end end else @@ -130,8 +140,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do additional ), {:ok, activity} <- insert(create_data, local), - :ok <- maybe_federate(activity), - {:ok, _actor} <- User.increase_note_count(actor) do + # Changing note count prior to enqueuing federation task in order to avoid race conditions on updating user.info + {:ok, _actor} <- User.increase_note_count(actor), + :ok <- maybe_federate(activity) do {:ok, activity} end end @@ -216,10 +227,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do %User{ap_id: _} = user, %Object{data: %{"id" => _}} = object, activity_id \\ nil, - local \\ true + local \\ true, + public \\ true ) do with true <- is_public?(object), - announce_data <- make_announce_data(user, object, activity_id), + announce_data <- make_announce_data(user, object, activity_id, public), {:ok, activity} <- insert(announce_data, local), {:ok, object} <- add_announce_to_object(activity, object), :ok <- maybe_federate(activity) do @@ -277,8 +289,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do with {:ok, _} <- Object.delete(object), {:ok, activity} <- insert(data, local), - :ok <- maybe_federate(activity), - {:ok, _actor} <- User.decrease_note_count(user) do + # Changing note count prior to enqueuing federation task in order to avoid race conditions on updating user.info + {:ok, _actor} <- User.decrease_note_count(user), + :ok <- maybe_federate(activity) do {:ok, activity} end end @@ -356,21 +369,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do @valid_visibilities ~w[direct unlisted public private] - defp restrict_visibility(query, %{visibility: "direct"}) do - public = "https://www.w3.org/ns/activitystreams#Public" + defp restrict_visibility(query, %{visibility: visibility}) + when visibility in @valid_visibilities do + query = + from( + a in query, + where: + fragment("activity_visibility(?, ?, ?) = ?", a.actor, a.recipients, a.data, ^visibility) + ) - from( - activity in query, - join: sender in User, - on: sender.ap_id == activity.actor, - # Are non-direct statuses with no to/cc possible? - where: - fragment( - "not (? && ?)", - [^public, sender.follower_address], - activity.recipients - ) - ) + Ecto.Adapters.SQL.to_sql(:all, Repo, query) + + query end defp restrict_visibility(_query, %{visibility: visibility}) @@ -386,6 +396,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> Map.put("type", ["Create", "Announce"]) |> Map.put("actor_id", user.ap_id) |> Map.put("whole_db", true) + |> Map.put("pinned_activity_ids", user.info.pinned_activities) recipients = if reading_user do @@ -399,6 +410,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> Enum.reverse() end + defp restrict_since(query, %{"since_id" => ""}), do: query + defp restrict_since(query, %{"since_id" => since_id}) do from(activity in query, where: activity.id > ^since_id) end @@ -454,6 +467,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_local(query, _), do: query + defp restrict_max(query, %{"max_id" => ""}), do: query + defp restrict_max(query, %{"max_id" => max_id}) do from(activity in query, where: activity.id < ^max_id) end @@ -503,15 +518,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_replies(query, _), do: query - # Only search through last 100_000 activities by default - defp restrict_recent(query, %{"whole_db" => true}), do: query - - defp restrict_recent(query, _) do - since = (Repo.aggregate(Activity, :max, :id) || 0) - 100_000 - - from(activity in query, where: activity.id > ^since) + defp restrict_reblogs(query, %{"exclude_reblogs" => val}) when val == "true" or val == "1" do + from(activity in query, where: fragment("?->>'type' != 'Announce'", activity.data)) end + defp restrict_reblogs(query, _), do: query + defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do blocks = info.blocks || [] domain_blocks = info.domain_blocks || [] @@ -538,6 +550,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do ) end + defp restrict_pinned(query, %{"pinned" => "true", "pinned_activity_ids" => ids}) do + from(activity in query, where: activity.id in ^ids) + end + + defp restrict_pinned(query, _), do: query + def fetch_activities_query(recipients, opts \\ %{}) do base_query = from( @@ -556,11 +574,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> restrict_actor(opts) |> restrict_type(opts) |> restrict_favorited_by(opts) - |> restrict_recent(opts) |> restrict_blocked(opts) |> restrict_media(opts) |> restrict_visibility(opts) |> restrict_replies(opts) + |> restrict_reblogs(opts) + |> restrict_pinned(opts) end def fetch_activities(recipients, opts \\ %{}) do @@ -726,8 +745,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do {"Content-Type", "application/activity+json"}, {"signature", signature}, {"digest", digest} - ], - hackney: [pool: :default] + ] ) end @@ -787,9 +805,24 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end end - def is_public?(activity) do - "https://www.w3.org/ns/activitystreams#Public" in (activity.data["to"] ++ - (activity.data["cc"] || [])) + def is_public?(%Object{data: %{"type" => "Tombstone"}}), do: false + def is_public?(%Object{data: data}), do: is_public?(data) + def is_public?(%Activity{data: data}), do: is_public?(data) + def is_public?(%{"directMessage" => true}), do: false + + def is_public?(data) do + "https://www.w3.org/ns/activitystreams#Public" in (data["to"] ++ (data["cc"] || [])) + end + + def is_private?(activity) do + !is_public?(activity) && Enum.any?(activity.data["to"], &String.contains?(&1, "/followers")) + end + + def is_direct?(%Activity{data: %{"directMessage" => true}}), do: true + def is_direct?(%Object{data: %{"directMessage" => true}}), do: true + + def is_direct?(activity) do + !is_public?(activity) && !is_private?(activity) end def visible_for_user?(activity, nil) do