Merge remote-tracking branch 'origin/develop' into benchmark-finishing
[akkoma] / test / web / activity_pub / activity_pub_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 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 use Oban.Testing, repo: Pleroma.Repo
8
9 import Pleroma.Factory
10 alias Pleroma.Activity
11 alias Pleroma.Delivery
12 alias Pleroma.Instances
13 alias Pleroma.Object
14 alias Pleroma.Tests.ObanHelpers
15 alias Pleroma.User
16 alias Pleroma.Web.ActivityPub.ObjectView
17 alias Pleroma.Web.ActivityPub.Relay
18 alias Pleroma.Web.ActivityPub.UserView
19 alias Pleroma.Web.ActivityPub.Utils
20 alias Pleroma.Web.CommonAPI
21 alias Pleroma.Workers.ReceiverWorker
22
23 setup_all do
24 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
25 :ok
26 end
27
28 clear_config_all([:instance, :federating],
29 do: Pleroma.Config.put([:instance, :federating], true)
30 )
31
32 describe "/relay" do
33 clear_config([:instance, :allow_relay])
34
35 test "with the relay active, it returns the relay user", %{conn: conn} do
36 res =
37 conn
38 |> get(activity_pub_path(conn, :relay))
39 |> json_response(200)
40
41 assert res["id"] =~ "/relay"
42 end
43
44 test "with the relay disabled, it returns 404", %{conn: conn} do
45 Pleroma.Config.put([:instance, :allow_relay], false)
46
47 conn
48 |> get(activity_pub_path(conn, :relay))
49 |> json_response(404)
50 |> assert
51 end
52 end
53
54 describe "/internal/fetch" do
55 test "it returns the internal fetch user", %{conn: conn} do
56 res =
57 conn
58 |> get(activity_pub_path(conn, :internal_fetch))
59 |> json_response(200)
60
61 assert res["id"] =~ "/fetch"
62 end
63 end
64
65 describe "/users/:nickname" do
66 test "it returns a json representation of the user with accept application/json", %{
67 conn: conn
68 } do
69 user = insert(:user)
70
71 conn =
72 conn
73 |> put_req_header("accept", "application/json")
74 |> get("/users/#{user.nickname}")
75
76 user = User.get_cached_by_id(user.id)
77
78 assert json_response(conn, 200) == UserView.render("user.json", %{user: user})
79 end
80
81 test "it returns a json representation of the user with accept application/activity+json", %{
82 conn: conn
83 } do
84 user = insert(:user)
85
86 conn =
87 conn
88 |> put_req_header("accept", "application/activity+json")
89 |> get("/users/#{user.nickname}")
90
91 user = User.get_cached_by_id(user.id)
92
93 assert json_response(conn, 200) == UserView.render("user.json", %{user: user})
94 end
95
96 test "it returns a json representation of the user with accept application/ld+json", %{
97 conn: conn
98 } do
99 user = insert(:user)
100
101 conn =
102 conn
103 |> put_req_header(
104 "accept",
105 "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
106 )
107 |> get("/users/#{user.nickname}")
108
109 user = User.get_cached_by_id(user.id)
110
111 assert json_response(conn, 200) == UserView.render("user.json", %{user: user})
112 end
113 end
114
115 describe "/object/:uuid" do
116 test "it returns a json representation of the object with accept application/json", %{
117 conn: conn
118 } do
119 note = insert(:note)
120 uuid = String.split(note.data["id"], "/") |> List.last()
121
122 conn =
123 conn
124 |> put_req_header("accept", "application/json")
125 |> get("/objects/#{uuid}")
126
127 assert json_response(conn, 200) == ObjectView.render("object.json", %{object: note})
128 end
129
130 test "it returns a json representation of the object with accept application/activity+json",
131 %{conn: conn} do
132 note = insert(:note)
133 uuid = String.split(note.data["id"], "/") |> List.last()
134
135 conn =
136 conn
137 |> put_req_header("accept", "application/activity+json")
138 |> get("/objects/#{uuid}")
139
140 assert json_response(conn, 200) == ObjectView.render("object.json", %{object: note})
141 end
142
143 test "it returns a json representation of the object with accept application/ld+json", %{
144 conn: conn
145 } do
146 note = insert(:note)
147 uuid = String.split(note.data["id"], "/") |> List.last()
148
149 conn =
150 conn
151 |> put_req_header(
152 "accept",
153 "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
154 )
155 |> get("/objects/#{uuid}")
156
157 assert json_response(conn, 200) == ObjectView.render("object.json", %{object: note})
158 end
159
160 test "it returns 404 for non-public messages", %{conn: conn} do
161 note = insert(:direct_note)
162 uuid = String.split(note.data["id"], "/") |> List.last()
163
164 conn =
165 conn
166 |> put_req_header("accept", "application/activity+json")
167 |> get("/objects/#{uuid}")
168
169 assert json_response(conn, 404)
170 end
171
172 test "it returns 404 for tombstone objects", %{conn: conn} do
173 tombstone = insert(:tombstone)
174 uuid = String.split(tombstone.data["id"], "/") |> List.last()
175
176 conn =
177 conn
178 |> put_req_header("accept", "application/activity+json")
179 |> get("/objects/#{uuid}")
180
181 assert json_response(conn, 404)
182 end
183
184 test "it caches a response", %{conn: conn} do
185 note = insert(:note)
186 uuid = String.split(note.data["id"], "/") |> List.last()
187
188 conn1 =
189 conn
190 |> put_req_header("accept", "application/activity+json")
191 |> get("/objects/#{uuid}")
192
193 assert json_response(conn1, :ok)
194 assert Enum.any?(conn1.resp_headers, &(&1 == {"x-cache", "MISS from Pleroma"}))
195
196 conn2 =
197 conn
198 |> put_req_header("accept", "application/activity+json")
199 |> get("/objects/#{uuid}")
200
201 assert json_response(conn1, :ok) == json_response(conn2, :ok)
202 assert Enum.any?(conn2.resp_headers, &(&1 == {"x-cache", "HIT from Pleroma"}))
203 end
204
205 test "cached purged after object deletion", %{conn: conn} do
206 note = insert(:note)
207 uuid = String.split(note.data["id"], "/") |> List.last()
208
209 conn1 =
210 conn
211 |> put_req_header("accept", "application/activity+json")
212 |> get("/objects/#{uuid}")
213
214 assert json_response(conn1, :ok)
215 assert Enum.any?(conn1.resp_headers, &(&1 == {"x-cache", "MISS from Pleroma"}))
216
217 Object.delete(note)
218
219 conn2 =
220 conn
221 |> put_req_header("accept", "application/activity+json")
222 |> get("/objects/#{uuid}")
223
224 assert "Not found" == json_response(conn2, :not_found)
225 end
226 end
227
228 describe "/activities/:uuid" do
229 test "it returns a json representation of the activity", %{conn: conn} do
230 activity = insert(:note_activity)
231 uuid = String.split(activity.data["id"], "/") |> List.last()
232
233 conn =
234 conn
235 |> put_req_header("accept", "application/activity+json")
236 |> get("/activities/#{uuid}")
237
238 assert json_response(conn, 200) == ObjectView.render("object.json", %{object: activity})
239 end
240
241 test "it returns 404 for non-public activities", %{conn: conn} do
242 activity = insert(:direct_note_activity)
243 uuid = String.split(activity.data["id"], "/") |> List.last()
244
245 conn =
246 conn
247 |> put_req_header("accept", "application/activity+json")
248 |> get("/activities/#{uuid}")
249
250 assert json_response(conn, 404)
251 end
252
253 test "it caches a response", %{conn: conn} do
254 activity = insert(:note_activity)
255 uuid = String.split(activity.data["id"], "/") |> List.last()
256
257 conn1 =
258 conn
259 |> put_req_header("accept", "application/activity+json")
260 |> get("/activities/#{uuid}")
261
262 assert json_response(conn1, :ok)
263 assert Enum.any?(conn1.resp_headers, &(&1 == {"x-cache", "MISS from Pleroma"}))
264
265 conn2 =
266 conn
267 |> put_req_header("accept", "application/activity+json")
268 |> get("/activities/#{uuid}")
269
270 assert json_response(conn1, :ok) == json_response(conn2, :ok)
271 assert Enum.any?(conn2.resp_headers, &(&1 == {"x-cache", "HIT from Pleroma"}))
272 end
273
274 test "cached purged after activity deletion", %{conn: conn} do
275 user = insert(:user)
276 {:ok, activity} = CommonAPI.post(user, %{"status" => "cofe"})
277
278 uuid = String.split(activity.data["id"], "/") |> List.last()
279
280 conn1 =
281 conn
282 |> put_req_header("accept", "application/activity+json")
283 |> get("/activities/#{uuid}")
284
285 assert json_response(conn1, :ok)
286 assert Enum.any?(conn1.resp_headers, &(&1 == {"x-cache", "MISS from Pleroma"}))
287
288 Activity.delete_by_ap_id(activity.object.data["id"])
289
290 conn2 =
291 conn
292 |> put_req_header("accept", "application/activity+json")
293 |> get("/activities/#{uuid}")
294
295 assert "Not found" == json_response(conn2, :not_found)
296 end
297 end
298
299 describe "/inbox" do
300 test "it inserts an incoming activity into the database", %{conn: conn} do
301 data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
302
303 conn =
304 conn
305 |> assign(:valid_signature, true)
306 |> put_req_header("content-type", "application/activity+json")
307 |> post("/inbox", data)
308
309 assert "ok" == json_response(conn, 200)
310
311 ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
312 assert Activity.get_by_ap_id(data["id"])
313 end
314
315 test "it clears `unreachable` federation status of the sender", %{conn: conn} do
316 data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
317
318 sender_url = data["actor"]
319 Instances.set_consistently_unreachable(sender_url)
320 refute Instances.reachable?(sender_url)
321
322 conn =
323 conn
324 |> assign(:valid_signature, true)
325 |> put_req_header("content-type", "application/activity+json")
326 |> post("/inbox", data)
327
328 assert "ok" == json_response(conn, 200)
329 assert Instances.reachable?(sender_url)
330 end
331 end
332
333 describe "/users/:nickname/inbox" do
334 setup do
335 data =
336 File.read!("test/fixtures/mastodon-post-activity.json")
337 |> Poison.decode!()
338
339 [data: data]
340 end
341
342 test "it inserts an incoming activity into the database", %{conn: conn, data: data} do
343 user = insert(:user)
344 data = Map.put(data, "bcc", [user.ap_id])
345
346 conn =
347 conn
348 |> assign(:valid_signature, true)
349 |> put_req_header("content-type", "application/activity+json")
350 |> post("/users/#{user.nickname}/inbox", data)
351
352 assert "ok" == json_response(conn, 200)
353 ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
354 assert Activity.get_by_ap_id(data["id"])
355 end
356
357 test "it accepts messages from actors that are followed by the user", %{
358 conn: conn,
359 data: data
360 } do
361 recipient = insert(:user)
362 actor = insert(:user, %{ap_id: "http://mastodon.example.org/users/actor"})
363
364 {:ok, recipient} = User.follow(recipient, actor)
365
366 object =
367 data["object"]
368 |> Map.put("attributedTo", actor.ap_id)
369
370 data =
371 data
372 |> Map.put("actor", actor.ap_id)
373 |> Map.put("object", object)
374
375 conn =
376 conn
377 |> assign(:valid_signature, true)
378 |> put_req_header("content-type", "application/activity+json")
379 |> post("/users/#{recipient.nickname}/inbox", data)
380
381 assert "ok" == json_response(conn, 200)
382 ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
383 assert Activity.get_by_ap_id(data["id"])
384 end
385
386 test "it rejects reads from other users", %{conn: conn} do
387 user = insert(:user)
388 otheruser = insert(:user)
389
390 conn =
391 conn
392 |> assign(:user, otheruser)
393 |> put_req_header("accept", "application/activity+json")
394 |> get("/users/#{user.nickname}/inbox")
395
396 assert json_response(conn, 403)
397 end
398
399 test "it doesn't crash without an authenticated user", %{conn: conn} do
400 user = insert(:user)
401
402 conn =
403 conn
404 |> put_req_header("accept", "application/activity+json")
405 |> get("/users/#{user.nickname}/inbox")
406
407 assert json_response(conn, 403)
408 end
409
410 test "it returns a note activity in a collection", %{conn: conn} do
411 note_activity = insert(:direct_note_activity)
412 note_object = Object.normalize(note_activity)
413 user = User.get_cached_by_ap_id(hd(note_activity.data["to"]))
414
415 conn =
416 conn
417 |> assign(:user, user)
418 |> put_req_header("accept", "application/activity+json")
419 |> get("/users/#{user.nickname}/inbox?page=true")
420
421 assert response(conn, 200) =~ note_object.data["content"]
422 end
423
424 test "it clears `unreachable` federation status of the sender", %{conn: conn, data: data} do
425 user = insert(:user)
426 data = Map.put(data, "bcc", [user.ap_id])
427
428 sender_host = URI.parse(data["actor"]).host
429 Instances.set_consistently_unreachable(sender_host)
430 refute Instances.reachable?(sender_host)
431
432 conn =
433 conn
434 |> assign(:valid_signature, true)
435 |> put_req_header("content-type", "application/activity+json")
436 |> post("/users/#{user.nickname}/inbox", data)
437
438 assert "ok" == json_response(conn, 200)
439 assert Instances.reachable?(sender_host)
440 end
441
442 test "it removes all follower collections but actor's", %{conn: conn} do
443 [actor, recipient] = insert_pair(:user)
444
445 data =
446 File.read!("test/fixtures/activitypub-client-post-activity.json")
447 |> Poison.decode!()
448
449 object = Map.put(data["object"], "attributedTo", actor.ap_id)
450
451 data =
452 data
453 |> Map.put("id", Utils.generate_object_id())
454 |> Map.put("actor", actor.ap_id)
455 |> Map.put("object", object)
456 |> Map.put("cc", [
457 recipient.follower_address,
458 actor.follower_address
459 ])
460 |> Map.put("to", [
461 recipient.ap_id,
462 recipient.follower_address,
463 "https://www.w3.org/ns/activitystreams#Public"
464 ])
465
466 conn
467 |> assign(:valid_signature, true)
468 |> put_req_header("content-type", "application/activity+json")
469 |> post("/users/#{recipient.nickname}/inbox", data)
470 |> json_response(200)
471
472 ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
473
474 activity = Activity.get_by_ap_id(data["id"])
475
476 assert activity.id
477 assert actor.follower_address in activity.recipients
478 assert actor.follower_address in activity.data["cc"]
479
480 refute recipient.follower_address in activity.recipients
481 refute recipient.follower_address in activity.data["cc"]
482 refute recipient.follower_address in activity.data["to"]
483 end
484 end
485
486 describe "/users/:nickname/outbox" do
487 test "it will not bomb when there is no activity", %{conn: conn} do
488 user = insert(:user)
489
490 conn =
491 conn
492 |> put_req_header("accept", "application/activity+json")
493 |> get("/users/#{user.nickname}/outbox")
494
495 result = json_response(conn, 200)
496 assert user.ap_id <> "/outbox" == result["id"]
497 end
498
499 test "it returns a note activity in a collection", %{conn: conn} do
500 note_activity = insert(:note_activity)
501 note_object = Object.normalize(note_activity)
502 user = User.get_cached_by_ap_id(note_activity.data["actor"])
503
504 conn =
505 conn
506 |> put_req_header("accept", "application/activity+json")
507 |> get("/users/#{user.nickname}/outbox?page=true")
508
509 assert response(conn, 200) =~ note_object.data["content"]
510 end
511
512 test "it returns an announce activity in a collection", %{conn: conn} do
513 announce_activity = insert(:announce_activity)
514 user = User.get_cached_by_ap_id(announce_activity.data["actor"])
515
516 conn =
517 conn
518 |> put_req_header("accept", "application/activity+json")
519 |> get("/users/#{user.nickname}/outbox?page=true")
520
521 assert response(conn, 200) =~ announce_activity.data["object"]
522 end
523
524 test "it rejects posts from other users", %{conn: conn} do
525 data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
526 user = insert(:user)
527 otheruser = insert(:user)
528
529 conn =
530 conn
531 |> assign(:user, otheruser)
532 |> put_req_header("content-type", "application/activity+json")
533 |> post("/users/#{user.nickname}/outbox", data)
534
535 assert json_response(conn, 403)
536 end
537
538 test "it inserts an incoming create activity into the database", %{conn: conn} do
539 data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
540 user = insert(:user)
541
542 conn =
543 conn
544 |> assign(:user, user)
545 |> put_req_header("content-type", "application/activity+json")
546 |> post("/users/#{user.nickname}/outbox", data)
547
548 result = json_response(conn, 201)
549
550 assert Activity.get_by_ap_id(result["id"])
551 end
552
553 test "it rejects an incoming activity with bogus type", %{conn: conn} do
554 data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
555 user = insert(:user)
556
557 data =
558 data
559 |> Map.put("type", "BadType")
560
561 conn =
562 conn
563 |> assign(:user, user)
564 |> put_req_header("content-type", "application/activity+json")
565 |> post("/users/#{user.nickname}/outbox", data)
566
567 assert json_response(conn, 400)
568 end
569
570 test "it erects a tombstone when receiving a delete activity", %{conn: conn} do
571 note_activity = insert(:note_activity)
572 note_object = Object.normalize(note_activity)
573 user = User.get_cached_by_ap_id(note_activity.data["actor"])
574
575 data = %{
576 type: "Delete",
577 object: %{
578 id: note_object.data["id"]
579 }
580 }
581
582 conn =
583 conn
584 |> assign(:user, user)
585 |> put_req_header("content-type", "application/activity+json")
586 |> post("/users/#{user.nickname}/outbox", data)
587
588 result = json_response(conn, 201)
589 assert Activity.get_by_ap_id(result["id"])
590
591 assert object = Object.get_by_ap_id(note_object.data["id"])
592 assert object.data["type"] == "Tombstone"
593 end
594
595 test "it rejects delete activity of object from other actor", %{conn: conn} do
596 note_activity = insert(:note_activity)
597 note_object = Object.normalize(note_activity)
598 user = insert(:user)
599
600 data = %{
601 type: "Delete",
602 object: %{
603 id: note_object.data["id"]
604 }
605 }
606
607 conn =
608 conn
609 |> assign(:user, user)
610 |> put_req_header("content-type", "application/activity+json")
611 |> post("/users/#{user.nickname}/outbox", data)
612
613 assert json_response(conn, 400)
614 end
615
616 test "it increases like count when receiving a like action", %{conn: conn} do
617 note_activity = insert(:note_activity)
618 note_object = Object.normalize(note_activity)
619 user = User.get_cached_by_ap_id(note_activity.data["actor"])
620
621 data = %{
622 type: "Like",
623 object: %{
624 id: note_object.data["id"]
625 }
626 }
627
628 conn =
629 conn
630 |> assign(:user, user)
631 |> put_req_header("content-type", "application/activity+json")
632 |> post("/users/#{user.nickname}/outbox", data)
633
634 result = json_response(conn, 201)
635 assert Activity.get_by_ap_id(result["id"])
636
637 assert object = Object.get_by_ap_id(note_object.data["id"])
638 assert object.data["like_count"] == 1
639 end
640 end
641
642 describe "/relay/followers" do
643 test "it returns relay followers", %{conn: conn} do
644 relay_actor = Relay.get_actor()
645 user = insert(:user)
646 User.follow(user, relay_actor)
647
648 result =
649 conn
650 |> assign(:relay, true)
651 |> get("/relay/followers")
652 |> json_response(200)
653
654 assert result["first"]["orderedItems"] == [user.ap_id]
655 end
656 end
657
658 describe "/relay/following" do
659 test "it returns relay following", %{conn: conn} do
660 result =
661 conn
662 |> assign(:relay, true)
663 |> get("/relay/following")
664 |> json_response(200)
665
666 assert result["first"]["orderedItems"] == []
667 end
668 end
669
670 describe "/users/:nickname/followers" do
671 test "it returns the followers in a collection", %{conn: conn} do
672 user = insert(:user)
673 user_two = insert(:user)
674 User.follow(user, user_two)
675
676 result =
677 conn
678 |> get("/users/#{user_two.nickname}/followers")
679 |> json_response(200)
680
681 assert result["first"]["orderedItems"] == [user.ap_id]
682 end
683
684 test "it returns returns a uri if the user has 'hide_followers' set", %{conn: conn} do
685 user = insert(:user)
686 user_two = insert(:user, %{info: %{hide_followers: true}})
687 User.follow(user, user_two)
688
689 result =
690 conn
691 |> get("/users/#{user_two.nickname}/followers")
692 |> json_response(200)
693
694 assert is_binary(result["first"])
695 end
696
697 test "it returns a 403 error on pages, if the user has 'hide_followers' set and the request is not authenticated",
698 %{conn: conn} do
699 user = insert(:user, %{info: %{hide_followers: true}})
700
701 result =
702 conn
703 |> get("/users/#{user.nickname}/followers?page=1")
704
705 assert result.status == 403
706 assert result.resp_body == ""
707 end
708
709 test "it renders the page, if the user has 'hide_followers' set and the request is authenticated with the same user",
710 %{conn: conn} do
711 user = insert(:user, %{info: %{hide_followers: true}})
712 other_user = insert(:user)
713 {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
714
715 result =
716 conn
717 |> assign(:user, user)
718 |> get("/users/#{user.nickname}/followers?page=1")
719 |> json_response(200)
720
721 assert result["totalItems"] == 1
722 assert result["orderedItems"] == [other_user.ap_id]
723 end
724
725 test "it works for more than 10 users", %{conn: conn} do
726 user = insert(:user)
727
728 Enum.each(1..15, fn _ ->
729 other_user = insert(:user)
730 User.follow(other_user, user)
731 end)
732
733 result =
734 conn
735 |> get("/users/#{user.nickname}/followers")
736 |> json_response(200)
737
738 assert length(result["first"]["orderedItems"]) == 10
739 assert result["first"]["totalItems"] == 15
740 assert result["totalItems"] == 15
741
742 result =
743 conn
744 |> get("/users/#{user.nickname}/followers?page=2")
745 |> json_response(200)
746
747 assert length(result["orderedItems"]) == 5
748 assert result["totalItems"] == 15
749 end
750 end
751
752 describe "/users/:nickname/following" do
753 test "it returns the following in a collection", %{conn: conn} do
754 user = insert(:user)
755 user_two = insert(:user)
756 User.follow(user, user_two)
757
758 result =
759 conn
760 |> get("/users/#{user.nickname}/following")
761 |> json_response(200)
762
763 assert result["first"]["orderedItems"] == [user_two.ap_id]
764 end
765
766 test "it returns a uri if the user has 'hide_follows' set", %{conn: conn} do
767 user = insert(:user, %{info: %{hide_follows: true}})
768 user_two = insert(:user)
769 User.follow(user, user_two)
770
771 result =
772 conn
773 |> get("/users/#{user.nickname}/following")
774 |> json_response(200)
775
776 assert is_binary(result["first"])
777 end
778
779 test "it returns a 403 error on pages, if the user has 'hide_follows' set and the request is not authenticated",
780 %{conn: conn} do
781 user = insert(:user, %{info: %{hide_follows: true}})
782
783 result =
784 conn
785 |> get("/users/#{user.nickname}/following?page=1")
786
787 assert result.status == 403
788 assert result.resp_body == ""
789 end
790
791 test "it renders the page, if the user has 'hide_follows' set and the request is authenticated with the same user",
792 %{conn: conn} do
793 user = insert(:user, %{info: %{hide_follows: true}})
794 other_user = insert(:user)
795 {:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
796
797 result =
798 conn
799 |> assign(:user, user)
800 |> get("/users/#{user.nickname}/following?page=1")
801 |> json_response(200)
802
803 assert result["totalItems"] == 1
804 assert result["orderedItems"] == [other_user.ap_id]
805 end
806
807 test "it works for more than 10 users", %{conn: conn} do
808 user = insert(:user)
809
810 Enum.each(1..15, fn _ ->
811 user = User.get_cached_by_id(user.id)
812 other_user = insert(:user)
813 User.follow(user, other_user)
814 end)
815
816 result =
817 conn
818 |> get("/users/#{user.nickname}/following")
819 |> json_response(200)
820
821 assert length(result["first"]["orderedItems"]) == 10
822 assert result["first"]["totalItems"] == 15
823 assert result["totalItems"] == 15
824
825 result =
826 conn
827 |> get("/users/#{user.nickname}/following?page=2")
828 |> json_response(200)
829
830 assert length(result["orderedItems"]) == 5
831 assert result["totalItems"] == 15
832 end
833 end
834
835 describe "delivery tracking" do
836 test "it tracks a signed object fetch", %{conn: conn} do
837 user = insert(:user, local: false)
838 activity = insert(:note_activity)
839 object = Object.normalize(activity)
840
841 object_path = String.trim_leading(object.data["id"], Pleroma.Web.Endpoint.url())
842
843 conn
844 |> put_req_header("accept", "application/activity+json")
845 |> assign(:user, user)
846 |> get(object_path)
847 |> json_response(200)
848
849 assert Delivery.get(object.id, user.id)
850 end
851
852 test "it tracks a signed activity fetch", %{conn: conn} do
853 user = insert(:user, local: false)
854 activity = insert(:note_activity)
855 object = Object.normalize(activity)
856
857 activity_path = String.trim_leading(activity.data["id"], Pleroma.Web.Endpoint.url())
858
859 conn
860 |> put_req_header("accept", "application/activity+json")
861 |> assign(:user, user)
862 |> get(activity_path)
863 |> json_response(200)
864
865 assert Delivery.get(object.id, user.id)
866 end
867
868 test "it tracks a signed object fetch when the json is cached", %{conn: conn} do
869 user = insert(:user, local: false)
870 other_user = insert(:user, local: false)
871 activity = insert(:note_activity)
872 object = Object.normalize(activity)
873
874 object_path = String.trim_leading(object.data["id"], Pleroma.Web.Endpoint.url())
875
876 conn
877 |> put_req_header("accept", "application/activity+json")
878 |> assign(:user, user)
879 |> get(object_path)
880 |> json_response(200)
881
882 build_conn()
883 |> put_req_header("accept", "application/activity+json")
884 |> assign(:user, other_user)
885 |> get(object_path)
886 |> json_response(200)
887
888 assert Delivery.get(object.id, user.id)
889 assert Delivery.get(object.id, other_user.id)
890 end
891
892 test "it tracks a signed activity fetch when the json is cached", %{conn: conn} do
893 user = insert(:user, local: false)
894 other_user = insert(:user, local: false)
895 activity = insert(:note_activity)
896 object = Object.normalize(activity)
897
898 activity_path = String.trim_leading(activity.data["id"], Pleroma.Web.Endpoint.url())
899
900 conn
901 |> put_req_header("accept", "application/activity+json")
902 |> assign(:user, user)
903 |> get(activity_path)
904 |> json_response(200)
905
906 build_conn()
907 |> put_req_header("accept", "application/activity+json")
908 |> assign(:user, other_user)
909 |> get(activity_path)
910 |> json_response(200)
911
912 assert Delivery.get(object.id, user.id)
913 assert Delivery.get(object.id, other_user.id)
914 end
915 end
916
917 describe "Additionnal ActivityPub C2S endpoints" do
918 test "/api/ap/whoami", %{conn: conn} do
919 user = insert(:user)
920
921 conn =
922 conn
923 |> assign(:user, user)
924 |> get("/api/ap/whoami")
925
926 user = User.get_cached_by_id(user.id)
927
928 assert UserView.render("user.json", %{user: user}) == json_response(conn, 200)
929 end
930
931 clear_config([:media_proxy])
932 clear_config([Pleroma.Upload])
933
934 test "uploadMedia", %{conn: conn} do
935 user = insert(:user)
936
937 desc = "Description of the image"
938
939 image = %Plug.Upload{
940 content_type: "image/jpg",
941 path: Path.absname("test/fixtures/image.jpg"),
942 filename: "an_image.jpg"
943 }
944
945 conn =
946 conn
947 |> assign(:user, user)
948 |> post("/api/ap/upload_media", %{"file" => image, "description" => desc})
949
950 assert object = json_response(conn, :created)
951 assert object["name"] == desc
952 assert object["type"] == "Document"
953 assert object["actor"] == user.ap_id
954 end
955 end
956 end