Merge branch 'customizable_auth' into 'develop'
[akkoma] / test / web / activity_pub / activity_pub_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.ActivityPubTest do
6 use Pleroma.DataCase
7 alias Pleroma.Web.ActivityPub.ActivityPub
8 alias Pleroma.Web.ActivityPub.Utils
9 alias Pleroma.Web.CommonAPI
10 alias Pleroma.Activity
11 alias Pleroma.Object
12 alias Pleroma.User
13 alias Pleroma.Instances
14 alias Pleroma.Builders.ActivityBuilder
15
16 import Pleroma.Factory
17 import Tesla.Mock
18 import Mock
19
20 setup do
21 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
22 :ok
23 end
24
25 describe "fetching restricted by visibility" do
26 test "it restricts by the appropriate visibility" do
27 user = insert(:user)
28
29 {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
30
31 {:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
32
33 {:ok, unlisted_activity} =
34 CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"})
35
36 {:ok, private_activity} =
37 CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
38
39 activities =
40 ActivityPub.fetch_activities([], %{:visibility => "direct", "actor_id" => user.ap_id})
41
42 assert activities == [direct_activity]
43
44 activities =
45 ActivityPub.fetch_activities([], %{:visibility => "unlisted", "actor_id" => user.ap_id})
46
47 assert activities == [unlisted_activity]
48
49 activities =
50 ActivityPub.fetch_activities([], %{:visibility => "private", "actor_id" => user.ap_id})
51
52 assert activities == [private_activity]
53
54 activities =
55 ActivityPub.fetch_activities([], %{:visibility => "public", "actor_id" => user.ap_id})
56
57 assert activities == [public_activity]
58 end
59 end
60
61 describe "building a user from his ap id" do
62 test "it returns a user" do
63 user_id = "http://mastodon.example.org/users/admin"
64 {:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
65 assert user.ap_id == user_id
66 assert user.nickname == "admin@mastodon.example.org"
67 assert user.info.source_data
68 assert user.info.ap_enabled
69 assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
70 end
71
72 test "it fetches the appropriate tag-restricted posts" do
73 user = insert(:user)
74
75 {:ok, status_one} = CommonAPI.post(user, %{"status" => ". #test"})
76 {:ok, status_two} = CommonAPI.post(user, %{"status" => ". #essais"})
77 {:ok, status_three} = CommonAPI.post(user, %{"status" => ". #test #reject"})
78
79 fetch_one = ActivityPub.fetch_activities([], %{"tag" => "test"})
80 fetch_two = ActivityPub.fetch_activities([], %{"tag" => ["test", "essais"]})
81
82 fetch_three =
83 ActivityPub.fetch_activities([], %{
84 "tag" => ["test", "essais"],
85 "tag_reject" => ["reject"]
86 })
87
88 fetch_four =
89 ActivityPub.fetch_activities([], %{
90 "tag" => ["test"],
91 "tag_all" => ["test", "reject"]
92 })
93
94 assert fetch_one == [status_one, status_three]
95 assert fetch_two == [status_one, status_two, status_three]
96 assert fetch_three == [status_one, status_two]
97 assert fetch_four == [status_three]
98 end
99 end
100
101 describe "insertion" do
102 test "drops activities beyond a certain limit" do
103 limit = Pleroma.Config.get([:instance, :remote_limit])
104
105 random_text =
106 :crypto.strong_rand_bytes(limit + 1)
107 |> Base.encode64()
108 |> binary_part(0, limit + 1)
109
110 data = %{
111 "ok" => true,
112 "object" => %{
113 "content" => random_text
114 }
115 }
116
117 assert {:error, {:remote_limit_error, _}} = ActivityPub.insert(data)
118 end
119
120 test "doesn't drop activities with content being null" do
121 data = %{
122 "ok" => true,
123 "object" => %{
124 "content" => nil
125 }
126 }
127
128 assert {:ok, _} = ActivityPub.insert(data)
129 end
130
131 test "returns the activity if one with the same id is already in" do
132 activity = insert(:note_activity)
133 {:ok, new_activity} = ActivityPub.insert(activity.data)
134
135 assert activity == new_activity
136 end
137
138 test "inserts a given map into the activity database, giving it an id if it has none." do
139 data = %{
140 "ok" => true
141 }
142
143 {:ok, %Activity{} = activity} = ActivityPub.insert(data)
144 assert activity.data["ok"] == data["ok"]
145 assert is_binary(activity.data["id"])
146
147 given_id = "bla"
148
149 data = %{
150 "ok" => true,
151 "id" => given_id,
152 "context" => "blabla"
153 }
154
155 {:ok, %Activity{} = activity} = ActivityPub.insert(data)
156 assert activity.data["ok"] == data["ok"]
157 assert activity.data["id"] == given_id
158 assert activity.data["context"] == "blabla"
159 assert activity.data["context_id"]
160 end
161
162 test "adds a context when none is there" do
163 data = %{
164 "id" => "some_id",
165 "object" => %{
166 "id" => "object_id"
167 }
168 }
169
170 {:ok, %Activity{} = activity} = ActivityPub.insert(data)
171
172 assert is_binary(activity.data["context"])
173 assert is_binary(activity.data["object"]["context"])
174 assert activity.data["context_id"]
175 assert activity.data["object"]["context_id"]
176 end
177
178 test "adds an id to a given object if it lacks one and is a note and inserts it to the object database" do
179 data = %{
180 "object" => %{
181 "type" => "Note",
182 "ok" => true
183 }
184 }
185
186 {:ok, %Activity{} = activity} = ActivityPub.insert(data)
187 assert is_binary(activity.data["object"]["id"])
188 assert %Object{} = Object.get_by_ap_id(activity.data["object"]["id"])
189 end
190 end
191
192 describe "create activities" do
193 test "removes doubled 'to' recipients" do
194 user = insert(:user)
195
196 {:ok, activity} =
197 ActivityPub.create(%{
198 to: ["user1", "user1", "user2"],
199 actor: user,
200 context: "",
201 object: %{}
202 })
203
204 assert activity.data["to"] == ["user1", "user2"]
205 assert activity.actor == user.ap_id
206 assert activity.recipients == ["user1", "user2", user.ap_id]
207 end
208 end
209
210 describe "fetch activities for recipients" do
211 test "retrieve the activities for certain recipients" do
212 {:ok, activity_one} = ActivityBuilder.insert(%{"to" => ["someone"]})
213 {:ok, activity_two} = ActivityBuilder.insert(%{"to" => ["someone_else"]})
214 {:ok, _activity_three} = ActivityBuilder.insert(%{"to" => ["noone"]})
215
216 activities = ActivityPub.fetch_activities(["someone", "someone_else"])
217 assert length(activities) == 2
218 assert activities == [activity_one, activity_two]
219 end
220 end
221
222 describe "fetch activities in context" do
223 test "retrieves activities that have a given context" do
224 {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
225 {:ok, activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
226 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
227 {:ok, _activity_four} = ActivityBuilder.insert(%{"type" => "Announce", "context" => "2hu"})
228 activity_five = insert(:note_activity)
229 user = insert(:user)
230
231 {:ok, user} = User.block(user, %{ap_id: activity_five.data["actor"]})
232
233 activities = ActivityPub.fetch_activities_for_context("2hu", %{"blocking_user" => user})
234 assert activities == [activity_two, activity]
235 end
236 end
237
238 test "doesn't return blocked activities" do
239 activity_one = insert(:note_activity)
240 activity_two = insert(:note_activity)
241 activity_three = insert(:note_activity)
242 user = insert(:user)
243 booster = insert(:user)
244 {:ok, user} = User.block(user, %{ap_id: activity_one.data["actor"]})
245
246 activities = ActivityPub.fetch_activities([], %{"blocking_user" => user})
247
248 assert Enum.member?(activities, activity_two)
249 assert Enum.member?(activities, activity_three)
250 refute Enum.member?(activities, activity_one)
251
252 {:ok, user} = User.unblock(user, %{ap_id: activity_one.data["actor"]})
253
254 activities = ActivityPub.fetch_activities([], %{"blocking_user" => user})
255
256 assert Enum.member?(activities, activity_two)
257 assert Enum.member?(activities, activity_three)
258 assert Enum.member?(activities, activity_one)
259
260 {:ok, user} = User.block(user, %{ap_id: activity_three.data["actor"]})
261 {:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.repeat(activity_three.id, booster)
262 %Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id)
263 activity_three = Repo.get(Activity, activity_three.id)
264
265 activities = ActivityPub.fetch_activities([], %{"blocking_user" => user})
266
267 assert Enum.member?(activities, activity_two)
268 refute Enum.member?(activities, activity_three)
269 refute Enum.member?(activities, boost_activity)
270 assert Enum.member?(activities, activity_one)
271
272 activities = ActivityPub.fetch_activities([], %{"blocking_user" => nil})
273
274 assert Enum.member?(activities, activity_two)
275 assert Enum.member?(activities, activity_three)
276 assert Enum.member?(activities, boost_activity)
277 assert Enum.member?(activities, activity_one)
278 end
279
280 test "doesn't return muted activities" do
281 activity_one = insert(:note_activity)
282 activity_two = insert(:note_activity)
283 activity_three = insert(:note_activity)
284 user = insert(:user)
285 booster = insert(:user)
286 {:ok, user} = User.mute(user, %User{ap_id: activity_one.data["actor"]})
287
288 activities = ActivityPub.fetch_activities([], %{"muting_user" => user})
289
290 assert Enum.member?(activities, activity_two)
291 assert Enum.member?(activities, activity_three)
292 refute Enum.member?(activities, activity_one)
293
294 # Calling with 'with_muted' will deliver muted activities, too.
295 activities = ActivityPub.fetch_activities([], %{"muting_user" => user, "with_muted" => true})
296
297 assert Enum.member?(activities, activity_two)
298 assert Enum.member?(activities, activity_three)
299 assert Enum.member?(activities, activity_one)
300
301 {:ok, user} = User.unmute(user, %User{ap_id: activity_one.data["actor"]})
302
303 activities = ActivityPub.fetch_activities([], %{"muting_user" => user})
304
305 assert Enum.member?(activities, activity_two)
306 assert Enum.member?(activities, activity_three)
307 assert Enum.member?(activities, activity_one)
308
309 {:ok, user} = User.mute(user, %User{ap_id: activity_three.data["actor"]})
310 {:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.repeat(activity_three.id, booster)
311 %Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id)
312 activity_three = Repo.get(Activity, activity_three.id)
313
314 activities = ActivityPub.fetch_activities([], %{"muting_user" => user})
315
316 assert Enum.member?(activities, activity_two)
317 refute Enum.member?(activities, activity_three)
318 refute Enum.member?(activities, boost_activity)
319 assert Enum.member?(activities, activity_one)
320
321 activities = ActivityPub.fetch_activities([], %{"muting_user" => nil})
322
323 assert Enum.member?(activities, activity_two)
324 assert Enum.member?(activities, activity_three)
325 assert Enum.member?(activities, boost_activity)
326 assert Enum.member?(activities, activity_one)
327 end
328
329 test "excludes reblogs on request" do
330 user = insert(:user)
331 {:ok, expected_activity} = ActivityBuilder.insert(%{"type" => "Create"}, %{:user => user})
332 {:ok, _} = ActivityBuilder.insert(%{"type" => "Announce"}, %{:user => user})
333
334 [activity] = ActivityPub.fetch_user_activities(user, nil, %{"exclude_reblogs" => "true"})
335
336 assert activity == expected_activity
337 end
338
339 describe "public fetch activities" do
340 test "doesn't retrieve unlisted activities" do
341 user = insert(:user)
342
343 {:ok, _unlisted_activity} =
344 CommonAPI.post(user, %{"status" => "yeah", "visibility" => "unlisted"})
345
346 {:ok, listed_activity} = CommonAPI.post(user, %{"status" => "yeah"})
347
348 [activity] = ActivityPub.fetch_public_activities()
349
350 assert activity == listed_activity
351 end
352
353 test "retrieves public activities" do
354 _activities = ActivityPub.fetch_public_activities()
355
356 %{public: public} = ActivityBuilder.public_and_non_public()
357
358 activities = ActivityPub.fetch_public_activities()
359 assert length(activities) == 1
360 assert Enum.at(activities, 0) == public
361 end
362
363 test "retrieves a maximum of 20 activities" do
364 activities = ActivityBuilder.insert_list(30)
365 last_expected = List.last(activities)
366
367 activities = ActivityPub.fetch_public_activities()
368 last = List.last(activities)
369
370 assert length(activities) == 20
371 assert last == last_expected
372 end
373
374 test "retrieves ids starting from a since_id" do
375 activities = ActivityBuilder.insert_list(30)
376 later_activities = ActivityBuilder.insert_list(10)
377 since_id = List.last(activities).id
378 last_expected = List.last(later_activities)
379
380 activities = ActivityPub.fetch_public_activities(%{"since_id" => since_id})
381 last = List.last(activities)
382
383 assert length(activities) == 10
384 assert last == last_expected
385 end
386
387 test "retrieves ids up to max_id" do
388 _first_activities = ActivityBuilder.insert_list(10)
389 activities = ActivityBuilder.insert_list(20)
390 later_activities = ActivityBuilder.insert_list(10)
391 max_id = List.first(later_activities).id
392 last_expected = List.last(activities)
393
394 activities = ActivityPub.fetch_public_activities(%{"max_id" => max_id})
395 last = List.last(activities)
396
397 assert length(activities) == 20
398 assert last == last_expected
399 end
400 end
401
402 describe "like an object" do
403 test "adds a like activity to the db" do
404 note_activity = insert(:note_activity)
405 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
406 user = insert(:user)
407 user_two = insert(:user)
408
409 {:ok, like_activity, object} = ActivityPub.like(user, object)
410
411 assert like_activity.data["actor"] == user.ap_id
412 assert like_activity.data["type"] == "Like"
413 assert like_activity.data["object"] == object.data["id"]
414 assert like_activity.data["to"] == [User.ap_followers(user), note_activity.data["actor"]]
415 assert like_activity.data["context"] == object.data["context"]
416 assert object.data["like_count"] == 1
417 assert object.data["likes"] == [user.ap_id]
418
419 # Just return the original activity if the user already liked it.
420 {:ok, same_like_activity, object} = ActivityPub.like(user, object)
421
422 assert like_activity == same_like_activity
423 assert object.data["likes"] == [user.ap_id]
424
425 [note_activity] = Activity.get_all_create_by_object_ap_id(object.data["id"])
426 assert note_activity.data["object"]["like_count"] == 1
427
428 {:ok, _like_activity, object} = ActivityPub.like(user_two, object)
429 assert object.data["like_count"] == 2
430 end
431 end
432
433 describe "unliking" do
434 test "unliking a previously liked object" do
435 note_activity = insert(:note_activity)
436 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
437 user = insert(:user)
438
439 # Unliking something that hasn't been liked does nothing
440 {:ok, object} = ActivityPub.unlike(user, object)
441 assert object.data["like_count"] == 0
442
443 {:ok, like_activity, object} = ActivityPub.like(user, object)
444 assert object.data["like_count"] == 1
445
446 {:ok, _, _, object} = ActivityPub.unlike(user, object)
447 assert object.data["like_count"] == 0
448
449 assert Repo.get(Activity, like_activity.id) == nil
450 end
451 end
452
453 describe "announcing an object" do
454 test "adds an announce activity to the db" do
455 note_activity = insert(:note_activity)
456 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
457 user = insert(:user)
458
459 {:ok, announce_activity, object} = ActivityPub.announce(user, object)
460 assert object.data["announcement_count"] == 1
461 assert object.data["announcements"] == [user.ap_id]
462
463 assert announce_activity.data["to"] == [
464 User.ap_followers(user),
465 note_activity.data["actor"]
466 ]
467
468 assert announce_activity.data["object"] == object.data["id"]
469 assert announce_activity.data["actor"] == user.ap_id
470 assert announce_activity.data["context"] == object.data["context"]
471 end
472 end
473
474 describe "unannouncing an object" do
475 test "unannouncing a previously announced object" do
476 note_activity = insert(:note_activity)
477 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
478 user = insert(:user)
479
480 # Unannouncing an object that is not announced does nothing
481 # {:ok, object} = ActivityPub.unannounce(user, object)
482 # assert object.data["announcement_count"] == 0
483
484 {:ok, announce_activity, object} = ActivityPub.announce(user, object)
485 assert object.data["announcement_count"] == 1
486
487 {:ok, unannounce_activity, object} = ActivityPub.unannounce(user, object)
488 assert object.data["announcement_count"] == 0
489
490 assert unannounce_activity.data["to"] == [
491 User.ap_followers(user),
492 announce_activity.data["actor"]
493 ]
494
495 assert unannounce_activity.data["type"] == "Undo"
496 assert unannounce_activity.data["object"] == announce_activity.data
497 assert unannounce_activity.data["actor"] == user.ap_id
498 assert unannounce_activity.data["context"] == announce_activity.data["context"]
499
500 assert Repo.get(Activity, announce_activity.id) == nil
501 end
502 end
503
504 describe "uploading files" do
505 test "copies the file to the configured folder" do
506 file = %Plug.Upload{
507 content_type: "image/jpg",
508 path: Path.absname("test/fixtures/image.jpg"),
509 filename: "an_image.jpg"
510 }
511
512 {:ok, %Object{} = object} = ActivityPub.upload(file)
513 assert object.data["name"] == "an_image.jpg"
514 end
515
516 test "works with base64 encoded images" do
517 file = %{
518 "img" => data_uri()
519 }
520
521 {:ok, %Object{}} = ActivityPub.upload(file)
522 end
523 end
524
525 describe "fetch the latest Follow" do
526 test "fetches the latest Follow activity" do
527 %Activity{data: %{"type" => "Follow"}} = activity = insert(:follow_activity)
528 follower = Repo.get_by(User, ap_id: activity.data["actor"])
529 followed = Repo.get_by(User, ap_id: activity.data["object"])
530
531 assert activity == Utils.fetch_latest_follow(follower, followed)
532 end
533 end
534
535 describe "fetching an object" do
536 test "it fetches an object" do
537 {:ok, object} =
538 ActivityPub.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
539
540 assert activity = Activity.get_create_by_object_ap_id(object.data["id"])
541 assert activity.data["id"]
542
543 {:ok, object_again} =
544 ActivityPub.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
545
546 assert [attachment] = object.data["attachment"]
547 assert is_list(attachment["url"])
548
549 assert object == object_again
550 end
551
552 test "it works with objects only available via Ostatus" do
553 {:ok, object} = ActivityPub.fetch_object_from_id("https://shitposter.club/notice/2827873")
554 assert activity = Activity.get_create_by_object_ap_id(object.data["id"])
555 assert activity.data["id"]
556
557 {:ok, object_again} =
558 ActivityPub.fetch_object_from_id("https://shitposter.club/notice/2827873")
559
560 assert object == object_again
561 end
562
563 test "it correctly stitches up conversations between ostatus and ap" do
564 last = "https://mstdn.io/users/mayuutann/statuses/99568293732299394"
565 {:ok, object} = ActivityPub.fetch_object_from_id(last)
566
567 object = Object.get_by_ap_id(object.data["inReplyTo"])
568 assert object
569 end
570 end
571
572 describe "following / unfollowing" do
573 test "creates a follow activity" do
574 follower = insert(:user)
575 followed = insert(:user)
576
577 {:ok, activity} = ActivityPub.follow(follower, followed)
578 assert activity.data["type"] == "Follow"
579 assert activity.data["actor"] == follower.ap_id
580 assert activity.data["object"] == followed.ap_id
581 end
582
583 test "creates an undo activity for the last follow" do
584 follower = insert(:user)
585 followed = insert(:user)
586
587 {:ok, follow_activity} = ActivityPub.follow(follower, followed)
588 {:ok, activity} = ActivityPub.unfollow(follower, followed)
589
590 assert activity.data["type"] == "Undo"
591 assert activity.data["actor"] == follower.ap_id
592
593 assert is_map(activity.data["object"])
594 assert activity.data["object"]["type"] == "Follow"
595 assert activity.data["object"]["object"] == followed.ap_id
596 assert activity.data["object"]["id"] == follow_activity.data["id"]
597 end
598 end
599
600 describe "blocking / unblocking" do
601 test "creates a block activity" do
602 blocker = insert(:user)
603 blocked = insert(:user)
604
605 {:ok, activity} = ActivityPub.block(blocker, blocked)
606
607 assert activity.data["type"] == "Block"
608 assert activity.data["actor"] == blocker.ap_id
609 assert activity.data["object"] == blocked.ap_id
610 end
611
612 test "creates an undo activity for the last block" do
613 blocker = insert(:user)
614 blocked = insert(:user)
615
616 {:ok, block_activity} = ActivityPub.block(blocker, blocked)
617 {:ok, activity} = ActivityPub.unblock(blocker, blocked)
618
619 assert activity.data["type"] == "Undo"
620 assert activity.data["actor"] == blocker.ap_id
621
622 assert is_map(activity.data["object"])
623 assert activity.data["object"]["type"] == "Block"
624 assert activity.data["object"]["object"] == blocked.ap_id
625 assert activity.data["object"]["id"] == block_activity.data["id"]
626 end
627 end
628
629 describe "deletion" do
630 test "it creates a delete activity and deletes the original object" do
631 note = insert(:note_activity)
632 object = Object.get_by_ap_id(note.data["object"]["id"])
633 {:ok, delete} = ActivityPub.delete(object)
634
635 assert delete.data["type"] == "Delete"
636 assert delete.data["actor"] == note.data["actor"]
637 assert delete.data["object"] == note.data["object"]["id"]
638
639 assert Repo.get(Activity, delete.id) != nil
640
641 assert Repo.get(Object, object.id).data["type"] == "Tombstone"
642 end
643 end
644
645 describe "timeline post-processing" do
646 test "it filters broken threads" do
647 user1 = insert(:user)
648 user2 = insert(:user)
649 user3 = insert(:user)
650
651 {:ok, user1} = User.follow(user1, user3)
652 assert User.following?(user1, user3)
653
654 {:ok, user2} = User.follow(user2, user3)
655 assert User.following?(user2, user3)
656
657 {:ok, user3} = User.follow(user3, user2)
658 assert User.following?(user3, user2)
659
660 {:ok, public_activity} = CommonAPI.post(user3, %{"status" => "hi 1"})
661
662 {:ok, private_activity_1} =
663 CommonAPI.post(user3, %{"status" => "hi 2", "visibility" => "private"})
664
665 {:ok, private_activity_2} =
666 CommonAPI.post(user2, %{
667 "status" => "hi 3",
668 "visibility" => "private",
669 "in_reply_to_status_id" => private_activity_1.id
670 })
671
672 {:ok, private_activity_3} =
673 CommonAPI.post(user3, %{
674 "status" => "hi 4",
675 "visibility" => "private",
676 "in_reply_to_status_id" => private_activity_2.id
677 })
678
679 activities = ActivityPub.fetch_activities([user1.ap_id | user1.following])
680
681 assert [public_activity, private_activity_1, private_activity_3] == activities
682 assert length(activities) == 3
683
684 activities = ActivityPub.contain_timeline(activities, user1)
685
686 assert [public_activity, private_activity_1] == activities
687 assert length(activities) == 2
688 end
689 end
690
691 test "it can fetch plume articles" do
692 {:ok, object} =
693 ActivityPub.fetch_object_from_id(
694 "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/"
695 )
696
697 assert object
698 end
699
700 describe "update" do
701 test "it creates an update activity with the new user data" do
702 user = insert(:user)
703 {:ok, user} = Pleroma.Web.WebFinger.ensure_keys_present(user)
704 user_data = Pleroma.Web.ActivityPub.UserView.render("user.json", %{user: user})
705
706 {:ok, update} =
707 ActivityPub.update(%{
708 actor: user_data["id"],
709 to: [user.follower_address],
710 cc: [],
711 object: user_data
712 })
713
714 assert update.data["actor"] == user.ap_id
715 assert update.data["to"] == [user.follower_address]
716 assert update.data["object"]["id"] == user_data["id"]
717 assert update.data["object"]["type"] == user_data["type"]
718 end
719 end
720
721 test "it can fetch peertube videos" do
722 {:ok, object} =
723 ActivityPub.fetch_object_from_id(
724 "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
725 )
726
727 assert object
728 end
729
730 test "returned pinned statuses" do
731 Pleroma.Config.put([:instance, :max_pinned_statuses], 3)
732 user = insert(:user)
733
734 {:ok, activity_one} = CommonAPI.post(user, %{"status" => "HI!!!"})
735 {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
736 {:ok, activity_three} = CommonAPI.post(user, %{"status" => "HI!!!"})
737
738 CommonAPI.pin(activity_one.id, user)
739 user = refresh_record(user)
740
741 CommonAPI.pin(activity_two.id, user)
742 user = refresh_record(user)
743
744 CommonAPI.pin(activity_three.id, user)
745 user = refresh_record(user)
746
747 activities = ActivityPub.fetch_user_activities(user, nil, %{"pinned" => "true"})
748
749 assert 3 = length(activities)
750 end
751
752 test "it can create a Flag activity" do
753 reporter = insert(:user)
754 target_account = insert(:user)
755 {:ok, activity} = CommonAPI.post(target_account, %{"status" => "foobar"})
756 context = Utils.generate_context_id()
757 content = "foobar"
758
759 reporter_ap_id = reporter.ap_id
760 target_ap_id = target_account.ap_id
761 activity_ap_id = activity.data["id"]
762
763 assert {:ok, activity} =
764 ActivityPub.flag(%{
765 actor: reporter,
766 context: context,
767 account: target_account,
768 statuses: [activity],
769 content: content
770 })
771
772 assert %Activity{
773 actor: ^reporter_ap_id,
774 data: %{
775 "type" => "Flag",
776 "content" => ^content,
777 "context" => ^context,
778 "object" => [^target_ap_id, ^activity_ap_id]
779 }
780 } = activity
781 end
782
783 describe "publish_one/1" do
784 test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is not specified",
785 Instances,
786 [:passthrough],
787 [] do
788 actor = insert(:user)
789 inbox = "http://200.site/users/nick1/inbox"
790
791 assert {:ok, _} = ActivityPub.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
792
793 assert called(Instances.set_reachable(inbox))
794 end
795
796 test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is set",
797 Instances,
798 [:passthrough],
799 [] do
800 actor = insert(:user)
801 inbox = "http://200.site/users/nick1/inbox"
802
803 assert {:ok, _} =
804 ActivityPub.publish_one(%{
805 inbox: inbox,
806 json: "{}",
807 actor: actor,
808 id: 1,
809 unreachable_since: NaiveDateTime.utc_now()
810 })
811
812 assert called(Instances.set_reachable(inbox))
813 end
814
815 test_with_mock "does NOT call `Instances.set_reachable` on successful federation if `unreachable_since` is nil",
816 Instances,
817 [:passthrough],
818 [] do
819 actor = insert(:user)
820 inbox = "http://200.site/users/nick1/inbox"
821
822 assert {:ok, _} =
823 ActivityPub.publish_one(%{
824 inbox: inbox,
825 json: "{}",
826 actor: actor,
827 id: 1,
828 unreachable_since: nil
829 })
830
831 refute called(Instances.set_reachable(inbox))
832 end
833
834 test_with_mock "calls `Instances.set_unreachable` on target inbox on non-2xx HTTP response code",
835 Instances,
836 [:passthrough],
837 [] do
838 actor = insert(:user)
839 inbox = "http://404.site/users/nick1/inbox"
840
841 assert {:error, _} =
842 ActivityPub.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
843
844 assert called(Instances.set_unreachable(inbox))
845 end
846
847 test_with_mock "it calls `Instances.set_unreachable` on target inbox on request error of any kind",
848 Instances,
849 [:passthrough],
850 [] do
851 actor = insert(:user)
852 inbox = "http://connrefused.site/users/nick1/inbox"
853
854 assert {:error, _} =
855 ActivityPub.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
856
857 assert called(Instances.set_unreachable(inbox))
858 end
859
860 test_with_mock "does NOT call `Instances.set_unreachable` if target is reachable",
861 Instances,
862 [:passthrough],
863 [] do
864 actor = insert(:user)
865 inbox = "http://200.site/users/nick1/inbox"
866
867 assert {:ok, _} = ActivityPub.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
868
869 refute called(Instances.set_unreachable(inbox))
870 end
871
872 test_with_mock "does NOT call `Instances.set_unreachable` if target instance has non-nil `unreachable_since`",
873 Instances,
874 [:passthrough],
875 [] do
876 actor = insert(:user)
877 inbox = "http://connrefused.site/users/nick1/inbox"
878
879 assert {:error, _} =
880 ActivityPub.publish_one(%{
881 inbox: inbox,
882 json: "{}",
883 actor: actor,
884 id: 1,
885 unreachable_since: NaiveDateTime.utc_now()
886 })
887
888 refute called(Instances.set_unreachable(inbox))
889 end
890 end
891
892 def data_uri do
893 File.read!("test/fixtures/avatar_data_uri")
894 end
895 end