move to 2.5.5
[anni] / test / pleroma / web / activity_pub / transmogrifier / follow_handling_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
6   use Pleroma.DataCase
7   alias Pleroma.Activity
8   alias Pleroma.Notification
9   alias Pleroma.Repo
10   alias Pleroma.User
11   alias Pleroma.Web.ActivityPub.Transmogrifier
12   alias Pleroma.Web.ActivityPub.Utils
13
14   import Pleroma.Factory
15   import Ecto.Query
16   import Mock
17
18   setup_all do
19     Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
20     :ok
21   end
22
23   describe "handle_incoming" do
24     setup do: clear_config([:user, :deny_follow_blocked])
25
26     test "it works for osada follow request" do
27       user = insert(:user)
28
29       data =
30         File.read!("test/fixtures/osada-follow-activity.json")
31         |> Jason.decode!()
32         |> Map.put("object", user.ap_id)
33
34       {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
35
36       assert data["actor"] == "https://apfed.club/channel/indio"
37       assert data["type"] == "Follow"
38       assert data["id"] == "https://apfed.club/follow/9"
39
40       activity = Repo.get(Activity, activity.id)
41       assert activity.data["state"] == "accept"
42       assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
43     end
44
45     test "it works for incoming follow requests" do
46       user = insert(:user)
47
48       data =
49         File.read!("test/fixtures/mastodon-follow-activity.json")
50         |> Jason.decode!()
51         |> Map.put("object", user.ap_id)
52
53       {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
54
55       assert data["actor"] == "http://mastodon.example.org/users/admin"
56       assert data["type"] == "Follow"
57       assert data["id"] == "http://mastodon.example.org/users/admin#follows/2"
58
59       activity = Repo.get(Activity, activity.id)
60       assert activity.data["state"] == "accept"
61       assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
62
63       [notification] = Notification.for_user(user)
64       assert notification.type == "follow"
65     end
66
67     test "with locked accounts, it does create a Follow, but not an Accept" do
68       user = insert(:user, is_locked: true)
69
70       data =
71         File.read!("test/fixtures/mastodon-follow-activity.json")
72         |> Jason.decode!()
73         |> Map.put("object", user.ap_id)
74
75       {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
76
77       assert data["state"] == "pending"
78
79       refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)
80
81       accepts =
82         from(
83           a in Activity,
84           where: fragment("?->>'type' = ?", a.data, "Accept")
85         )
86         |> Repo.all()
87
88       assert Enum.empty?(accepts)
89
90       [notification] = Notification.for_user(user)
91       assert notification.type == "follow_request"
92     end
93
94     test "it works for follow requests when you are already followed, creating a new accept activity" do
95       # This is important because the remote might have the wrong idea about the
96       # current follow status. This can lead to instance A thinking that x@A is
97       # followed by y@B, but B thinks they are not. In this case, the follow can
98       # never go through again because it will never get an Accept.
99       user = insert(:user)
100
101       data =
102         File.read!("test/fixtures/mastodon-follow-activity.json")
103         |> Jason.decode!()
104         |> Map.put("object", user.ap_id)
105
106       {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
107
108       accepts =
109         from(
110           a in Activity,
111           where: fragment("?->>'type' = ?", a.data, "Accept")
112         )
113         |> Repo.all()
114
115       assert length(accepts) == 1
116
117       data =
118         File.read!("test/fixtures/mastodon-follow-activity.json")
119         |> Jason.decode!()
120         |> Map.put("id", String.replace(data["id"], "2", "3"))
121         |> Map.put("object", user.ap_id)
122
123       {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
124
125       accepts =
126         from(
127           a in Activity,
128           where: fragment("?->>'type' = ?", a.data, "Accept")
129         )
130         |> Repo.all()
131
132       assert length(accepts) == 2
133     end
134
135     test "it rejects incoming follow requests from blocked users when deny_follow_blocked is enabled" do
136       clear_config([:user, :deny_follow_blocked], true)
137
138       user = insert(:user)
139       {:ok, target} = User.get_or_fetch("http://mastodon.example.org/users/admin")
140
141       {:ok, _user_relationship} = User.block(user, target)
142
143       data =
144         File.read!("test/fixtures/mastodon-follow-activity.json")
145         |> Jason.decode!()
146         |> Map.put("object", user.ap_id)
147
148       {:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data)
149
150       %Activity{} = activity = Activity.get_by_ap_id(id)
151
152       assert activity.data["state"] == "reject"
153     end
154
155     test "it rejects incoming follow requests if the following errors for some reason" do
156       user = insert(:user)
157
158       data =
159         File.read!("test/fixtures/mastodon-follow-activity.json")
160         |> Jason.decode!()
161         |> Map.put("object", user.ap_id)
162
163       with_mock Pleroma.User, [:passthrough], follow: fn _, _, _ -> {:error, :testing} end do
164         {:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data)
165
166         %Activity{} = activity = Activity.get_by_ap_id(id)
167
168         assert activity.data["state"] == "reject"
169       end
170     end
171
172     test "it works for incoming follow requests from hubzilla" do
173       user = insert(:user)
174
175       data =
176         File.read!("test/fixtures/hubzilla-follow-activity.json")
177         |> Jason.decode!()
178         |> Map.put("object", user.ap_id)
179         |> Utils.normalize_params()
180
181       {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
182
183       assert data["actor"] == "https://hubzilla.example.org/channel/kaniini"
184       assert data["type"] == "Follow"
185       assert data["id"] == "https://hubzilla.example.org/channel/kaniini#follows/2"
186       assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
187     end
188
189     test "it works for incoming follows to locked account" do
190       pending_follower = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
191       user = insert(:user, is_locked: true)
192
193       data =
194         File.read!("test/fixtures/mastodon-follow-activity.json")
195         |> Jason.decode!()
196         |> Map.put("object", user.ap_id)
197
198       {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
199
200       assert data["type"] == "Follow"
201       assert data["object"] == user.ap_id
202       assert data["state"] == "pending"
203       assert data["actor"] == "http://mastodon.example.org/users/admin"
204
205       assert [^pending_follower] = User.get_follow_requests(user)
206     end
207   end
208 end