summaryrefslogtreecommitdiff
path: root/lib/pleroma/web/activity_pub
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma/web/activity_pub')
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex17
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub_controller.ex8
-rw-r--r--lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex44
-rw-r--r--lib/pleroma/web/activity_pub/mrf/tag_policy.ex139
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex2
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex2
6 files changed, 195 insertions, 17 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 06e8c3f1c..b33912721 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -521,7 +521,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_actor(query, _), do: query
defp restrict_type(query, %{"type" => type}) when is_binary(type) do
- restrict_type(query, %{"type" => [type]})
+ from(activity in query, where: fragment("?->>'type' = ?", activity.data, ^type))
end
defp restrict_type(query, %{"type" => type}) do
@@ -744,7 +744,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
public = is_public?(activity)
- remote_inboxes =
+ reachable_inboxes_metadata =
(Pleroma.Web.Salmon.remote_users(activity) ++ remote_followers)
|> Enum.filter(fn user -> User.ap_enabled?(user) end)
|> Enum.map(fn %{info: %{source_data: data}} ->
@@ -757,17 +757,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
{:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
json = Jason.encode!(data)
- Enum.each(remote_inboxes, fn inbox ->
+ Enum.each(reachable_inboxes_metadata, fn {inbox, unreachable_since} ->
Federator.enqueue(:publish_single_ap, %{
inbox: inbox,
json: json,
actor: actor,
- id: activity.data["id"]
+ id: activity.data["id"],
+ unreachable_since: unreachable_since
})
end)
end
- def publish_one(%{inbox: inbox, json: json, actor: actor, id: id}) do
+ def publish_one(%{inbox: inbox, json: json, actor: actor, id: id} = params) do
Logger.info("Federating #{id} to #{inbox}")
host = URI.parse(inbox).host
@@ -791,11 +792,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
{"digest", digest}
]
) do
- Instances.set_reachable(inbox)
+ if !Map.has_key?(params, :unreachable_since) || params[:unreachable_since],
+ do: Instances.set_reachable(inbox)
+
result
else
{_post_result, response} ->
- Instances.set_unreachable(inbox)
+ unless params[:unreachable_since], do: Instances.set_unreachable(inbox)
{:error, response}
end
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 4dea6ab83..2cdf132e2 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -198,6 +198,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
end
+ def whoami(%{assigns: %{user: %User{} = user}} = conn, _params) do
+ conn
+ |> put_resp_header("content-type", "application/activity+json")
+ |> json(UserView.render("user.json", %{user: user}))
+ end
+
+ def whoami(_conn, _params), do: {:error, :not_found}
+
def read_inbox(%{assigns: %{user: user}} = conn, %{"nickname" => nickname} = params) do
if nickname == user.nickname do
conn
diff --git a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
index a3f516ae7..4c6e612b2 100644
--- a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
@@ -3,20 +3,46 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
+ alias Pleroma.User
@behaviour Pleroma.Web.ActivityPub.MRF
+ defp delist_message(message) do
+ follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
+
+ message
+ |> Map.put("to", [follower_collection])
+ |> Map.put("cc", ["https://www.w3.org/ns/activitystreams#Public"])
+ end
+
@impl true
- def filter(%{"type" => "Create"} = object) do
- threshold = Pleroma.Config.get([:mrf_hellthread, :threshold])
- recipients = (object["to"] || []) ++ (object["cc"] || [])
-
- if length(recipients) > threshold do
- {:reject, nil}
- else
- {:ok, object}
+ def filter(%{"type" => "Create"} = message) do
+ delist_threshold = Pleroma.Config.get([:mrf_hellthread, :delist_threshold])
+
+ reject_threshold =
+ Pleroma.Config.get(
+ [:mrf_hellthread, :reject_threshold],
+ Pleroma.Config.get([:mrf_hellthread, :threshold])
+ )
+
+ recipients = (message["to"] || []) ++ (message["cc"] || [])
+
+ cond do
+ length(recipients) > reject_threshold and reject_threshold > 0 ->
+ {:reject, nil}
+
+ length(recipients) > delist_threshold and delist_threshold > 0 ->
+ if Enum.member?(message["to"], "https://www.w3.org/ns/activitystreams#Public") or
+ Enum.member?(message["cc"], "https://www.w3.org/ns/activitystreams#Public") do
+ {:ok, delist_message(message)}
+ else
+ {:ok, message}
+ end
+
+ true ->
+ {:ok, message}
end
end
@impl true
- def filter(object), do: {:ok, object}
+ def filter(message), do: {:ok, message}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
new file mode 100644
index 000000000..b242e44e6
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
@@ -0,0 +1,139 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
+ alias Pleroma.User
+ @behaviour Pleroma.Web.ActivityPub.MRF
+
+ defp get_tags(%User{tags: tags}) when is_list(tags), do: tags
+ defp get_tags(_), do: []
+
+ defp process_tag(
+ "mrf_tag:media-force-nsfw",
+ %{"type" => "Create", "object" => %{"attachment" => child_attachment} = object} = message
+ )
+ when length(child_attachment) > 0 do
+ tags = (object["tag"] || []) ++ ["nsfw"]
+
+ object =
+ object
+ |> Map.put("tags", tags)
+ |> Map.put("sensitive", true)
+
+ message = Map.put(message, "object", object)
+
+ {:ok, message}
+ end
+
+ defp process_tag(
+ "mrf_tag:media-strip",
+ %{"type" => "Create", "object" => %{"attachment" => child_attachment} = object} = message
+ )
+ when length(child_attachment) > 0 do
+ object = Map.delete(object, "attachment")
+ message = Map.put(message, "object", object)
+
+ {:ok, message}
+ end
+
+ defp process_tag(
+ "mrf_tag:force-unlisted",
+ %{"type" => "Create", "to" => to, "cc" => cc, "actor" => actor} = message
+ ) do
+ user = User.get_cached_by_ap_id(actor)
+
+ if Enum.member?(to, "https://www.w3.org/ns/activitystreams#Public") do
+ to =
+ List.delete(to, "https://www.w3.org/ns/activitystreams#Public") ++ [user.follower_address]
+
+ cc =
+ List.delete(cc, user.follower_address) ++ ["https://www.w3.org/ns/activitystreams#Public"]
+
+ object =
+ message["object"]
+ |> Map.put("to", to)
+ |> Map.put("cc", cc)
+
+ message =
+ message
+ |> Map.put("to", to)
+ |> Map.put("cc", cc)
+ |> Map.put("object", object)
+
+ {:ok, message}
+ else
+ {:ok, message}
+ end
+ end
+
+ defp process_tag(
+ "mrf_tag:sandbox",
+ %{"type" => "Create", "to" => to, "cc" => cc, "actor" => actor} = message
+ ) do
+ user = User.get_cached_by_ap_id(actor)
+
+ if Enum.member?(to, "https://www.w3.org/ns/activitystreams#Public") or
+ Enum.member?(cc, "https://www.w3.org/ns/activitystreams#Public") do
+ to =
+ List.delete(to, "https://www.w3.org/ns/activitystreams#Public") ++ [user.follower_address]
+
+ cc = List.delete(cc, "https://www.w3.org/ns/activitystreams#Public")
+
+ object =
+ message["object"]
+ |> Map.put("to", to)
+ |> Map.put("cc", cc)
+
+ message =
+ message
+ |> Map.put("to", to)
+ |> Map.put("cc", cc)
+ |> Map.put("object", object)
+
+ {:ok, message}
+ else
+ {:ok, message}
+ end
+ end
+
+ defp process_tag(
+ "mrf_tag:disable-remote-subscription",
+ %{"type" => "Follow", "actor" => actor} = message
+ ) do
+ user = User.get_cached_by_ap_id(actor)
+
+ if user.local == true do
+ {:ok, message}
+ else
+ {:reject, nil}
+ end
+ end
+
+ defp process_tag("mrf_tag:disable-any-subscription", %{"type" => "Follow"}), do: {:reject, nil}
+
+ defp process_tag(_, message), do: {:ok, message}
+
+ def filter_message(actor, message) do
+ User.get_cached_by_ap_id(actor)
+ |> get_tags()
+ |> Enum.reduce({:ok, message}, fn
+ tag, {:ok, message} ->
+ process_tag(tag, message)
+
+ _, error ->
+ error
+ end)
+ end
+
+ @impl true
+ def filter(%{"object" => target_actor, "type" => "Follow"} = message),
+ do: filter_message(target_actor, message)
+
+ @impl true
+ def filter(%{"actor" => actor, "type" => "Create"} = message),
+ do: filter_message(actor, message)
+
+ @impl true
+ def filter(message), do: {:ok, message}
+end
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 43725c3db..7151efdeb 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -313,6 +313,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> Map.put("tag", combined)
end
+ def fix_tag(%{"tag" => %{} = tag} = object), do: Map.put(object, "tag", [tag])
+
def fix_tag(object), do: object
# content map usually only has one language so this will do for now.
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 3b0cdfe71..4a2cc6738 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -285,7 +285,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|> Map.put("#{property}_count", length(element))
|> Map.put("#{property}s", element),
changeset <- Changeset.change(object, data: new_data),
- {:ok, object} <- Repo.update(changeset),
+ {:ok, object} <- Object.update_and_set_cache(changeset),
_ <- update_object_in_activities(object) do
{:ok, object}
end