Compare commits

...

2 Commits

Author SHA1 Message Date
lain
f9afaaebd7 Credo fixes. 2020-05-05 19:29:03 +02:00
lain
c99777433b Undoing: Move undoing follows to the pipeline everywhere. 2020-05-05 19:19:09 +02:00
17 changed files with 120 additions and 201 deletions

View File

@ -1435,15 +1435,13 @@ defmodule Pleroma.User do
user user
|> get_followers() |> get_followers()
|> Enum.each(fn follower -> |> Enum.each(fn follower ->
ActivityPub.unfollow(follower, user) CommonAPI.unfollow(follower, user)
unfollow(follower, user)
end) end)
user user
|> get_friends() |> get_friends()
|> Enum.each(fn followed -> |> Enum.each(fn followed ->
ActivityPub.unfollow(user, followed) CommonAPI.unfollow(user, followed)
unfollow(user, followed)
end) end)
delete_user_activities(user) delete_user_activities(user)

View File

@ -17,7 +17,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.Upload alias Pleroma.Upload
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.MRF alias Pleroma.Web.ActivityPub.MRF
alias Pleroma.Web.ActivityPub.Pipeline
alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.Streamer alias Pleroma.Web.Streamer
@ -421,28 +423,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end end
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
with {:ok, result} <-
Repo.transaction(fn -> do_unfollow(follower, followed, activity_id, local) end) do
result
end
end
defp do_unfollow(follower, followed, activity_id, local) 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
{:ok, activity}
else
nil -> nil
{:error, error} -> Repo.rollback(error)
end
end
@spec delete(User.t() | Object.t(), keyword()) :: {:ok, User.t() | Object.t()} | {:error, any()} @spec delete(User.t() | Object.t(), keyword()) :: {:ok, User.t() | Object.t()} | {:error, any()}
def delete(entity, options \\ []) do def delete(entity, options \\ []) do
with {:ok, result} <- Repo.transaction(fn -> do_delete(entity, options) end) do with {:ok, result} <- Repo.transaction(fn -> do_delete(entity, options) end) do
@ -518,8 +498,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
unfollow_blocked = Config.get([:activitypub, :unfollow_blocked]) unfollow_blocked = Config.get([:activitypub, :unfollow_blocked])
if unfollow_blocked do if unfollow_blocked do
follow_activity = fetch_latest_follow(blocker, blocked) with %Activity{} = follow_activity <- fetch_latest_follow(blocker, blocked),
if follow_activity, do: unfollow(blocker, blocked, nil, local) {:ok, undo_data, _} <- Builder.undo(blocker, follow_activity),
{:ok, _undo, _} <- Pipeline.common_pipeline(undo_data, local: local) do
:ok
end
end end
with true <- outgoing_blocks, with true <- outgoing_blocks,

View File

@ -10,6 +10,18 @@ defmodule Pleroma.Web.ActivityPub.Builder do
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
@spec follow(User.t(), User.t()) :: {:ok, map(), keyword()}
def follow(follower, followed) do
{:ok,
%{
"id" => Utils.generate_activity_id(),
"actor" => follower.ap_id,
"type" => "Follow",
"object" => followed.ap_id,
"to" => [followed.ap_id]
}, []}
end
@spec undo(User.t(), Activity.t()) :: {:ok, map(), keyword()} @spec undo(User.t(), Activity.t()) :: {:ok, map(), keyword()}
def undo(actor, object) do def undo(actor, object) do
{:ok, {:ok,

View File

@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.Relay do
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.CommonAPI
require Logger require Logger
@relay_nickname "relay" @relay_nickname "relay"
@ -39,8 +40,7 @@ defmodule Pleroma.Web.ActivityPub.Relay do
def unfollow(target_instance) do def unfollow(target_instance) do
with %User{} = local_user <- get_actor(), with %User{} = local_user <- get_actor(),
{:ok, %User{} = target_user} <- User.get_or_fetch_by_ap_id(target_instance), {:ok, %User{} = target_user} <- User.get_or_fetch_by_ap_id(target_instance),
{:ok, activity} <- ActivityPub.unfollow(local_user, target_user) do {:ok, activity} <- CommonAPI.unfollow(local_user, target_user) do
User.unfollow(local_user, target_user)
Logger.info("relay: unfollowed instance: #{target_instance}: id=#{activity.data["id"]}") Logger.info("relay: unfollowed instance: #{target_instance}: id=#{activity.data["id"]}")
{:ok, activity} {:ok, activity}
else else

View File

@ -63,6 +63,18 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
end end
def handle_undoing( def handle_undoing(
%{data: %{"type" => "Follow", "actor" => follower, "object" => followed}} = object
) do
with %User{} = follower <- User.get_cached_by_ap_id(follower),
%User{} = followed <- User.get_cached_by_ap_id(followed),
{:ok, _, _} <- User.unfollow(follower, followed),
_ <- User.unsubscribe(follower, followed),
{:ok, _} <- Repo.delete(object) do
:ok
end
end
def handle_undoing(
%{data: %{"type" => "Block", "actor" => blocker, "object" => blocked}} = object %{data: %{"type" => "Block", "actor" => blocker, "object" => blocked}} = object
) do ) do
with %User{} = blocker <- User.get_cached_by_ap_id(blocker), with %User{} = blocker <- User.get_cached_by_ap_id(blocker),

View File

@ -666,6 +666,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end end
end end
def handle_incoming(%{"type" => "Undo"} = data, _options) do
with {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
{:ok, activity}
end
end
def handle_incoming( def handle_incoming(
%{ %{
"type" => "EmojiReact", "type" => "EmojiReact",
@ -769,56 +775,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end end
def handle_incoming( def handle_incoming(
%{
"type" => "Undo",
"object" => %{"type" => "Follow", "object" => followed},
"actor" => follower,
"id" => id
} = _data,
_options
) do
with %User{local: true} = followed <- User.get_cached_by_ap_id(followed),
{:ok, %User{} = follower} <- User.get_or_fetch_by_ap_id(follower),
{:ok, activity} <- ActivityPub.unfollow(follower, followed, id, false) do
User.unfollow(follower, followed)
{:ok, activity}
else
_e -> :error
end
end
def handle_incoming(
%{
"type" => "Undo",
"object" => %{"type" => type}
} = data,
_options
)
when type in ["Like", "EmojiReact", "Announce", "Block"] do
with {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
{:ok, activity}
end
end
# For Undos that don't have the complete object attached, try to find it in our database.
def handle_incoming(
%{
"type" => "Undo",
"object" => object
} = activity,
options
)
when is_binary(object) do
with %Activity{data: data} <- Activity.get_by_ap_id(object) do
activity
|> Map.put("object", data)
|> handle_incoming(options)
else
_e -> :error
end
end
def handle_incoming(
%{"type" => "Block", "object" => blocked, "actor" => blocker, "id" => id} = _data, %{"type" => "Block", "object" => blocked, "actor" => blocker, "id" => id} = _data,
_options _options
) do ) do

View File

@ -614,18 +614,6 @@ defmodule Pleroma.Web.ActivityPub.Utils do
defp take_announcements(_), do: [] defp take_announcements(_), do: []
#### Unfollow-related helpers
def make_unfollow_data(follower, followed, follow_activity, activity_id) do
%{
"type" => "Undo",
"actor" => follower.ap_id,
"to" => [followed.ap_id],
"object" => follow_activity.data
}
|> maybe_put("id", activity_id)
end
#### Block-related helpers #### Block-related helpers
@spec fetch_latest_block(User.t(), User.t()) :: Activity.t() | nil @spec fetch_latest_block(User.t(), User.t()) :: Activity.t() | nil
def fetch_latest_block(%User{ap_id: blocker_id}, %User{ap_id: blocked_id}) do def fetch_latest_block(%User{ap_id: blocker_id}, %User{ap_id: blocked_id}) do

View File

@ -32,6 +32,28 @@ defmodule Pleroma.Web.CommonAPI do
end end
end end
def unfollow(follower, followed) do
with {_, %Activity{} = follow} <-
{:fetch_follow, Utils.fetch_latest_follow(follower, followed)},
{:ok, unfollow_data, _} <- Builder.undo(follower, follow),
{:ok, unfollow, _} <- Pipeline.common_pipeline(unfollow_data, local: true) do
{:ok, unfollow}
else
{:fetch_follow, nil} ->
Logger.warn(
"No follow activity found for #{follower.ap_id} and #{followed.ap_id}, inserting one and starting over"
)
with {:ok, follow_data, _} <- Builder.follow(follower, followed),
{:ok, _follow, _} <- ActivityPub.persist(follow_data, local: true) do
unfollow(follower, followed)
end
e ->
e
end
end
def follow(follower, followed) do def follow(follower, followed) do
timeout = Pleroma.Config.get([:activitypub, :follow_handshake_timeout]) timeout = Pleroma.Config.get([:activitypub, :follow_handshake_timeout])
@ -42,14 +64,6 @@ defmodule Pleroma.Web.CommonAPI do
end end
end end
def unfollow(follower, unfollowed) do
with {:ok, follower, _follow_activity} <- User.unfollow(follower, unfollowed),
{:ok, _activity} <- ActivityPub.unfollow(follower, unfollowed),
{:ok, _subscription} <- User.unsubscribe(follower, unfollowed) do
{:ok, follower}
end
end
def accept_follow_request(follower, followed) do def accept_follow_request(follower, followed) do
with %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), with %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),
{:ok, follower} <- User.follow(follower, followed), {:ok, follower} <- User.follow(follower, followed),

View File

@ -321,7 +321,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end end
def unfollow(%{assigns: %{user: follower, account: followed}} = conn, _params) do def unfollow(%{assigns: %{user: follower, account: followed}} = conn, _params) do
with {:ok, follower} <- CommonAPI.unfollow(follower, followed) do with {:ok, _unfollow} <- CommonAPI.unfollow(follower, followed) do
render(conn, "relationship.json", user: follower, target: followed) render(conn, "relationship.json", user: follower, target: followed)
end end
end end

View File

@ -331,21 +331,6 @@ defmodule Pleroma.NotificationTest do
assert %{type: "follow"} = NotificationView.render("show.json", render_opts) assert %{type: "follow"} = NotificationView.render("show.json", render_opts)
end end
test "it doesn't create a notification for follow-unfollow-follow chains" do
user = insert(:user)
followed_user = insert(:user, locked: false)
{:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
assert FollowingRelationship.following?(user, followed_user)
assert [notification] = Notification.for_user(followed_user)
CommonAPI.unfollow(user, followed_user)
{:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
notification_id = notification.id
assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
end
test "dismisses the notification on follow request rejection" do test "dismisses the notification on follow request rejection" do
user = insert(:user, locked: true) user = insert(:user, locked: true)
follower = insert(:user) follower = insert(:user)

View File

@ -58,7 +58,7 @@ defmodule Mix.Tasks.Pleroma.RelayTest do
Mix.Tasks.Pleroma.Relay.run(["unfollow", target_instance]) Mix.Tasks.Pleroma.Relay.run(["unfollow", target_instance])
cancelled_activity = Activity.get_by_ap_id(follow_activity.data["id"]) cancelled_activity = Activity.get_by_ap_id(follow_activity.data["id"])
assert cancelled_activity.data["state"] == "cancelled" refute cancelled_activity
[undo_activity] = [undo_activity] =
ActivityPub.fetch_activities([], %{ ActivityPub.fetch_activities([], %{
@ -70,7 +70,7 @@ defmodule Mix.Tasks.Pleroma.RelayTest do
assert undo_activity.data["type"] == "Undo" assert undo_activity.data["type"] == "Undo"
assert undo_activity.data["actor"] == local_user.ap_id assert undo_activity.data["actor"] == local_user.ap_id
assert undo_activity.data["object"] == cancelled_activity.data assert undo_activity.data["object"] == follow_activity.data["id"]
refute "#{target_instance}/followers" in User.following(local_user) refute "#{target_instance}/followers" in User.following(local_user)
end end
end end

View File

@ -1149,8 +1149,8 @@ defmodule Pleroma.UserTest do
{:ok, like_two} = CommonAPI.favorite(follower, activity.id) {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
{:ok, repeat, _} = CommonAPI.repeat(activity_two.id, user) {:ok, repeat, _} = CommonAPI.repeat(activity_two.id, user)
{:ok, job} = User.delete(user) {:ok, _job} = User.delete(user)
{:ok, _user} = ObanHelpers.perform(job) ObanHelpers.perform_all()
follower = User.get_cached_by_id(follower.id) follower = User.get_cached_by_id(follower.id)

View File

@ -1052,23 +1052,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert Repo.aggregate(Object, :count, :id) == 0 assert Repo.aggregate(Object, :count, :id) == 0
end end
test "it reverts unfollow activity" do
follower = insert(:user)
followed = insert(:user)
{:ok, follow_activity} = ActivityPub.follow(follower, followed)
with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
assert {:error, :reverted} = ActivityPub.unfollow(follower, followed)
end
activity = Activity.get_by_id(follow_activity.id)
assert activity.data["type"] == "Follow"
assert activity.data["actor"] == follower.ap_id
assert activity.data["object"] == followed.ap_id
end
test "creates a follow activity" do test "creates a follow activity" do
follower = insert(:user) follower = insert(:user)
followed = insert(:user) followed = insert(:user)
@ -1078,40 +1061,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert activity.data["actor"] == follower.ap_id assert activity.data["actor"] == follower.ap_id
assert activity.data["object"] == followed.ap_id assert activity.data["object"] == followed.ap_id
end end
test "creates an undo activity for the last follow" do
follower = insert(:user)
followed = insert(:user)
{:ok, follow_activity} = ActivityPub.follow(follower, followed)
{:ok, activity} = ActivityPub.unfollow(follower, followed)
assert activity.data["type"] == "Undo"
assert activity.data["actor"] == follower.ap_id
embedded_object = activity.data["object"]
assert is_map(embedded_object)
assert embedded_object["type"] == "Follow"
assert embedded_object["object"] == followed.ap_id
assert embedded_object["id"] == follow_activity.data["id"]
end
test "creates an undo activity for a pending follow request" do
follower = insert(:user)
followed = insert(:user, %{locked: true})
{:ok, follow_activity} = ActivityPub.follow(follower, followed)
{:ok, activity} = ActivityPub.unfollow(follower, followed)
assert activity.data["type"] == "Undo"
assert activity.data["actor"] == follower.ap_id
embedded_object = activity.data["object"]
assert is_map(embedded_object)
assert embedded_object["type"] == "Follow"
assert embedded_object["object"] == followed.ap_id
assert embedded_object["id"] == follow_activity.data["id"]
end
end end
describe "blocking" do describe "blocking" do

View File

@ -21,12 +21,15 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
setup do setup do
poster = insert(:user) poster = insert(:user)
user = insert(:user) user = insert(:user)
followed = insert(:user)
{:ok, post} = CommonAPI.post(poster, %{"status" => "hey"}) {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
{:ok, like} = CommonAPI.favorite(user, post.id) {:ok, like} = CommonAPI.favorite(user, post.id)
{:ok, reaction, _} = CommonAPI.react_with_emoji(post.id, user, "👍") {:ok, reaction, _} = CommonAPI.react_with_emoji(post.id, user, "👍")
{:ok, announce, _} = CommonAPI.repeat(post.id, user) {:ok, announce, _} = CommonAPI.repeat(post.id, user)
{:ok, block} = ActivityPub.block(user, poster) {:ok, block} = ActivityPub.block(user, poster)
User.block(user, poster) User.block(user, poster)
{:ok, user, followed, follow} = CommonAPI.follow(user, followed)
User.subscribe(user, followed)
{:ok, undo_data, _meta} = Builder.undo(user, like) {:ok, undo_data, _meta} = Builder.undo(user, like)
{:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true) {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
@ -40,6 +43,9 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
{:ok, undo_data, _meta} = Builder.undo(user, block) {:ok, undo_data, _meta} = Builder.undo(user, block)
{:ok, block_undo, _meta} = ActivityPub.persist(undo_data, local: true) {:ok, block_undo, _meta} = ActivityPub.persist(undo_data, local: true)
{:ok, undo_data, _meta} = Builder.undo(user, follow)
{:ok, follow_undo, _meta} = ActivityPub.persist(undo_data, local: true)
%{ %{
like_undo: like_undo, like_undo: like_undo,
post: post, post: post,
@ -50,11 +56,31 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
announce: announce, announce: announce,
block_undo: block_undo, block_undo: block_undo,
block: block, block: block,
follow_undo: follow_undo,
follow: follow,
poster: poster, poster: poster,
user: user user: user,
followed: followed
} }
end end
test "deletes the original follow", %{follow_undo: follow_undo, follow: follow} do
{:ok, _follow_undo, _} = SideEffects.handle(follow_undo)
refute Activity.get_by_id(follow.id)
end
test "unfollows and unsubscribes the followed user", %{
follow_undo: follow_undo,
follow: follow
} do
follower = User.get_by_ap_id(follow.data["actor"])
followed = User.get_by_ap_id(follow.data["object"])
{:ok, _follow_undo, _} = SideEffects.handle(follow_undo)
refute User.following?(follower, followed)
refute User.subscribed_to?(follower, followed)
end
test "deletes the original block", %{block_undo: block_undo, block: block} do test "deletes the original block", %{block_undo: block_undo, block: block} do
{:ok, _block_undo, _} = SideEffects.handle(block_undo) {:ok, _block_undo, _} = SideEffects.handle(block_undo)
refute Activity.get_by_id(block.id) refute Activity.get_by_id(block.id)

View File

@ -34,14 +34,15 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do
test "it returns an error for incoming unlikes wihout a like activity" do test "it returns an error for incoming unlikes wihout a like activity" do
user = insert(:user) user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"}) {:ok, _activity} = CommonAPI.post(user, %{"status" => "leave a like pls"})
data = data =
File.read!("test/fixtures/mastodon-undo-like.json") File.read!("test/fixtures/mastodon-undo-like.json")
|> Poison.decode!() |> Poison.decode!()
|> Map.put("object", activity.data["object"]) |> Map.put("object", user.ap_id <> "/activities/likes/1")
|> Map.put("actor", user.ap_id)
assert Transmogrifier.handle_incoming(data) == :error assert {:error, _} = Transmogrifier.handle_incoming(data)
end end
test "it works for incoming unlikes with an existing like activity" do test "it works for incoming unlikes with an existing like activity" do
@ -150,9 +151,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["type"] == "Undo" assert data["type"] == "Undo"
assert data["object"]["type"] == "Follow" assert data["object"] == follow_data["id"]
assert data["object"]["object"] == user.ap_id
assert data["actor"] == "http://mastodon.example.org/users/admin"
refute User.following?(User.get_cached_by_ap_id(data["actor"]), user) refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)
end end

View File

@ -14,6 +14,7 @@ defmodule Pleroma.Web.CommonAPITest do
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
import Pleroma.Factory import Pleroma.Factory
import ExUnit.CaptureLog
require Pleroma.Constants require Pleroma.Constants
@ -601,6 +602,17 @@ defmodule Pleroma.Web.CommonAPITest do
end end
describe "unfollow/2" do describe "unfollow/2" do
test "still works if we don't have an existing follow activity" do
[follower, followed] = insert_pair(:user)
# No activity created here
{:ok, follower} = User.follow(follower, followed)
assert capture_log(fn ->
assert {:ok, _undo} = CommonAPI.unfollow(follower, followed)
end) =~ "No follow activity found"
end
test "also unsubscribes a user" do test "also unsubscribes a user" do
[follower, followed] = insert_pair(:user) [follower, followed] = insert_pair(:user)
{:ok, follower, followed, _} = CommonAPI.follow(follower, followed) {:ok, follower, followed, _} = CommonAPI.follow(follower, followed)
@ -608,7 +620,7 @@ defmodule Pleroma.Web.CommonAPITest do
assert User.subscribed_to?(follower, followed) assert User.subscribed_to?(follower, followed)
{:ok, follower} = CommonAPI.unfollow(follower, followed) {:ok, _undo} = CommonAPI.unfollow(follower, followed)
refute User.subscribed_to?(follower, followed) refute User.subscribed_to?(follower, followed)
end end
@ -621,18 +633,10 @@ defmodule Pleroma.Web.CommonAPITest do
CommonAPI.follow(follower, followed) CommonAPI.follow(follower, followed)
assert User.get_follow_state(follower, followed) == :follow_pending assert User.get_follow_state(follower, followed) == :follow_pending
assert {:ok, follower} = CommonAPI.unfollow(follower, followed) assert {:ok, _undo} = CommonAPI.unfollow(follower, followed)
assert User.get_follow_state(follower, followed) == nil assert User.get_follow_state(follower, followed) == nil
assert %{id: ^activity_id, data: %{"state" => "cancelled"}} = refute Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(follower, followed)
Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(follower, followed)
assert %{
data: %{
"type" => "Undo",
"object" => %{"type" => "Follow", "state" => "cancelled"}
}
} = Pleroma.Web.ActivityPub.Utils.fetch_latest_undo(follower)
end end
test "cancels a pending follow for a remote user" do test "cancels a pending follow for a remote user" do
@ -643,18 +647,10 @@ defmodule Pleroma.Web.CommonAPITest do
CommonAPI.follow(follower, followed) CommonAPI.follow(follower, followed)
assert User.get_follow_state(follower, followed) == :follow_pending assert User.get_follow_state(follower, followed) == :follow_pending
assert {:ok, follower} = CommonAPI.unfollow(follower, followed) assert {:ok, _undo} = CommonAPI.unfollow(follower, followed)
assert User.get_follow_state(follower, followed) == nil assert User.get_follow_state(follower, followed) == nil
assert %{id: ^activity_id, data: %{"state" => "cancelled"}} = refute Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(follower, followed)
Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(follower, followed)
assert %{
data: %{
"type" => "Undo",
"object" => %{"type" => "Follow", "state" => "cancelled"}
}
} = Pleroma.Web.ActivityPub.Utils.fetch_latest_undo(follower)
end end
end end

View File

@ -107,9 +107,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
test_notifications_rendering([notification], followed, [expected]) test_notifications_rendering([notification], followed, [expected])
User.perform(:delete, follower) User.perform(:delete, follower)
notification = Notification |> Repo.one() |> Repo.preload(:activity)
test_notifications_rendering([notification], followed, []) refute Notification
|> Repo.one()
|> Repo.preload(:activity)
end end
@tag capture_log: true @tag capture_log: true