Merge branch 'fix-varnish-chunked' into 'develop'
[akkoma] / test / web / activity_pub / activity_pub_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
6 use Pleroma.Web.ConnCase
7 import Pleroma.Factory
8 alias Pleroma.Web.ActivityPub.{UserView, ObjectView}
9 alias Pleroma.{Object, Repo, User}
10 alias Pleroma.Activity
11
12 setup_all do
13 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
14 :ok
15 end
16
17 describe "/relay" do
18 test "with the relay active, it returns the relay user", %{conn: conn} do
19 res =
20 conn
21 |> get(activity_pub_path(conn, :relay))
22 |> json_response(200)
23
24 assert res["id"] =~ "/relay"
25 end
26
27 test "with the relay disabled, it returns 404", %{conn: conn} do
28 Pleroma.Config.put([:instance, :allow_relay], false)
29
30 conn
31 |> get(activity_pub_path(conn, :relay))
32 |> json_response(404)
33 |> assert
34
35 Pleroma.Config.put([:instance, :allow_relay], true)
36 end
37 end
38
39 describe "/users/:nickname" do
40 test "it returns a json representation of the user", %{conn: conn} do
41 user = insert(:user)
42
43 conn =
44 conn
45 |> put_req_header("accept", "application/activity+json")
46 |> get("/users/#{user.nickname}")
47
48 user = Repo.get(User, user.id)
49
50 assert json_response(conn, 200) == UserView.render("user.json", %{user: user})
51 end
52 end
53
54 describe "/object/:uuid" do
55 test "it returns a json representation of the object", %{conn: conn} do
56 note = insert(:note)
57 uuid = String.split(note.data["id"], "/") |> List.last()
58
59 conn =
60 conn
61 |> put_req_header("accept", "application/activity+json")
62 |> get("/objects/#{uuid}")
63
64 assert json_response(conn, 200) == ObjectView.render("object.json", %{object: note})
65 end
66
67 test "it returns 404 for non-public messages", %{conn: conn} do
68 note = insert(:direct_note)
69 uuid = String.split(note.data["id"], "/") |> List.last()
70
71 conn =
72 conn
73 |> put_req_header("accept", "application/activity+json")
74 |> get("/objects/#{uuid}")
75
76 assert json_response(conn, 404)
77 end
78
79 test "it returns 404 for tombstone objects", %{conn: conn} do
80 tombstone = insert(:tombstone)
81 uuid = String.split(tombstone.data["id"], "/") |> List.last()
82
83 conn =
84 conn
85 |> put_req_header("accept", "application/activity+json")
86 |> get("/objects/#{uuid}")
87
88 assert json_response(conn, 404)
89 end
90 end
91
92 describe "/activities/:uuid" do
93 test "it returns a json representation of the activity", %{conn: conn} do
94 activity = insert(:note_activity)
95 uuid = String.split(activity.data["id"], "/") |> List.last()
96
97 conn =
98 conn
99 |> put_req_header("accept", "application/activity+json")
100 |> get("/activities/#{uuid}")
101
102 assert json_response(conn, 200) == ObjectView.render("object.json", %{object: activity})
103 end
104
105 test "it returns 404 for non-public activities", %{conn: conn} do
106 activity = insert(:direct_note_activity)
107 uuid = String.split(activity.data["id"], "/") |> List.last()
108
109 conn =
110 conn
111 |> put_req_header("accept", "application/activity+json")
112 |> get("/activities/#{uuid}")
113
114 assert json_response(conn, 404)
115 end
116 end
117
118 describe "/inbox" do
119 test "it inserts an incoming activity into the database", %{conn: conn} do
120 data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
121
122 conn =
123 conn
124 |> assign(:valid_signature, true)
125 |> put_req_header("content-type", "application/activity+json")
126 |> post("/inbox", data)
127
128 assert "ok" == json_response(conn, 200)
129 :timer.sleep(500)
130 assert Activity.get_by_ap_id(data["id"])
131 end
132 end
133
134 describe "/users/:nickname/inbox" do
135 test "it inserts an incoming activity into the database", %{conn: conn} do
136 user = insert(:user)
137
138 data =
139 File.read!("test/fixtures/mastodon-post-activity.json")
140 |> Poison.decode!()
141 |> Map.put("bcc", [user.ap_id])
142
143 conn =
144 conn
145 |> assign(:valid_signature, true)
146 |> put_req_header("content-type", "application/activity+json")
147 |> post("/users/#{user.nickname}/inbox", data)
148
149 assert "ok" == json_response(conn, 200)
150 :timer.sleep(500)
151 assert Activity.get_by_ap_id(data["id"])
152 end
153
154 test "it rejects reads from other users", %{conn: conn} do
155 user = insert(:user)
156 otheruser = insert(:user)
157
158 conn =
159 conn
160 |> assign(:user, otheruser)
161 |> put_req_header("accept", "application/activity+json")
162 |> get("/users/#{user.nickname}/inbox")
163
164 assert json_response(conn, 403)
165 end
166
167 test "it returns a note activity in a collection", %{conn: conn} do
168 note_activity = insert(:direct_note_activity)
169 user = User.get_cached_by_ap_id(hd(note_activity.data["to"]))
170
171 conn =
172 conn
173 |> assign(:user, user)
174 |> put_req_header("accept", "application/activity+json")
175 |> get("/users/#{user.nickname}/inbox")
176
177 assert response(conn, 200) =~ note_activity.data["object"]["content"]
178 end
179 end
180
181 describe "/users/:nickname/outbox" do
182 test "it returns a note activity in a collection", %{conn: conn} do
183 note_activity = insert(:note_activity)
184 user = User.get_cached_by_ap_id(note_activity.data["actor"])
185
186 conn =
187 conn
188 |> put_req_header("accept", "application/activity+json")
189 |> get("/users/#{user.nickname}/outbox")
190
191 assert response(conn, 200) =~ note_activity.data["object"]["content"]
192 end
193
194 test "it returns an announce activity in a collection", %{conn: conn} do
195 announce_activity = insert(:announce_activity)
196 user = User.get_cached_by_ap_id(announce_activity.data["actor"])
197
198 conn =
199 conn
200 |> put_req_header("accept", "application/activity+json")
201 |> get("/users/#{user.nickname}/outbox")
202
203 assert response(conn, 200) =~ announce_activity.data["object"]
204 end
205
206 test "it rejects posts from other users", %{conn: conn} do
207 data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
208 user = insert(:user)
209 otheruser = insert(:user)
210
211 conn =
212 conn
213 |> assign(:user, otheruser)
214 |> put_req_header("content-type", "application/activity+json")
215 |> post("/users/#{user.nickname}/outbox", data)
216
217 assert json_response(conn, 403)
218 end
219
220 test "it inserts an incoming create activity into the database", %{conn: conn} do
221 data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
222 user = insert(:user)
223
224 conn =
225 conn
226 |> assign(:user, user)
227 |> put_req_header("content-type", "application/activity+json")
228 |> post("/users/#{user.nickname}/outbox", data)
229
230 result = json_response(conn, 201)
231 assert Activity.get_by_ap_id(result["id"])
232 end
233
234 test "it rejects an incoming activity with bogus type", %{conn: conn} do
235 data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
236 user = insert(:user)
237
238 data =
239 data
240 |> Map.put("type", "BadType")
241
242 conn =
243 conn
244 |> assign(:user, user)
245 |> put_req_header("content-type", "application/activity+json")
246 |> post("/users/#{user.nickname}/outbox", data)
247
248 assert json_response(conn, 400)
249 end
250
251 test "it erects a tombstone when receiving a delete activity", %{conn: conn} do
252 note_activity = insert(:note_activity)
253 user = User.get_cached_by_ap_id(note_activity.data["actor"])
254
255 data = %{
256 type: "Delete",
257 object: %{
258 id: note_activity.data["object"]["id"]
259 }
260 }
261
262 conn =
263 conn
264 |> assign(:user, user)
265 |> put_req_header("content-type", "application/activity+json")
266 |> post("/users/#{user.nickname}/outbox", data)
267
268 result = json_response(conn, 201)
269 assert Activity.get_by_ap_id(result["id"])
270
271 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
272 assert object
273 assert object.data["type"] == "Tombstone"
274 end
275
276 test "it rejects delete activity of object from other actor", %{conn: conn} do
277 note_activity = insert(:note_activity)
278 user = insert(:user)
279
280 data = %{
281 type: "Delete",
282 object: %{
283 id: note_activity.data["object"]["id"]
284 }
285 }
286
287 conn =
288 conn
289 |> assign(:user, user)
290 |> put_req_header("content-type", "application/activity+json")
291 |> post("/users/#{user.nickname}/outbox", data)
292
293 assert json_response(conn, 400)
294 end
295 end
296
297 describe "/users/:nickname/followers" do
298 test "it returns the followers in a collection", %{conn: conn} do
299 user = insert(:user)
300 user_two = insert(:user)
301 User.follow(user, user_two)
302
303 result =
304 conn
305 |> get("/users/#{user_two.nickname}/followers")
306 |> json_response(200)
307
308 assert result["first"]["orderedItems"] == [user.ap_id]
309 end
310
311 test "it returns returns empty if the user has 'hide_network' set", %{conn: conn} do
312 user = insert(:user)
313 user_two = insert(:user, %{info: %{hide_network: true}})
314 User.follow(user, user_two)
315
316 result =
317 conn
318 |> get("/users/#{user_two.nickname}/followers")
319 |> json_response(200)
320
321 assert result["first"]["orderedItems"] == []
322 assert result["totalItems"] == 1
323 end
324
325 test "it works for more than 10 users", %{conn: conn} do
326 user = insert(:user)
327
328 Enum.each(1..15, fn _ ->
329 other_user = insert(:user)
330 User.follow(other_user, user)
331 end)
332
333 result =
334 conn
335 |> get("/users/#{user.nickname}/followers")
336 |> json_response(200)
337
338 assert length(result["first"]["orderedItems"]) == 10
339 assert result["first"]["totalItems"] == 15
340 assert result["totalItems"] == 15
341
342 result =
343 conn
344 |> get("/users/#{user.nickname}/followers?page=2")
345 |> json_response(200)
346
347 assert length(result["orderedItems"]) == 5
348 assert result["totalItems"] == 15
349 end
350 end
351
352 describe "/users/:nickname/following" do
353 test "it returns the following in a collection", %{conn: conn} do
354 user = insert(:user)
355 user_two = insert(:user)
356 User.follow(user, user_two)
357
358 result =
359 conn
360 |> get("/users/#{user.nickname}/following")
361 |> json_response(200)
362
363 assert result["first"]["orderedItems"] == [user_two.ap_id]
364 end
365
366 test "it returns returns empty if the user has 'hide_network' set", %{conn: conn} do
367 user = insert(:user, %{info: %{hide_network: true}})
368 user_two = insert(:user)
369 User.follow(user, user_two)
370
371 result =
372 conn
373 |> get("/users/#{user.nickname}/following")
374 |> json_response(200)
375
376 assert result["first"]["orderedItems"] == []
377 assert result["totalItems"] == 1
378 end
379
380 test "it works for more than 10 users", %{conn: conn} do
381 user = insert(:user)
382
383 Enum.each(1..15, fn _ ->
384 user = Repo.get(User, user.id)
385 other_user = insert(:user)
386 User.follow(user, other_user)
387 end)
388
389 result =
390 conn
391 |> get("/users/#{user.nickname}/following")
392 |> json_response(200)
393
394 assert length(result["first"]["orderedItems"]) == 10
395 assert result["first"]["totalItems"] == 15
396 assert result["totalItems"] == 15
397
398 result =
399 conn
400 |> get("/users/#{user.nickname}/following?page=2")
401 |> json_response(200)
402
403 assert length(result["orderedItems"]) == 5
404 assert result["totalItems"] == 15
405 end
406 end
407 end