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.ex10
-rw-r--r--lib/pleroma/web/activity_pub/mrf/reject_non_public.ex26
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex89
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex25
4 files changed, 130 insertions, 20 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index a12bd5b58..b174af7ce 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -57,6 +57,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
if activity.data["type"] in ["Create", "Announce"] do
Pleroma.Web.Streamer.stream("user", activity)
+ Pleroma.Web.Streamer.stream("list", activity)
if Enum.member?(activity.data["to"], public) do
Pleroma.Web.Streamer.stream("public", activity)
@@ -198,7 +199,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
:ok <- maybe_federate(unannounce_activity),
{:ok, _activity} <- Repo.delete(announce_activity),
{:ok, object} <- remove_announce_from_object(announce_activity, object) do
- {:ok, unannounce_activity, announce_activity, object}
+ {:ok, unannounce_activity, object}
else
_e -> {:ok, object}
end
@@ -214,6 +215,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
def unfollow(follower, followed, activity_id \\ nil, local \\ true) do
with %Activity{} = follow_activity <- fetch_latest_follow(follower, followed),
+ {:ok, follow_activity} <- update_follow_state(follow_activity, "cancelled"),
unfollow_data <- make_unfollow_data(follower, followed, follow_activity, activity_id),
{:ok, activity} <- insert(unfollow_data, local),
:ok <- maybe_federate(activity) do
@@ -449,11 +451,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do
blocks = info["blocks"] || []
+ domain_blocks = info["domain_blocks"] || []
from(
activity in query,
where: fragment("not (? = ANY(?))", activity.actor, ^blocks),
- where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks)
+ where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks),
+ where: fragment("not (split_part(?, '/', 3) = ANY(?))", activity.actor, ^domain_blocks)
)
end
@@ -502,7 +506,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
def upload(file) do
- data = Upload.store(file)
+ data = Upload.store(file, Application.get_env(:pleroma, :instance)[:dedupe_media])
Repo.insert(%Object{data: data})
end
diff --git a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
index 879cbe6de..b6936fe90 100644
--- a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
+++ b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
@@ -2,6 +2,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do
alias Pleroma.User
@behaviour Pleroma.Web.ActivityPub.MRF
+ @mrf_rejectnonpublic Application.get_env(:pleroma, :mrf_rejectnonpublic)
+ @allow_followersonly Keyword.get(@mrf_rejectnonpublic, :allow_followersonly)
+ @allow_direct Keyword.get(@mrf_rejectnonpublic, :allow_direct)
+
@impl true
def filter(object) do
if object["type"] == "Create" do
@@ -18,9 +22,25 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do
end
case visibility do
- "public" -> {:ok, object}
- "unlisted" -> {:ok, object}
- _ -> {:reject, nil}
+ "public" ->
+ {:ok, object}
+
+ "unlisted" ->
+ {:ok, object}
+
+ "followers" ->
+ with true <- @allow_followersonly do
+ {:ok, object}
+ else
+ _e -> {:reject, nil}
+ end
+
+ "direct" ->
+ with true <- @allow_direct do
+ {:ok, object}
+ else
+ _e -> {:reject, nil}
+ end
end
else
{:ok, object}
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 75ba36729..300e0fcdd 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -30,14 +30,19 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
when not is_nil(in_reply_to_id) do
case ActivityPub.fetch_object_from_id(in_reply_to_id) do
{:ok, replied_object} ->
- activity = Activity.get_create_activity_by_object_ap_id(replied_object.data["id"])
-
- object
- |> Map.put("inReplyTo", replied_object.data["id"])
- |> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id)
- |> Map.put("inReplyToStatusId", activity.id)
- |> Map.put("conversation", replied_object.data["context"] || object["conversation"])
- |> Map.put("context", replied_object.data["context"] || object["conversation"])
+ with %Activity{} = activity <-
+ Activity.get_create_activity_by_object_ap_id(replied_object.data["id"]) do
+ object
+ |> Map.put("inReplyTo", replied_object.data["id"])
+ |> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id)
+ |> Map.put("inReplyToStatusId", activity.id)
+ |> Map.put("conversation", replied_object.data["context"] || object["conversation"])
+ |> Map.put("context", replied_object.data["context"] || object["conversation"])
+ else
+ e ->
+ Logger.error("Couldn't fetch #{object["inReplyTo"]} #{inspect(e)}")
+ object
+ end
e ->
Logger.error("Couldn't fetch #{object["inReplyTo"]} #{inspect(e)}")
@@ -137,9 +142,17 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
with %User{local: true} = followed <- User.get_cached_by_ap_id(followed),
%User{} = follower <- User.get_or_fetch_by_ap_id(follower),
{:ok, activity} <- ActivityPub.follow(follower, followed, id, false) do
- ActivityPub.accept(%{to: [follower.ap_id], actor: followed.ap_id, object: data, local: true})
+ if not User.locked?(followed) do
+ ActivityPub.accept(%{
+ to: [follower.ap_id],
+ actor: followed.ap_id,
+ object: data,
+ local: true
+ })
+
+ User.follow(follower, followed)
+ end
- User.follow(follower, followed)
{:ok, activity}
else
_e -> :error
@@ -252,7 +265,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
{:ok, new_user_data} = ActivityPub.user_data_from_user_object(object)
banner = new_user_data[:info]["banner"]
- locked = new_user_data[:info]["locked"]
+ locked = new_user_data[:info]["locked"] || false
update_data =
new_user_data
@@ -304,7 +317,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
{:ok, object} <-
get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
- {:ok, activity, _, _} <- ActivityPub.unannounce(actor, object, id, false) do
+ {:ok, activity, _} <- ActivityPub.unannounce(actor, object, id, false) do
{:ok, activity}
else
_e -> :error
@@ -432,6 +445,58 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
{:ok, data}
end
+ # Mastodon Accept/Reject requires a non-normalized object containing the actor URIs,
+ # because of course it does.
+ def prepare_outgoing(%{"type" => "Accept"} = data) do
+ follow_activity_id =
+ if is_binary(data["object"]) do
+ data["object"]
+ else
+ data["object"]["id"]
+ end
+
+ with follow_activity <- Activity.get_by_ap_id(follow_activity_id) do
+ object = %{
+ "actor" => follow_activity.actor,
+ "object" => follow_activity.data["object"],
+ "id" => follow_activity.data["id"],
+ "type" => "Follow"
+ }
+
+ data =
+ data
+ |> Map.put("object", object)
+ |> Map.put("@context", "https://www.w3.org/ns/activitystreams")
+
+ {:ok, data}
+ end
+ end
+
+ def prepare_outgoing(%{"type" => "Reject"} = data) do
+ follow_activity_id =
+ if is_binary(data["object"]) do
+ data["object"]
+ else
+ data["object"]["id"]
+ end
+
+ with follow_activity <- Activity.get_by_ap_id(follow_activity_id) do
+ object = %{
+ "actor" => follow_activity.actor,
+ "object" => follow_activity.data["object"],
+ "id" => follow_activity.data["id"],
+ "type" => "Follow"
+ }
+
+ data =
+ data
+ |> Map.put("object", object)
+ |> Map.put("@context", "https://www.w3.org/ns/activitystreams")
+
+ {:ok, data}
+ end
+ end
+
def prepare_outgoing(%{"type" => _type} = data) do
data =
data
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 56b80a8db..64329b710 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -4,6 +4,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
alias Pleroma.Web.Endpoint
alias Ecto.{Changeset, UUID}
import Ecto.Query
+ require Logger
# Some implementations send the actor URI as the actor field, others send the entire actor object,
# so figure out what the actor's URI is based on what we have.
@@ -217,9 +218,26 @@ defmodule Pleroma.Web.ActivityPub.Utils do
#### Follow-related helpers
@doc """
+ Updates a follow activity's state (for locked accounts).
+ """
+ def update_follow_state(%Activity{} = activity, state) do
+ with new_data <-
+ activity.data
+ |> Map.put("state", state),
+ changeset <- Changeset.change(activity, data: new_data),
+ {:ok, activity} <- Repo.update(changeset) do
+ {:ok, activity}
+ end
+ end
+
+ @doc """
Makes a follow activity data for the given follower and followed
"""
- def make_follow_data(%User{ap_id: follower_id}, %User{ap_id: followed_id}, activity_id) do
+ def make_follow_data(
+ %User{ap_id: follower_id},
+ %User{ap_id: followed_id} = followed,
+ activity_id
+ ) do
data = %{
"type" => "Follow",
"actor" => follower_id,
@@ -228,7 +246,10 @@ defmodule Pleroma.Web.ActivityPub.Utils do
"object" => followed_id
}
- if activity_id, do: Map.put(data, "id", activity_id), else: data
+ data = if activity_id, do: Map.put(data, "id", activity_id), else: data
+ data = if User.locked?(followed), do: Map.put(data, "state", "pending"), else: data
+
+ data
end
def fetch_latest_follow(%User{ap_id: follower_id}, %User{ap_id: followed_id}) do