aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorHaelwenn <contact+git.pleroma.social@hacktivis.me>2020-08-13 16:04:43 +0000
committerHaelwenn <contact+git.pleroma.social@hacktivis.me>2020-08-13 16:04:43 +0000
commitf99b8a25ebd89a11ad3b98fa5815cc4fd338eeb1 (patch)
treef783663a78a7b221e393cb289129b69a9eea64f5 /lib
parent8d5f9d4b28e370aa0526c7c2f8cf7bfc1a78e6be (diff)
parent2e347e8286fab13075e6e39e64e56cb3ba14e7e8 (diff)
downloadpleroma-f99b8a25ebd89a11ad3b98fa5815cc4fd338eeb1.tar.gz
Merge branch 'reject' into 'develop'
Move Accepts and Rejects to the Pipeline See merge request pleroma/pleroma!2878
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex26
-rw-r--r--lib/pleroma/web/activity_pub/builder.ex22
-rw-r--r--lib/pleroma/web/activity_pub/object_validator.ex12
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex56
-rw-r--r--lib/pleroma/web/activity_pub/side_effects.ex84
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex90
-rw-r--r--lib/pleroma/web/common_api/common_api.ex27
7 files changed, 158 insertions, 159 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index fe62673dc..bde1fe708 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -285,32 +285,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
- @spec accept(map()) :: {:ok, Activity.t()} | {:error, any()}
- def accept(params) do
- accept_or_reject("Accept", params)
- end
-
- @spec reject(map()) :: {:ok, Activity.t()} | {:error, any()}
- def reject(params) do
- accept_or_reject("Reject", params)
- end
-
- @spec accept_or_reject(String.t(), map()) :: {:ok, Activity.t()} | {:error, any()}
- defp accept_or_reject(type, %{to: to, actor: actor, object: object} = params) do
- local = Map.get(params, :local, true)
- activity_id = Map.get(params, :activity_id, nil)
-
- data =
- %{"to" => to, "type" => type, "actor" => actor.ap_id, "object" => object}
- |> Maps.put_if_present("id", activity_id)
-
- with {:ok, activity} <- insert(data, local),
- _ <- notify_and_stream(activity),
- :ok <- maybe_federate(activity) do
- {:ok, activity}
- end
- end
-
@spec unfollow(User.t(), User.t(), String.t() | nil, boolean()) ::
{:ok, Activity.t()} | nil | {:error, any()}
def unfollow(follower, followed, activity_id \\ nil, local \\ true) do
diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex
index 1b4c421b8..f2392ce79 100644
--- a/lib/pleroma/web/activity_pub/builder.ex
+++ b/lib/pleroma/web/activity_pub/builder.ex
@@ -14,6 +14,28 @@ defmodule Pleroma.Web.ActivityPub.Builder do
require Pleroma.Constants
+ def accept_or_reject(actor, activity, type) do
+ data = %{
+ "id" => Utils.generate_activity_id(),
+ "actor" => actor.ap_id,
+ "type" => type,
+ "object" => activity.data["id"],
+ "to" => [activity.actor]
+ }
+
+ {:ok, data, []}
+ end
+
+ @spec reject(User.t(), Activity.t()) :: {:ok, map(), keyword()}
+ def reject(actor, rejected_activity) do
+ accept_or_reject(actor, rejected_activity, "Reject")
+ end
+
+ @spec accept(User.t(), Activity.t()) :: {:ok, map(), keyword()}
+ def accept(actor, accepted_activity) do
+ accept_or_reject(actor, accepted_activity, "Accept")
+ end
+
@spec follow(User.t(), User.t()) :: {:ok, map(), keyword()}
def follow(follower, followed) do
data = %{
diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex
index e1114a44d..3f1dffe2b 100644
--- a/lib/pleroma/web/activity_pub/object_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validator.ex
@@ -13,6 +13,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Object
alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator
@@ -30,6 +31,17 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
@spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
def validate(object, meta)
+ def validate(%{"type" => type} = object, meta)
+ when type in ~w[Accept Reject] do
+ with {:ok, object} <-
+ object
+ |> AcceptRejectValidator.cast_and_validate()
+ |> Ecto.Changeset.apply_action(:insert) do
+ object = stringify_keys(object)
+ {:ok, object, meta}
+ end
+ end
+
def validate(%{"type" => "Follow"} = object, meta) do
with {:ok, object} <-
object
diff --git a/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex b/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex
new file mode 100644
index 000000000..179beda58
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex
@@ -0,0 +1,56 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator do
+ use Ecto.Schema
+
+ alias Pleroma.Activity
+ alias Pleroma.EctoType.ActivityPub.ObjectValidators
+
+ import Ecto.Changeset
+ import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
+
+ @primary_key false
+
+ embedded_schema do
+ field(:id, ObjectValidators.ObjectID, primary_key: true)
+ field(:type, :string)
+ field(:object, ObjectValidators.ObjectID)
+ field(:actor, ObjectValidators.ObjectID)
+ field(:to, ObjectValidators.Recipients, default: [])
+ field(:cc, ObjectValidators.Recipients, default: [])
+ end
+
+ def cast_data(data) do
+ %__MODULE__{}
+ |> cast(data, __schema__(:fields))
+ end
+
+ def validate_data(cng) do
+ cng
+ |> validate_required([:id, :type, :actor, :to, :cc, :object])
+ |> validate_inclusion(:type, ["Accept", "Reject"])
+ |> validate_actor_presence()
+ |> validate_object_presence(allowed_types: ["Follow"])
+ |> validate_accept_reject_rights()
+ end
+
+ def cast_and_validate(data) do
+ data
+ |> cast_data
+ |> validate_data
+ end
+
+ def validate_accept_reject_rights(cng) do
+ with object_id when is_binary(object_id) <- get_field(cng, :object),
+ %Activity{data: %{"object" => followed_actor}} <- Activity.get_by_ap_id(object_id),
+ true <- followed_actor == get_field(cng, :actor) do
+ cng
+ else
+ _e ->
+ cng
+ |> add_error(:actor, "can't accept or reject the given activity")
+ end
+ end
+end
diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex
index 5104d38ee..14a1da0c1 100644
--- a/lib/pleroma/web/activity_pub/side_effects.ex
+++ b/lib/pleroma/web/activity_pub/side_effects.ex
@@ -16,6 +16,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.Pipeline
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.Push
@@ -24,6 +25,59 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
def handle(object, meta \\ [])
+ # Task this handles
+ # - Follows
+ # - Sends a notification
+ def handle(
+ %{
+ data: %{
+ "actor" => actor,
+ "type" => "Accept",
+ "object" => follow_activity_id
+ }
+ } = object,
+ meta
+ ) do
+ with %Activity{actor: follower_id} = follow_activity <-
+ Activity.get_by_ap_id(follow_activity_id),
+ %User{} = followed <- User.get_cached_by_ap_id(actor),
+ %User{} = follower <- User.get_cached_by_ap_id(follower_id),
+ {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"),
+ {:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_accept) do
+ Notification.update_notification_type(followed, follow_activity)
+ User.update_follower_count(followed)
+ User.update_following_count(follower)
+ end
+
+ {:ok, object, meta}
+ end
+
+ # Task this handles
+ # - Rejects all existing follow activities for this person
+ # - Updates the follow state
+ # - Dismisses notificatios
+ def handle(
+ %{
+ data: %{
+ "actor" => actor,
+ "type" => "Reject",
+ "object" => follow_activity_id
+ }
+ } = object,
+ meta
+ ) do
+ with %Activity{actor: follower_id} = follow_activity <-
+ Activity.get_by_ap_id(follow_activity_id),
+ %User{} = followed <- User.get_cached_by_ap_id(actor),
+ %User{} = follower <- User.get_cached_by_ap_id(follower_id),
+ {:ok, _follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "reject") do
+ FollowingRelationship.update(follower, followed, :follow_reject)
+ Notification.dismiss(follow_activity)
+ end
+
+ {:ok, object, meta}
+ end
+
# Tasks this handle
# - Follows if possible
# - Sends a notification
@@ -44,33 +98,13 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
{_, {:ok, _}, _, _} <-
{:following, User.follow(follower, followed, :follow_pending), follower, followed} do
if followed.local && !followed.locked do
- Utils.update_follow_state_for_all(object, "accept")
- FollowingRelationship.update(follower, followed, :follow_accept)
- User.update_follower_count(followed)
- User.update_following_count(follower)
-
- %{
- to: [following_user],
- actor: followed,
- object: follow_id,
- local: true
- }
- |> ActivityPub.accept()
+ {:ok, accept_data, _} = Builder.accept(followed, object)
+ {:ok, _activity, _} = Pipeline.common_pipeline(accept_data, local: true)
end
else
- {:following, {:error, _}, follower, followed} ->
- Utils.update_follow_state_for_all(object, "reject")
- FollowingRelationship.update(follower, followed, :follow_reject)
-
- if followed.local do
- %{
- to: [follower.ap_id],
- actor: followed,
- object: follow_id,
- local: true
- }
- |> ActivityPub.reject()
- end
+ {:following, {:error, _}, _follower, followed} ->
+ {:ok, reject_data, _} = Builder.reject(followed, object)
+ {:ok, _activity, _} = Pipeline.common_pipeline(reject_data, local: true)
_ ->
nil
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 2f04cc6ff..544f3f3b6 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -9,9 +9,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
alias Pleroma.Activity
alias Pleroma.EarmarkRenderer
alias Pleroma.EctoType.ActivityPub.ObjectValidators
- alias Pleroma.FollowingRelationship
alias Pleroma.Maps
- alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Object.Containment
alias Pleroma.Repo
@@ -391,32 +389,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
defp fix_content(object), do: object
- defp mastodon_follow_hack(%{"id" => id, "actor" => follower_id}, followed) do
- with true <- id =~ "follows",
- %User{local: true} = follower <- User.get_cached_by_ap_id(follower_id),
- %Activity{} = activity <- Utils.fetch_latest_follow(follower, followed) do
- {:ok, activity}
- else
- _ -> {:error, nil}
- end
- end
-
- defp mastodon_follow_hack(_, _), do: {:error, nil}
-
- defp get_follow_activity(follow_object, followed) do
- with object_id when not is_nil(object_id) <- Utils.get_ap_id(follow_object),
- {_, %Activity{} = activity} <- {:activity, Activity.get_by_ap_id(object_id)} do
- {:ok, activity}
- else
- # Can't find the activity. This might a Mastodon 2.3 "Accept"
- {:activity, nil} ->
- mastodon_follow_hack(follow_object, followed)
-
- _ ->
- {:error, nil}
- end
- end
-
# Reduce the object list to find the reported user.
defp get_reported(objects) do
Enum.reduce_while(objects, nil, fn ap_id, _ ->
@@ -551,60 +523,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
end
- def handle_incoming(
- %{"type" => "Accept", "object" => follow_object, "actor" => _actor, "id" => id} = data,
- _options
- ) do
- with actor <- Containment.get_actor(data),
- {:ok, %User{} = followed} <- User.get_or_fetch_by_ap_id(actor),
- {:ok, follow_activity} <- get_follow_activity(follow_object, followed),
- {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"),
- %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]),
- {:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_accept) do
- User.update_follower_count(followed)
- User.update_following_count(follower)
-
- Notification.update_notification_type(followed, follow_activity)
-
- ActivityPub.accept(%{
- to: follow_activity.data["to"],
- type: "Accept",
- actor: followed,
- object: follow_activity.data["id"],
- local: false,
- activity_id: id
- })
- else
- _e ->
- :error
- end
- end
-
- def handle_incoming(
- %{"type" => "Reject", "object" => follow_object, "actor" => _actor, "id" => id} = data,
- _options
- ) do
- with actor <- Containment.get_actor(data),
- {:ok, %User{} = followed} <- User.get_or_fetch_by_ap_id(actor),
- {:ok, follow_activity} <- get_follow_activity(follow_object, followed),
- {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "reject"),
- %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]),
- {:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_reject),
- {:ok, activity} <-
- ActivityPub.reject(%{
- to: follow_activity.data["to"],
- type: "Reject",
- actor: followed,
- object: follow_activity.data["id"],
- local: false,
- activity_id: id
- }) do
- {:ok, activity}
- else
- _e -> :error
- end
- end
-
@misskey_reactions %{
"like" => "👍",
"love" => "❤️",
@@ -659,9 +577,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
%{"type" => type} = data,
_options
)
- when type in ~w{Update Block Follow} do
+ when type in ~w{Update Block Follow Accept Reject} do
with {:ok, %User{}} <- ObjectValidator.fetch_actor(data),
- {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
+ {:ok, activity, _} <-
+ Pipeline.common_pipeline(data, local: false) do
{:ok, activity}
end
end
@@ -670,7 +589,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
%{"type" => "Delete"} = data,
_options
) do
- with {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
+ with {:ok, activity, _} <-
+ Pipeline.common_pipeline(data, local: false) do
{:ok, activity}
else
{:error, {:validate_object, _}} = e ->
diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex
index c08e0ffeb..a8141b28f 100644
--- a/lib/pleroma/web/common_api/common_api.ex
+++ b/lib/pleroma/web/common_api/common_api.ex
@@ -6,9 +6,7 @@ defmodule Pleroma.Web.CommonAPI do
alias Pleroma.Activity
alias Pleroma.ActivityExpiration
alias Pleroma.Conversation.Participation
- alias Pleroma.FollowingRelationship
alias Pleroma.Formatter
- alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.ThreadMute
alias Pleroma.User
@@ -122,33 +120,16 @@ defmodule Pleroma.Web.CommonAPI do
def accept_follow_request(follower, followed) do
with %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),
- {:ok, follower} <- User.follow(follower, followed),
- {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"),
- {:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_accept),
- {:ok, _activity} <-
- ActivityPub.accept(%{
- to: [follower.ap_id],
- actor: followed,
- object: follow_activity.data["id"],
- type: "Accept"
- }) do
- Notification.update_notification_type(followed, follow_activity)
+ {:ok, accept_data, _} <- Builder.accept(followed, follow_activity),
+ {:ok, _activity, _} <- Pipeline.common_pipeline(accept_data, local: true) do
{:ok, follower}
end
end
def reject_follow_request(follower, followed) do
with %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),
- {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "reject"),
- {:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_reject),
- {:ok, _notifications} <- Notification.dismiss(follow_activity),
- {:ok, _activity} <-
- ActivityPub.reject(%{
- to: [follower.ap_id],
- actor: followed,
- object: follow_activity.data["id"],
- type: "Reject"
- }) do
+ {:ok, reject_data, _} <- Builder.reject(followed, follow_activity),
+ {:ok, _activity, _} <- Pipeline.common_pipeline(reject_data, local: true) do
{:ok, follower}
end
end