Fix MastoAPI.AuthControllerTest, json_response(:no_content) --> empty_json_response()
[akkoma] / test / web / activity_pub / activity_pub_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 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 use Oban.Testing, repo: Pleroma.Repo
8
9 alias Pleroma.Activity
10 alias Pleroma.Builders.ActivityBuilder
11 alias Pleroma.Config
12 alias Pleroma.Notification
13 alias Pleroma.Object
14 alias Pleroma.User
15 alias Pleroma.Web.ActivityPub.ActivityPub
16 alias Pleroma.Web.ActivityPub.Utils
17 alias Pleroma.Web.AdminAPI.AccountView
18 alias Pleroma.Web.CommonAPI
19
20 import ExUnit.CaptureLog
21 import Mock
22 import Pleroma.Factory
23 import Tesla.Mock
24
25 setup do
26 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
27 :ok
28 end
29
30 setup do: clear_config([:instance, :federating])
31
32 describe "streaming out participations" do
33 test "it streams them out" do
34 user = insert(:user)
35 {:ok, activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
36
37 {:ok, conversation} = Pleroma.Conversation.create_or_bump_for(activity)
38
39 participations =
40 conversation.participations
41 |> Repo.preload(:user)
42
43 with_mock Pleroma.Web.Streamer,
44 stream: fn _, _ -> nil end do
45 ActivityPub.stream_out_participations(conversation.participations)
46
47 assert called(Pleroma.Web.Streamer.stream("participation", participations))
48 end
49 end
50
51 test "streams them out on activity creation" do
52 user_one = insert(:user)
53 user_two = insert(:user)
54
55 with_mock Pleroma.Web.Streamer,
56 stream: fn _, _ -> nil end do
57 {:ok, activity} =
58 CommonAPI.post(user_one, %{
59 status: "@#{user_two.nickname}",
60 visibility: "direct"
61 })
62
63 conversation =
64 activity.data["context"]
65 |> Pleroma.Conversation.get_for_ap_id()
66 |> Repo.preload(participations: :user)
67
68 assert called(Pleroma.Web.Streamer.stream("participation", conversation.participations))
69 end
70 end
71 end
72
73 describe "fetching restricted by visibility" do
74 test "it restricts by the appropriate visibility" do
75 user = insert(:user)
76
77 {:ok, public_activity} = CommonAPI.post(user, %{status: ".", visibility: "public"})
78
79 {:ok, direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
80
81 {:ok, unlisted_activity} = CommonAPI.post(user, %{status: ".", visibility: "unlisted"})
82
83 {:ok, private_activity} = CommonAPI.post(user, %{status: ".", visibility: "private"})
84
85 activities = ActivityPub.fetch_activities([], %{visibility: "direct", actor_id: user.ap_id})
86
87 assert activities == [direct_activity]
88
89 activities =
90 ActivityPub.fetch_activities([], %{visibility: "unlisted", actor_id: user.ap_id})
91
92 assert activities == [unlisted_activity]
93
94 activities =
95 ActivityPub.fetch_activities([], %{visibility: "private", actor_id: user.ap_id})
96
97 assert activities == [private_activity]
98
99 activities = ActivityPub.fetch_activities([], %{visibility: "public", actor_id: user.ap_id})
100
101 assert activities == [public_activity]
102
103 activities =
104 ActivityPub.fetch_activities([], %{
105 visibility: ~w[private public],
106 actor_id: user.ap_id
107 })
108
109 assert activities == [public_activity, private_activity]
110 end
111 end
112
113 describe "fetching excluded by visibility" do
114 test "it excludes by the appropriate visibility" do
115 user = insert(:user)
116
117 {:ok, public_activity} = CommonAPI.post(user, %{status: ".", visibility: "public"})
118
119 {:ok, direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
120
121 {:ok, unlisted_activity} = CommonAPI.post(user, %{status: ".", visibility: "unlisted"})
122
123 {:ok, private_activity} = CommonAPI.post(user, %{status: ".", visibility: "private"})
124
125 activities =
126 ActivityPub.fetch_activities([], %{
127 exclude_visibilities: "direct",
128 actor_id: user.ap_id
129 })
130
131 assert public_activity in activities
132 assert unlisted_activity in activities
133 assert private_activity in activities
134 refute direct_activity in activities
135
136 activities =
137 ActivityPub.fetch_activities([], %{
138 exclude_visibilities: "unlisted",
139 actor_id: user.ap_id
140 })
141
142 assert public_activity in activities
143 refute unlisted_activity in activities
144 assert private_activity in activities
145 assert direct_activity in activities
146
147 activities =
148 ActivityPub.fetch_activities([], %{
149 exclude_visibilities: "private",
150 actor_id: user.ap_id
151 })
152
153 assert public_activity in activities
154 assert unlisted_activity in activities
155 refute private_activity in activities
156 assert direct_activity in activities
157
158 activities =
159 ActivityPub.fetch_activities([], %{
160 exclude_visibilities: "public",
161 actor_id: user.ap_id
162 })
163
164 refute public_activity in activities
165 assert unlisted_activity in activities
166 assert private_activity in activities
167 assert direct_activity in activities
168 end
169 end
170
171 describe "building a user from his ap id" do
172 test "it returns a user" do
173 user_id = "http://mastodon.example.org/users/admin"
174 {:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
175 assert user.ap_id == user_id
176 assert user.nickname == "admin@mastodon.example.org"
177 assert user.ap_enabled
178 assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
179 end
180
181 test "it returns a user that is invisible" do
182 user_id = "http://mastodon.example.org/users/relay"
183 {:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
184 assert User.invisible?(user)
185 end
186
187 test "it returns a user that accepts chat messages" do
188 user_id = "http://mastodon.example.org/users/admin"
189 {:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
190
191 assert user.accepts_chat_messages
192 end
193 end
194
195 test "it fetches the appropriate tag-restricted posts" do
196 user = insert(:user)
197
198 {:ok, status_one} = CommonAPI.post(user, %{status: ". #test"})
199 {:ok, status_two} = CommonAPI.post(user, %{status: ". #essais"})
200 {:ok, status_three} = CommonAPI.post(user, %{status: ". #test #reject"})
201
202 fetch_one = ActivityPub.fetch_activities([], %{type: "Create", tag: "test"})
203
204 fetch_two = ActivityPub.fetch_activities([], %{type: "Create", tag: ["test", "essais"]})
205
206 fetch_three =
207 ActivityPub.fetch_activities([], %{
208 type: "Create",
209 tag: ["test", "essais"],
210 tag_reject: ["reject"]
211 })
212
213 fetch_four =
214 ActivityPub.fetch_activities([], %{
215 type: "Create",
216 tag: ["test"],
217 tag_all: ["test", "reject"]
218 })
219
220 assert fetch_one == [status_one, status_three]
221 assert fetch_two == [status_one, status_two, status_three]
222 assert fetch_three == [status_one, status_two]
223 assert fetch_four == [status_three]
224 end
225
226 describe "insertion" do
227 test "drops activities beyond a certain limit" do
228 limit = Config.get([:instance, :remote_limit])
229
230 random_text =
231 :crypto.strong_rand_bytes(limit + 1)
232 |> Base.encode64()
233 |> binary_part(0, limit + 1)
234
235 data = %{
236 "ok" => true,
237 "object" => %{
238 "content" => random_text
239 }
240 }
241
242 assert {:error, {:remote_limit_error, _}} = ActivityPub.insert(data)
243 end
244
245 test "doesn't drop activities with content being null" do
246 user = insert(:user)
247
248 data = %{
249 "actor" => user.ap_id,
250 "to" => [],
251 "object" => %{
252 "actor" => user.ap_id,
253 "to" => [],
254 "type" => "Note",
255 "content" => nil
256 }
257 }
258
259 assert {:ok, _} = ActivityPub.insert(data)
260 end
261
262 test "returns the activity if one with the same id is already in" do
263 activity = insert(:note_activity)
264 {:ok, new_activity} = ActivityPub.insert(activity.data)
265
266 assert activity.id == new_activity.id
267 end
268
269 test "inserts a given map into the activity database, giving it an id if it has none." do
270 user = insert(:user)
271
272 data = %{
273 "actor" => user.ap_id,
274 "to" => [],
275 "object" => %{
276 "actor" => user.ap_id,
277 "to" => [],
278 "type" => "Note",
279 "content" => "hey"
280 }
281 }
282
283 {:ok, %Activity{} = activity} = ActivityPub.insert(data)
284 assert activity.data["ok"] == data["ok"]
285 assert is_binary(activity.data["id"])
286
287 given_id = "bla"
288
289 data = %{
290 "id" => given_id,
291 "actor" => user.ap_id,
292 "to" => [],
293 "context" => "blabla",
294 "object" => %{
295 "actor" => user.ap_id,
296 "to" => [],
297 "type" => "Note",
298 "content" => "hey"
299 }
300 }
301
302 {:ok, %Activity{} = activity} = ActivityPub.insert(data)
303 assert activity.data["ok"] == data["ok"]
304 assert activity.data["id"] == given_id
305 assert activity.data["context"] == "blabla"
306 assert activity.data["context_id"]
307 end
308
309 test "adds a context when none is there" do
310 user = insert(:user)
311
312 data = %{
313 "actor" => user.ap_id,
314 "to" => [],
315 "object" => %{
316 "actor" => user.ap_id,
317 "to" => [],
318 "type" => "Note",
319 "content" => "hey"
320 }
321 }
322
323 {:ok, %Activity{} = activity} = ActivityPub.insert(data)
324 object = Pleroma.Object.normalize(activity)
325
326 assert is_binary(activity.data["context"])
327 assert is_binary(object.data["context"])
328 assert activity.data["context_id"]
329 assert object.data["context_id"]
330 end
331
332 test "adds an id to a given object if it lacks one and is a note and inserts it to the object database" do
333 user = insert(:user)
334
335 data = %{
336 "actor" => user.ap_id,
337 "to" => [],
338 "object" => %{
339 "actor" => user.ap_id,
340 "to" => [],
341 "type" => "Note",
342 "content" => "hey"
343 }
344 }
345
346 {:ok, %Activity{} = activity} = ActivityPub.insert(data)
347 assert object = Object.normalize(activity)
348 assert is_binary(object.data["id"])
349 end
350 end
351
352 describe "listen activities" do
353 test "does not increase user note count" do
354 user = insert(:user)
355
356 {:ok, activity} =
357 ActivityPub.listen(%{
358 to: ["https://www.w3.org/ns/activitystreams#Public"],
359 actor: user,
360 context: "",
361 object: %{
362 "actor" => user.ap_id,
363 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
364 "artist" => "lain",
365 "title" => "lain radio episode 1",
366 "length" => 180_000,
367 "type" => "Audio"
368 }
369 })
370
371 assert activity.actor == user.ap_id
372
373 user = User.get_cached_by_id(user.id)
374 assert user.note_count == 0
375 end
376
377 test "can be fetched into a timeline" do
378 _listen_activity_1 = insert(:listen)
379 _listen_activity_2 = insert(:listen)
380 _listen_activity_3 = insert(:listen)
381
382 timeline = ActivityPub.fetch_activities([], %{type: ["Listen"]})
383
384 assert length(timeline) == 3
385 end
386 end
387
388 describe "create activities" do
389 test "it reverts create" do
390 user = insert(:user)
391
392 with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
393 assert {:error, :reverted} =
394 ActivityPub.create(%{
395 to: ["user1", "user2"],
396 actor: user,
397 context: "",
398 object: %{
399 "to" => ["user1", "user2"],
400 "type" => "Note",
401 "content" => "testing"
402 }
403 })
404 end
405
406 assert Repo.aggregate(Activity, :count, :id) == 0
407 assert Repo.aggregate(Object, :count, :id) == 0
408 end
409
410 test "removes doubled 'to' recipients" do
411 user = insert(:user)
412
413 {:ok, activity} =
414 ActivityPub.create(%{
415 to: ["user1", "user1", "user2"],
416 actor: user,
417 context: "",
418 object: %{
419 "to" => ["user1", "user1", "user2"],
420 "type" => "Note",
421 "content" => "testing"
422 }
423 })
424
425 assert activity.data["to"] == ["user1", "user2"]
426 assert activity.actor == user.ap_id
427 assert activity.recipients == ["user1", "user2", user.ap_id]
428 end
429
430 test "increases user note count only for public activities" do
431 user = insert(:user)
432
433 {:ok, _} =
434 CommonAPI.post(User.get_cached_by_id(user.id), %{
435 status: "1",
436 visibility: "public"
437 })
438
439 {:ok, _} =
440 CommonAPI.post(User.get_cached_by_id(user.id), %{
441 status: "2",
442 visibility: "unlisted"
443 })
444
445 {:ok, _} =
446 CommonAPI.post(User.get_cached_by_id(user.id), %{
447 status: "2",
448 visibility: "private"
449 })
450
451 {:ok, _} =
452 CommonAPI.post(User.get_cached_by_id(user.id), %{
453 status: "3",
454 visibility: "direct"
455 })
456
457 user = User.get_cached_by_id(user.id)
458 assert user.note_count == 2
459 end
460
461 test "increases replies count" do
462 user = insert(:user)
463 user2 = insert(:user)
464
465 {:ok, activity} = CommonAPI.post(user, %{status: "1", visibility: "public"})
466 ap_id = activity.data["id"]
467 reply_data = %{status: "1", in_reply_to_status_id: activity.id}
468
469 # public
470 {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "public"))
471 assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
472 assert object.data["repliesCount"] == 1
473
474 # unlisted
475 {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "unlisted"))
476 assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
477 assert object.data["repliesCount"] == 2
478
479 # private
480 {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "private"))
481 assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
482 assert object.data["repliesCount"] == 2
483
484 # direct
485 {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "direct"))
486 assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
487 assert object.data["repliesCount"] == 2
488 end
489 end
490
491 describe "fetch activities for recipients" do
492 test "retrieve the activities for certain recipients" do
493 {:ok, activity_one} = ActivityBuilder.insert(%{"to" => ["someone"]})
494 {:ok, activity_two} = ActivityBuilder.insert(%{"to" => ["someone_else"]})
495 {:ok, _activity_three} = ActivityBuilder.insert(%{"to" => ["noone"]})
496
497 activities = ActivityPub.fetch_activities(["someone", "someone_else"])
498 assert length(activities) == 2
499 assert activities == [activity_one, activity_two]
500 end
501 end
502
503 describe "fetch activities in context" do
504 test "retrieves activities that have a given context" do
505 {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
506 {:ok, activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
507 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
508 {:ok, _activity_four} = ActivityBuilder.insert(%{"type" => "Announce", "context" => "2hu"})
509 activity_five = insert(:note_activity)
510 user = insert(:user)
511
512 {:ok, _user_relationship} = User.block(user, %{ap_id: activity_five.data["actor"]})
513
514 activities = ActivityPub.fetch_activities_for_context("2hu", %{blocking_user: user})
515 assert activities == [activity_two, activity]
516 end
517
518 test "doesn't return activities with filtered words" do
519 user = insert(:user)
520 user_two = insert(:user)
521 insert(:filter, user: user, phrase: "test", hide: true)
522
523 {:ok, %{id: id1, data: %{"context" => context}}} = CommonAPI.post(user, %{status: "1"})
524
525 {:ok, %{id: id2}} = CommonAPI.post(user_two, %{status: "2", in_reply_to_status_id: id1})
526
527 {:ok, %{id: id3} = user_activity} =
528 CommonAPI.post(user, %{status: "3 test?", in_reply_to_status_id: id2})
529
530 {:ok, %{id: id4} = filtered_activity} =
531 CommonAPI.post(user_two, %{status: "4 test!", in_reply_to_status_id: id3})
532
533 {:ok, _} = CommonAPI.post(user, %{status: "5", in_reply_to_status_id: id4})
534
535 activities =
536 context
537 |> ActivityPub.fetch_activities_for_context(%{user: user})
538 |> Enum.map(& &1.id)
539
540 assert length(activities) == 4
541 assert user_activity.id in activities
542 refute filtered_activity.id in activities
543 end
544 end
545
546 test "doesn't return blocked activities" do
547 activity_one = insert(:note_activity)
548 activity_two = insert(:note_activity)
549 activity_three = insert(:note_activity)
550 user = insert(:user)
551 booster = insert(:user)
552 {:ok, _user_relationship} = User.block(user, %{ap_id: activity_one.data["actor"]})
553
554 activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
555
556 assert Enum.member?(activities, activity_two)
557 assert Enum.member?(activities, activity_three)
558 refute Enum.member?(activities, activity_one)
559
560 {:ok, _user_block} = User.unblock(user, %{ap_id: activity_one.data["actor"]})
561
562 activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
563
564 assert Enum.member?(activities, activity_two)
565 assert Enum.member?(activities, activity_three)
566 assert Enum.member?(activities, activity_one)
567
568 {:ok, _user_relationship} = User.block(user, %{ap_id: activity_three.data["actor"]})
569 {:ok, %{data: %{"object" => id}}} = CommonAPI.repeat(activity_three.id, booster)
570 %Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id)
571 activity_three = Activity.get_by_id(activity_three.id)
572
573 activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
574
575 assert Enum.member?(activities, activity_two)
576 refute Enum.member?(activities, activity_three)
577 refute Enum.member?(activities, boost_activity)
578 assert Enum.member?(activities, activity_one)
579
580 activities = ActivityPub.fetch_activities([], %{blocking_user: nil, skip_preload: true})
581
582 assert Enum.member?(activities, activity_two)
583 assert Enum.member?(activities, activity_three)
584 assert Enum.member?(activities, boost_activity)
585 assert Enum.member?(activities, activity_one)
586 end
587
588 test "doesn't return transitive interactions concerning blocked users" do
589 blocker = insert(:user)
590 blockee = insert(:user)
591 friend = insert(:user)
592
593 {:ok, _user_relationship} = User.block(blocker, blockee)
594
595 {:ok, activity_one} = CommonAPI.post(friend, %{status: "hey!"})
596
597 {:ok, activity_two} = CommonAPI.post(friend, %{status: "hey! @#{blockee.nickname}"})
598
599 {:ok, activity_three} = CommonAPI.post(blockee, %{status: "hey! @#{friend.nickname}"})
600
601 {:ok, activity_four} = CommonAPI.post(blockee, %{status: "hey! @#{blocker.nickname}"})
602
603 activities = ActivityPub.fetch_activities([], %{blocking_user: blocker})
604
605 assert Enum.member?(activities, activity_one)
606 refute Enum.member?(activities, activity_two)
607 refute Enum.member?(activities, activity_three)
608 refute Enum.member?(activities, activity_four)
609 end
610
611 test "doesn't return announce activities with blocked users in 'to'" do
612 blocker = insert(:user)
613 blockee = insert(:user)
614 friend = insert(:user)
615
616 {:ok, _user_relationship} = User.block(blocker, blockee)
617
618 {:ok, activity_one} = CommonAPI.post(friend, %{status: "hey!"})
619
620 {:ok, activity_two} = CommonAPI.post(blockee, %{status: "hey! @#{friend.nickname}"})
621
622 {:ok, activity_three} = CommonAPI.repeat(activity_two.id, friend)
623
624 activities =
625 ActivityPub.fetch_activities([], %{blocking_user: blocker})
626 |> Enum.map(fn act -> act.id end)
627
628 assert Enum.member?(activities, activity_one.id)
629 refute Enum.member?(activities, activity_two.id)
630 refute Enum.member?(activities, activity_three.id)
631 end
632
633 test "doesn't return announce activities with blocked users in 'cc'" do
634 blocker = insert(:user)
635 blockee = insert(:user)
636 friend = insert(:user)
637
638 {:ok, _user_relationship} = User.block(blocker, blockee)
639
640 {:ok, activity_one} = CommonAPI.post(friend, %{status: "hey!"})
641
642 {:ok, activity_two} = CommonAPI.post(blockee, %{status: "hey! @#{friend.nickname}"})
643
644 assert object = Pleroma.Object.normalize(activity_two)
645
646 data = %{
647 "actor" => friend.ap_id,
648 "object" => object.data["id"],
649 "context" => object.data["context"],
650 "type" => "Announce",
651 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
652 "cc" => [blockee.ap_id]
653 }
654
655 assert {:ok, activity_three} = ActivityPub.insert(data)
656
657 activities =
658 ActivityPub.fetch_activities([], %{blocking_user: blocker})
659 |> Enum.map(fn act -> act.id end)
660
661 assert Enum.member?(activities, activity_one.id)
662 refute Enum.member?(activities, activity_two.id)
663 refute Enum.member?(activities, activity_three.id)
664 end
665
666 test "doesn't return activities from blocked domains" do
667 domain = "dogwhistle.zone"
668 domain_user = insert(:user, %{ap_id: "https://#{domain}/@pundit"})
669 note = insert(:note, %{data: %{"actor" => domain_user.ap_id}})
670 activity = insert(:note_activity, %{note: note})
671 user = insert(:user)
672 {:ok, user} = User.block_domain(user, domain)
673
674 activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
675
676 refute activity in activities
677
678 followed_user = insert(:user)
679 CommonAPI.follow(user, followed_user)
680 {:ok, repeat_activity} = CommonAPI.repeat(activity.id, followed_user)
681
682 activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
683
684 refute repeat_activity in activities
685 end
686
687 test "does return activities from followed users on blocked domains" do
688 domain = "meanies.social"
689 domain_user = insert(:user, %{ap_id: "https://#{domain}/@pundit"})
690 blocker = insert(:user)
691
692 {:ok, blocker} = User.follow(blocker, domain_user)
693 {:ok, blocker} = User.block_domain(blocker, domain)
694
695 assert User.following?(blocker, domain_user)
696 assert User.blocks_domain?(blocker, domain_user)
697 refute User.blocks?(blocker, domain_user)
698
699 note = insert(:note, %{data: %{"actor" => domain_user.ap_id}})
700 activity = insert(:note_activity, %{note: note})
701
702 activities = ActivityPub.fetch_activities([], %{blocking_user: blocker, skip_preload: true})
703
704 assert activity in activities
705
706 # And check that if the guy we DO follow boosts someone else from their domain,
707 # that should be hidden
708 another_user = insert(:user, %{ap_id: "https://#{domain}/@meanie2"})
709 bad_note = insert(:note, %{data: %{"actor" => another_user.ap_id}})
710 bad_activity = insert(:note_activity, %{note: bad_note})
711 {:ok, repeat_activity} = CommonAPI.repeat(bad_activity.id, domain_user)
712
713 activities = ActivityPub.fetch_activities([], %{blocking_user: blocker, skip_preload: true})
714
715 refute repeat_activity in activities
716 end
717
718 test "doesn't return muted activities" do
719 activity_one = insert(:note_activity)
720 activity_two = insert(:note_activity)
721 activity_three = insert(:note_activity)
722 user = insert(:user)
723 booster = insert(:user)
724
725 activity_one_actor = User.get_by_ap_id(activity_one.data["actor"])
726 {:ok, _user_relationships} = User.mute(user, activity_one_actor)
727
728 activities = ActivityPub.fetch_activities([], %{muting_user: user, skip_preload: true})
729
730 assert Enum.member?(activities, activity_two)
731 assert Enum.member?(activities, activity_three)
732 refute Enum.member?(activities, activity_one)
733
734 # Calling with 'with_muted' will deliver muted activities, too.
735 activities =
736 ActivityPub.fetch_activities([], %{
737 muting_user: user,
738 with_muted: true,
739 skip_preload: true
740 })
741
742 assert Enum.member?(activities, activity_two)
743 assert Enum.member?(activities, activity_three)
744 assert Enum.member?(activities, activity_one)
745
746 {:ok, _user_mute} = User.unmute(user, activity_one_actor)
747
748 activities = ActivityPub.fetch_activities([], %{muting_user: user, skip_preload: true})
749
750 assert Enum.member?(activities, activity_two)
751 assert Enum.member?(activities, activity_three)
752 assert Enum.member?(activities, activity_one)
753
754 activity_three_actor = User.get_by_ap_id(activity_three.data["actor"])
755 {:ok, _user_relationships} = User.mute(user, activity_three_actor)
756 {:ok, %{data: %{"object" => id}}} = CommonAPI.repeat(activity_three.id, booster)
757 %Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id)
758 activity_three = Activity.get_by_id(activity_three.id)
759
760 activities = ActivityPub.fetch_activities([], %{muting_user: user, skip_preload: true})
761
762 assert Enum.member?(activities, activity_two)
763 refute Enum.member?(activities, activity_three)
764 refute Enum.member?(activities, boost_activity)
765 assert Enum.member?(activities, activity_one)
766
767 activities = ActivityPub.fetch_activities([], %{muting_user: nil, skip_preload: true})
768
769 assert Enum.member?(activities, activity_two)
770 assert Enum.member?(activities, activity_three)
771 assert Enum.member?(activities, boost_activity)
772 assert Enum.member?(activities, activity_one)
773 end
774
775 test "doesn't return thread muted activities" do
776 user = insert(:user)
777 _activity_one = insert(:note_activity)
778 note_two = insert(:note, data: %{"context" => "suya.."})
779 activity_two = insert(:note_activity, note: note_two)
780
781 {:ok, _activity_two} = CommonAPI.add_mute(user, activity_two)
782
783 assert [_activity_one] = ActivityPub.fetch_activities([], %{muting_user: user})
784 end
785
786 test "returns thread muted activities when with_muted is set" do
787 user = insert(:user)
788 _activity_one = insert(:note_activity)
789 note_two = insert(:note, data: %{"context" => "suya.."})
790 activity_two = insert(:note_activity, note: note_two)
791
792 {:ok, _activity_two} = CommonAPI.add_mute(user, activity_two)
793
794 assert [_activity_two, _activity_one] =
795 ActivityPub.fetch_activities([], %{muting_user: user, with_muted: true})
796 end
797
798 test "does include announces on request" do
799 activity_three = insert(:note_activity)
800 user = insert(:user)
801 booster = insert(:user)
802
803 {:ok, user} = User.follow(user, booster)
804
805 {:ok, announce} = CommonAPI.repeat(activity_three.id, booster)
806
807 [announce_activity] = ActivityPub.fetch_activities([user.ap_id | User.following(user)])
808
809 assert announce_activity.id == announce.id
810 end
811
812 test "excludes reblogs on request" do
813 user = insert(:user)
814 {:ok, expected_activity} = ActivityBuilder.insert(%{"type" => "Create"}, %{:user => user})
815 {:ok, _} = ActivityBuilder.insert(%{"type" => "Announce"}, %{:user => user})
816
817 [activity] = ActivityPub.fetch_user_activities(user, nil, %{exclude_reblogs: true})
818
819 assert activity == expected_activity
820 end
821
822 describe "irreversible filters" do
823 setup do
824 user = insert(:user)
825 user_two = insert(:user)
826
827 insert(:filter, user: user_two, phrase: "cofe", hide: true)
828 insert(:filter, user: user_two, phrase: "ok boomer", hide: true)
829 insert(:filter, user: user_two, phrase: "test", hide: false)
830
831 params = %{
832 type: ["Create", "Announce"],
833 user: user_two
834 }
835
836 {:ok, %{user: user, user_two: user_two, params: params}}
837 end
838
839 test "it returns statuses if they don't contain exact filter words", %{
840 user: user,
841 params: params
842 } do
843 {:ok, _} = CommonAPI.post(user, %{status: "hey"})
844 {:ok, _} = CommonAPI.post(user, %{status: "got cofefe?"})
845 {:ok, _} = CommonAPI.post(user, %{status: "I am not a boomer"})
846 {:ok, _} = CommonAPI.post(user, %{status: "ok boomers"})
847 {:ok, _} = CommonAPI.post(user, %{status: "ccofee is not a word"})
848 {:ok, _} = CommonAPI.post(user, %{status: "this is a test"})
849
850 activities = ActivityPub.fetch_activities([], params)
851
852 assert Enum.count(activities) == 6
853 end
854
855 test "it does not filter user's own statuses", %{user_two: user_two, params: params} do
856 {:ok, _} = CommonAPI.post(user_two, %{status: "Give me some cofe!"})
857 {:ok, _} = CommonAPI.post(user_two, %{status: "ok boomer"})
858
859 activities = ActivityPub.fetch_activities([], params)
860
861 assert Enum.count(activities) == 2
862 end
863
864 test "it excludes statuses with filter words", %{user: user, params: params} do
865 {:ok, _} = CommonAPI.post(user, %{status: "Give me some cofe!"})
866 {:ok, _} = CommonAPI.post(user, %{status: "ok boomer"})
867 {:ok, _} = CommonAPI.post(user, %{status: "is it a cOfE?"})
868 {:ok, _} = CommonAPI.post(user, %{status: "cofe is all I need"})
869 {:ok, _} = CommonAPI.post(user, %{status: "— ok BOOMER\n"})
870
871 activities = ActivityPub.fetch_activities([], params)
872
873 assert Enum.empty?(activities)
874 end
875
876 test "it returns all statuses if user does not have any filters" do
877 another_user = insert(:user)
878 {:ok, _} = CommonAPI.post(another_user, %{status: "got cofe?"})
879 {:ok, _} = CommonAPI.post(another_user, %{status: "test!"})
880
881 activities =
882 ActivityPub.fetch_activities([], %{
883 type: ["Create", "Announce"],
884 user: another_user
885 })
886
887 assert Enum.count(activities) == 2
888 end
889 end
890
891 describe "public fetch activities" do
892 test "doesn't retrieve unlisted activities" do
893 user = insert(:user)
894
895 {:ok, _unlisted_activity} = CommonAPI.post(user, %{status: "yeah", visibility: "unlisted"})
896
897 {:ok, listed_activity} = CommonAPI.post(user, %{status: "yeah"})
898
899 [activity] = ActivityPub.fetch_public_activities()
900
901 assert activity == listed_activity
902 end
903
904 test "retrieves public activities" do
905 _activities = ActivityPub.fetch_public_activities()
906
907 %{public: public} = ActivityBuilder.public_and_non_public()
908
909 activities = ActivityPub.fetch_public_activities()
910 assert length(activities) == 1
911 assert Enum.at(activities, 0) == public
912 end
913
914 test "retrieves a maximum of 20 activities" do
915 ActivityBuilder.insert_list(10)
916 expected_activities = ActivityBuilder.insert_list(20)
917
918 activities = ActivityPub.fetch_public_activities()
919
920 assert collect_ids(activities) == collect_ids(expected_activities)
921 assert length(activities) == 20
922 end
923
924 test "retrieves ids starting from a since_id" do
925 activities = ActivityBuilder.insert_list(30)
926 expected_activities = ActivityBuilder.insert_list(10)
927 since_id = List.last(activities).id
928
929 activities = ActivityPub.fetch_public_activities(%{since_id: since_id})
930
931 assert collect_ids(activities) == collect_ids(expected_activities)
932 assert length(activities) == 10
933 end
934
935 test "retrieves ids up to max_id" do
936 ActivityBuilder.insert_list(10)
937 expected_activities = ActivityBuilder.insert_list(20)
938
939 %{id: max_id} =
940 10
941 |> ActivityBuilder.insert_list()
942 |> List.first()
943
944 activities = ActivityPub.fetch_public_activities(%{max_id: max_id})
945
946 assert length(activities) == 20
947 assert collect_ids(activities) == collect_ids(expected_activities)
948 end
949
950 test "paginates via offset/limit" do
951 _first_part_activities = ActivityBuilder.insert_list(10)
952 second_part_activities = ActivityBuilder.insert_list(10)
953
954 later_activities = ActivityBuilder.insert_list(10)
955
956 activities = ActivityPub.fetch_public_activities(%{page: "2", page_size: "20"}, :offset)
957
958 assert length(activities) == 20
959
960 assert collect_ids(activities) ==
961 collect_ids(second_part_activities) ++ collect_ids(later_activities)
962 end
963
964 test "doesn't return reblogs for users for whom reblogs have been muted" do
965 activity = insert(:note_activity)
966 user = insert(:user)
967 booster = insert(:user)
968 {:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, booster)
969
970 {:ok, activity} = CommonAPI.repeat(activity.id, booster)
971
972 activities = ActivityPub.fetch_activities([], %{muting_user: user})
973
974 refute Enum.any?(activities, fn %{id: id} -> id == activity.id end)
975 end
976
977 test "returns reblogs for users for whom reblogs have not been muted" do
978 activity = insert(:note_activity)
979 user = insert(:user)
980 booster = insert(:user)
981 {:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, booster)
982 {:ok, _reblog_mute} = CommonAPI.show_reblogs(user, booster)
983
984 {:ok, activity} = CommonAPI.repeat(activity.id, booster)
985
986 activities = ActivityPub.fetch_activities([], %{muting_user: user})
987
988 assert Enum.any?(activities, fn %{id: id} -> id == activity.id end)
989 end
990 end
991
992 describe "uploading files" do
993 setup do
994 test_file = %Plug.Upload{
995 content_type: "image/jpg",
996 path: Path.absname("test/fixtures/image.jpg"),
997 filename: "an_image.jpg"
998 }
999
1000 %{test_file: test_file}
1001 end
1002
1003 test "sets a description if given", %{test_file: file} do
1004 {:ok, %Object{} = object} = ActivityPub.upload(file, description: "a cool file")
1005 assert object.data["name"] == "a cool file"
1006 end
1007
1008 test "it sets the default description depending on the configuration", %{test_file: file} do
1009 clear_config([Pleroma.Upload, :default_description])
1010
1011 Pleroma.Config.put([Pleroma.Upload, :default_description], nil)
1012 {:ok, %Object{} = object} = ActivityPub.upload(file)
1013 assert object.data["name"] == ""
1014
1015 Pleroma.Config.put([Pleroma.Upload, :default_description], :filename)
1016 {:ok, %Object{} = object} = ActivityPub.upload(file)
1017 assert object.data["name"] == "an_image.jpg"
1018
1019 Pleroma.Config.put([Pleroma.Upload, :default_description], "unnamed attachment")
1020 {:ok, %Object{} = object} = ActivityPub.upload(file)
1021 assert object.data["name"] == "unnamed attachment"
1022 end
1023
1024 test "copies the file to the configured folder", %{test_file: file} do
1025 clear_config([Pleroma.Upload, :default_description], :filename)
1026 {:ok, %Object{} = object} = ActivityPub.upload(file)
1027 assert object.data["name"] == "an_image.jpg"
1028 end
1029
1030 test "works with base64 encoded images" do
1031 file = %{
1032 img: data_uri()
1033 }
1034
1035 {:ok, %Object{}} = ActivityPub.upload(file)
1036 end
1037 end
1038
1039 describe "fetch the latest Follow" do
1040 test "fetches the latest Follow activity" do
1041 %Activity{data: %{"type" => "Follow"}} = activity = insert(:follow_activity)
1042 follower = Repo.get_by(User, ap_id: activity.data["actor"])
1043 followed = Repo.get_by(User, ap_id: activity.data["object"])
1044
1045 assert activity == Utils.fetch_latest_follow(follower, followed)
1046 end
1047 end
1048
1049 describe "unfollowing" do
1050 test "it reverts unfollow activity" do
1051 follower = insert(:user)
1052 followed = insert(:user)
1053
1054 {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
1055
1056 with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
1057 assert {:error, :reverted} = ActivityPub.unfollow(follower, followed)
1058 end
1059
1060 activity = Activity.get_by_id(follow_activity.id)
1061 assert activity.data["type"] == "Follow"
1062 assert activity.data["actor"] == follower.ap_id
1063
1064 assert activity.data["object"] == followed.ap_id
1065 end
1066
1067 test "creates an undo activity for the last follow" do
1068 follower = insert(:user)
1069 followed = insert(:user)
1070
1071 {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
1072 {:ok, activity} = ActivityPub.unfollow(follower, followed)
1073
1074 assert activity.data["type"] == "Undo"
1075 assert activity.data["actor"] == follower.ap_id
1076
1077 embedded_object = activity.data["object"]
1078 assert is_map(embedded_object)
1079 assert embedded_object["type"] == "Follow"
1080 assert embedded_object["object"] == followed.ap_id
1081 assert embedded_object["id"] == follow_activity.data["id"]
1082 end
1083
1084 test "creates an undo activity for a pending follow request" do
1085 follower = insert(:user)
1086 followed = insert(:user, %{locked: true})
1087
1088 {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
1089 {:ok, activity} = ActivityPub.unfollow(follower, followed)
1090
1091 assert activity.data["type"] == "Undo"
1092 assert activity.data["actor"] == follower.ap_id
1093
1094 embedded_object = activity.data["object"]
1095 assert is_map(embedded_object)
1096 assert embedded_object["type"] == "Follow"
1097 assert embedded_object["object"] == followed.ap_id
1098 assert embedded_object["id"] == follow_activity.data["id"]
1099 end
1100 end
1101
1102 describe "timeline post-processing" do
1103 test "it filters broken threads" do
1104 user1 = insert(:user)
1105 user2 = insert(:user)
1106 user3 = insert(:user)
1107
1108 {:ok, user1} = User.follow(user1, user3)
1109 assert User.following?(user1, user3)
1110
1111 {:ok, user2} = User.follow(user2, user3)
1112 assert User.following?(user2, user3)
1113
1114 {:ok, user3} = User.follow(user3, user2)
1115 assert User.following?(user3, user2)
1116
1117 {:ok, public_activity} = CommonAPI.post(user3, %{status: "hi 1"})
1118
1119 {:ok, private_activity_1} = CommonAPI.post(user3, %{status: "hi 2", visibility: "private"})
1120
1121 {:ok, private_activity_2} =
1122 CommonAPI.post(user2, %{
1123 status: "hi 3",
1124 visibility: "private",
1125 in_reply_to_status_id: private_activity_1.id
1126 })
1127
1128 {:ok, private_activity_3} =
1129 CommonAPI.post(user3, %{
1130 status: "hi 4",
1131 visibility: "private",
1132 in_reply_to_status_id: private_activity_2.id
1133 })
1134
1135 activities =
1136 ActivityPub.fetch_activities([user1.ap_id | User.following(user1)])
1137 |> Enum.map(fn a -> a.id end)
1138
1139 private_activity_1 = Activity.get_by_ap_id_with_object(private_activity_1.data["id"])
1140
1141 assert [public_activity.id, private_activity_1.id, private_activity_3.id] == activities
1142
1143 assert length(activities) == 3
1144
1145 activities =
1146 ActivityPub.fetch_activities([user1.ap_id | User.following(user1)], %{user: user1})
1147 |> Enum.map(fn a -> a.id end)
1148
1149 assert [public_activity.id, private_activity_1.id] == activities
1150 assert length(activities) == 2
1151 end
1152 end
1153
1154 describe "flag/1" do
1155 setup do
1156 reporter = insert(:user)
1157 target_account = insert(:user)
1158 content = "foobar"
1159 {:ok, activity} = CommonAPI.post(target_account, %{status: content})
1160 context = Utils.generate_context_id()
1161
1162 reporter_ap_id = reporter.ap_id
1163 target_ap_id = target_account.ap_id
1164 activity_ap_id = activity.data["id"]
1165
1166 activity_with_object = Activity.get_by_ap_id_with_object(activity_ap_id)
1167
1168 {:ok,
1169 %{
1170 reporter: reporter,
1171 context: context,
1172 target_account: target_account,
1173 reported_activity: activity,
1174 content: content,
1175 activity_ap_id: activity_ap_id,
1176 activity_with_object: activity_with_object,
1177 reporter_ap_id: reporter_ap_id,
1178 target_ap_id: target_ap_id
1179 }}
1180 end
1181
1182 test "it can create a Flag activity",
1183 %{
1184 reporter: reporter,
1185 context: context,
1186 target_account: target_account,
1187 reported_activity: reported_activity,
1188 content: content,
1189 activity_ap_id: activity_ap_id,
1190 activity_with_object: activity_with_object,
1191 reporter_ap_id: reporter_ap_id,
1192 target_ap_id: target_ap_id
1193 } do
1194 assert {:ok, activity} =
1195 ActivityPub.flag(%{
1196 actor: reporter,
1197 context: context,
1198 account: target_account,
1199 statuses: [reported_activity],
1200 content: content
1201 })
1202
1203 note_obj = %{
1204 "type" => "Note",
1205 "id" => activity_ap_id,
1206 "content" => content,
1207 "published" => activity_with_object.object.data["published"],
1208 "actor" =>
1209 AccountView.render("show.json", %{user: target_account, skip_visibility_check: true})
1210 }
1211
1212 assert %Activity{
1213 actor: ^reporter_ap_id,
1214 data: %{
1215 "type" => "Flag",
1216 "content" => ^content,
1217 "context" => ^context,
1218 "object" => [^target_ap_id, ^note_obj]
1219 }
1220 } = activity
1221 end
1222
1223 test_with_mock "strips status data from Flag, before federating it",
1224 %{
1225 reporter: reporter,
1226 context: context,
1227 target_account: target_account,
1228 reported_activity: reported_activity,
1229 content: content
1230 },
1231 Utils,
1232 [:passthrough],
1233 [] do
1234 {:ok, activity} =
1235 ActivityPub.flag(%{
1236 actor: reporter,
1237 context: context,
1238 account: target_account,
1239 statuses: [reported_activity],
1240 content: content
1241 })
1242
1243 new_data =
1244 put_in(activity.data, ["object"], [target_account.ap_id, reported_activity.data["id"]])
1245
1246 assert_called(Utils.maybe_federate(%{activity | data: new_data}))
1247 end
1248 end
1249
1250 test "fetch_activities/2 returns activities addressed to a list " do
1251 user = insert(:user)
1252 member = insert(:user)
1253 {:ok, list} = Pleroma.List.create("foo", user)
1254 {:ok, list} = Pleroma.List.follow(list, member)
1255
1256 {:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"})
1257
1258 activity = Repo.preload(activity, :bookmark)
1259 activity = %Activity{activity | thread_muted?: !!activity.thread_muted?}
1260
1261 assert ActivityPub.fetch_activities([], %{user: user}) == [activity]
1262 end
1263
1264 def data_uri do
1265 File.read!("test/fixtures/avatar_data_uri")
1266 end
1267
1268 describe "fetch_activities_bounded" do
1269 test "fetches private posts for followed users" do
1270 user = insert(:user)
1271
1272 {:ok, activity} =
1273 CommonAPI.post(user, %{
1274 status: "thought I looked cute might delete later :3",
1275 visibility: "private"
1276 })
1277
1278 [result] = ActivityPub.fetch_activities_bounded([user.follower_address], [])
1279 assert result.id == activity.id
1280 end
1281
1282 test "fetches only public posts for other users" do
1283 user = insert(:user)
1284 {:ok, activity} = CommonAPI.post(user, %{status: "#cofe", visibility: "public"})
1285
1286 {:ok, _private_activity} =
1287 CommonAPI.post(user, %{
1288 status: "why is tenshi eating a corndog so cute?",
1289 visibility: "private"
1290 })
1291
1292 [result] = ActivityPub.fetch_activities_bounded([], [user.follower_address])
1293 assert result.id == activity.id
1294 end
1295 end
1296
1297 describe "fetch_follow_information_for_user" do
1298 test "syncronizes following/followers counters" do
1299 user =
1300 insert(:user,
1301 local: false,
1302 follower_address: "http://localhost:4001/users/fuser2/followers",
1303 following_address: "http://localhost:4001/users/fuser2/following"
1304 )
1305
1306 {:ok, info} = ActivityPub.fetch_follow_information_for_user(user)
1307 assert info.follower_count == 527
1308 assert info.following_count == 267
1309 end
1310
1311 test "detects hidden followers" do
1312 mock(fn env ->
1313 case env.url do
1314 "http://localhost:4001/users/masto_closed/followers?page=1" ->
1315 %Tesla.Env{status: 403, body: ""}
1316
1317 _ ->
1318 apply(HttpRequestMock, :request, [env])
1319 end
1320 end)
1321
1322 user =
1323 insert(:user,
1324 local: false,
1325 follower_address: "http://localhost:4001/users/masto_closed/followers",
1326 following_address: "http://localhost:4001/users/masto_closed/following"
1327 )
1328
1329 {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user)
1330 assert follow_info.hide_followers == true
1331 assert follow_info.hide_follows == false
1332 end
1333
1334 test "detects hidden follows" do
1335 mock(fn env ->
1336 case env.url do
1337 "http://localhost:4001/users/masto_closed/following?page=1" ->
1338 %Tesla.Env{status: 403, body: ""}
1339
1340 _ ->
1341 apply(HttpRequestMock, :request, [env])
1342 end
1343 end)
1344
1345 user =
1346 insert(:user,
1347 local: false,
1348 follower_address: "http://localhost:4001/users/masto_closed/followers",
1349 following_address: "http://localhost:4001/users/masto_closed/following"
1350 )
1351
1352 {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user)
1353 assert follow_info.hide_followers == false
1354 assert follow_info.hide_follows == true
1355 end
1356
1357 test "detects hidden follows/followers for friendica" do
1358 user =
1359 insert(:user,
1360 local: false,
1361 follower_address: "http://localhost:8080/followers/fuser3",
1362 following_address: "http://localhost:8080/following/fuser3"
1363 )
1364
1365 {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user)
1366 assert follow_info.hide_followers == true
1367 assert follow_info.follower_count == 296
1368 assert follow_info.following_count == 32
1369 assert follow_info.hide_follows == true
1370 end
1371
1372 test "doesn't crash when follower and following counters are hidden" do
1373 mock(fn env ->
1374 case env.url do
1375 "http://localhost:4001/users/masto_hidden_counters/following" ->
1376 json(%{
1377 "@context" => "https://www.w3.org/ns/activitystreams",
1378 "id" => "http://localhost:4001/users/masto_hidden_counters/followers"
1379 })
1380
1381 "http://localhost:4001/users/masto_hidden_counters/following?page=1" ->
1382 %Tesla.Env{status: 403, body: ""}
1383
1384 "http://localhost:4001/users/masto_hidden_counters/followers" ->
1385 json(%{
1386 "@context" => "https://www.w3.org/ns/activitystreams",
1387 "id" => "http://localhost:4001/users/masto_hidden_counters/following"
1388 })
1389
1390 "http://localhost:4001/users/masto_hidden_counters/followers?page=1" ->
1391 %Tesla.Env{status: 403, body: ""}
1392 end
1393 end)
1394
1395 user =
1396 insert(:user,
1397 local: false,
1398 follower_address: "http://localhost:4001/users/masto_hidden_counters/followers",
1399 following_address: "http://localhost:4001/users/masto_hidden_counters/following"
1400 )
1401
1402 {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user)
1403
1404 assert follow_info.hide_followers == true
1405 assert follow_info.follower_count == 0
1406 assert follow_info.hide_follows == true
1407 assert follow_info.following_count == 0
1408 end
1409 end
1410
1411 describe "fetch_favourites/3" do
1412 test "returns a favourite activities sorted by adds to favorite" do
1413 user = insert(:user)
1414 other_user = insert(:user)
1415 user1 = insert(:user)
1416 user2 = insert(:user)
1417 {:ok, a1} = CommonAPI.post(user1, %{status: "bla"})
1418 {:ok, _a2} = CommonAPI.post(user2, %{status: "traps are happy"})
1419 {:ok, a3} = CommonAPI.post(user2, %{status: "Trees Are "})
1420 {:ok, a4} = CommonAPI.post(user2, %{status: "Agent Smith "})
1421 {:ok, a5} = CommonAPI.post(user1, %{status: "Red or Blue "})
1422
1423 {:ok, _} = CommonAPI.favorite(user, a4.id)
1424 {:ok, _} = CommonAPI.favorite(other_user, a3.id)
1425 {:ok, _} = CommonAPI.favorite(user, a3.id)
1426 {:ok, _} = CommonAPI.favorite(other_user, a5.id)
1427 {:ok, _} = CommonAPI.favorite(user, a5.id)
1428 {:ok, _} = CommonAPI.favorite(other_user, a4.id)
1429 {:ok, _} = CommonAPI.favorite(user, a1.id)
1430 {:ok, _} = CommonAPI.favorite(other_user, a1.id)
1431 result = ActivityPub.fetch_favourites(user)
1432
1433 assert Enum.map(result, & &1.id) == [a1.id, a5.id, a3.id, a4.id]
1434
1435 result = ActivityPub.fetch_favourites(user, %{limit: 2})
1436 assert Enum.map(result, & &1.id) == [a1.id, a5.id]
1437 end
1438 end
1439
1440 describe "Move activity" do
1441 test "create" do
1442 %{ap_id: old_ap_id} = old_user = insert(:user)
1443 %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
1444 follower = insert(:user)
1445 follower_move_opted_out = insert(:user, allow_following_move: false)
1446
1447 User.follow(follower, old_user)
1448 User.follow(follower_move_opted_out, old_user)
1449
1450 assert User.following?(follower, old_user)
1451 assert User.following?(follower_move_opted_out, old_user)
1452
1453 assert {:ok, activity} = ActivityPub.move(old_user, new_user)
1454
1455 assert %Activity{
1456 actor: ^old_ap_id,
1457 data: %{
1458 "actor" => ^old_ap_id,
1459 "object" => ^old_ap_id,
1460 "target" => ^new_ap_id,
1461 "type" => "Move"
1462 },
1463 local: true
1464 } = activity
1465
1466 params = %{
1467 "op" => "move_following",
1468 "origin_id" => old_user.id,
1469 "target_id" => new_user.id
1470 }
1471
1472 assert_enqueued(worker: Pleroma.Workers.BackgroundWorker, args: params)
1473
1474 Pleroma.Workers.BackgroundWorker.perform(%Oban.Job{args: params})
1475
1476 refute User.following?(follower, old_user)
1477 assert User.following?(follower, new_user)
1478
1479 assert User.following?(follower_move_opted_out, old_user)
1480 refute User.following?(follower_move_opted_out, new_user)
1481
1482 activity = %Activity{activity | object: nil}
1483
1484 assert [%Notification{activity: ^activity}] = Notification.for_user(follower)
1485
1486 assert [%Notification{activity: ^activity}] = Notification.for_user(follower_move_opted_out)
1487 end
1488
1489 test "old user must be in the new user's `also_known_as` list" do
1490 old_user = insert(:user)
1491 new_user = insert(:user)
1492
1493 assert {:error, "Target account must have the origin in `alsoKnownAs`"} =
1494 ActivityPub.move(old_user, new_user)
1495 end
1496 end
1497
1498 test "doesn't retrieve replies activities with exclude_replies" do
1499 user = insert(:user)
1500
1501 {:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
1502
1503 {:ok, _reply} = CommonAPI.post(user, %{status: "yeah", in_reply_to_status_id: activity.id})
1504
1505 [result] = ActivityPub.fetch_public_activities(%{exclude_replies: true})
1506
1507 assert result.id == activity.id
1508
1509 assert length(ActivityPub.fetch_public_activities()) == 2
1510 end
1511
1512 describe "replies filtering with public messages" do
1513 setup :public_messages
1514
1515 test "public timeline", %{users: %{u1: user}} do
1516 activities_ids =
1517 %{}
1518 |> Map.put(:type, ["Create", "Announce"])
1519 |> Map.put(:local_only, false)
1520 |> Map.put(:blocking_user, user)
1521 |> Map.put(:muting_user, user)
1522 |> Map.put(:reply_filtering_user, user)
1523 |> ActivityPub.fetch_public_activities()
1524 |> Enum.map(& &1.id)
1525
1526 assert length(activities_ids) == 16
1527 end
1528
1529 test "public timeline with reply_visibility `following`", %{
1530 users: %{u1: user},
1531 u1: u1,
1532 u2: u2,
1533 u3: u3,
1534 u4: u4,
1535 activities: activities
1536 } do
1537 activities_ids =
1538 %{}
1539 |> Map.put(:type, ["Create", "Announce"])
1540 |> Map.put(:local_only, false)
1541 |> Map.put(:blocking_user, user)
1542 |> Map.put(:muting_user, user)
1543 |> Map.put(:reply_visibility, "following")
1544 |> Map.put(:reply_filtering_user, user)
1545 |> ActivityPub.fetch_public_activities()
1546 |> Enum.map(& &1.id)
1547
1548 assert length(activities_ids) == 14
1549
1550 visible_ids =
1551 Map.values(u1) ++ Map.values(u2) ++ Map.values(u4) ++ Map.values(activities) ++ [u3[:r1]]
1552
1553 assert Enum.all?(visible_ids, &(&1 in activities_ids))
1554 end
1555
1556 test "public timeline with reply_visibility `self`", %{
1557 users: %{u1: user},
1558 u1: u1,
1559 u2: u2,
1560 u3: u3,
1561 u4: u4,
1562 activities: activities
1563 } do
1564 activities_ids =
1565 %{}
1566 |> Map.put(:type, ["Create", "Announce"])
1567 |> Map.put(:local_only, false)
1568 |> Map.put(:blocking_user, user)
1569 |> Map.put(:muting_user, user)
1570 |> Map.put(:reply_visibility, "self")
1571 |> Map.put(:reply_filtering_user, user)
1572 |> ActivityPub.fetch_public_activities()
1573 |> Enum.map(& &1.id)
1574
1575 assert length(activities_ids) == 10
1576 visible_ids = Map.values(u1) ++ [u2[:r1], u3[:r1], u4[:r1]] ++ Map.values(activities)
1577 assert Enum.all?(visible_ids, &(&1 in activities_ids))
1578 end
1579
1580 test "home timeline", %{
1581 users: %{u1: user},
1582 activities: activities,
1583 u1: u1,
1584 u2: u2,
1585 u3: u3,
1586 u4: u4
1587 } do
1588 params =
1589 %{}
1590 |> Map.put(:type, ["Create", "Announce"])
1591 |> Map.put(:blocking_user, user)
1592 |> Map.put(:muting_user, user)
1593 |> Map.put(:user, user)
1594 |> Map.put(:reply_filtering_user, user)
1595
1596 activities_ids =
1597 ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
1598 |> Enum.map(& &1.id)
1599
1600 assert length(activities_ids) == 13
1601
1602 visible_ids =
1603 Map.values(u1) ++
1604 Map.values(u3) ++
1605 [
1606 activities[:a1],
1607 activities[:a2],
1608 activities[:a4],
1609 u2[:r1],
1610 u2[:r3],
1611 u4[:r1],
1612 u4[:r2]
1613 ]
1614
1615 assert Enum.all?(visible_ids, &(&1 in activities_ids))
1616 end
1617
1618 test "home timeline with reply_visibility `following`", %{
1619 users: %{u1: user},
1620 activities: activities,
1621 u1: u1,
1622 u2: u2,
1623 u3: u3,
1624 u4: u4
1625 } do
1626 params =
1627 %{}
1628 |> Map.put(:type, ["Create", "Announce"])
1629 |> Map.put(:blocking_user, user)
1630 |> Map.put(:muting_user, user)
1631 |> Map.put(:user, user)
1632 |> Map.put(:reply_visibility, "following")
1633 |> Map.put(:reply_filtering_user, user)
1634
1635 activities_ids =
1636 ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
1637 |> Enum.map(& &1.id)
1638
1639 assert length(activities_ids) == 11
1640
1641 visible_ids =
1642 Map.values(u1) ++
1643 [
1644 activities[:a1],
1645 activities[:a2],
1646 activities[:a4],
1647 u2[:r1],
1648 u2[:r3],
1649 u3[:r1],
1650 u4[:r1],
1651 u4[:r2]
1652 ]
1653
1654 assert Enum.all?(visible_ids, &(&1 in activities_ids))
1655 end
1656
1657 test "home timeline with reply_visibility `self`", %{
1658 users: %{u1: user},
1659 activities: activities,
1660 u1: u1,
1661 u2: u2,
1662 u3: u3,
1663 u4: u4
1664 } do
1665 params =
1666 %{}
1667 |> Map.put(:type, ["Create", "Announce"])
1668 |> Map.put(:blocking_user, user)
1669 |> Map.put(:muting_user, user)
1670 |> Map.put(:user, user)
1671 |> Map.put(:reply_visibility, "self")
1672 |> Map.put(:reply_filtering_user, user)
1673
1674 activities_ids =
1675 ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
1676 |> Enum.map(& &1.id)
1677
1678 assert length(activities_ids) == 9
1679
1680 visible_ids =
1681 Map.values(u1) ++
1682 [
1683 activities[:a1],
1684 activities[:a2],
1685 activities[:a4],
1686 u2[:r1],
1687 u3[:r1],
1688 u4[:r1]
1689 ]
1690
1691 assert Enum.all?(visible_ids, &(&1 in activities_ids))
1692 end
1693
1694 test "filtering out announces where the user is the actor of the announced message" do
1695 user = insert(:user)
1696 other_user = insert(:user)
1697 third_user = insert(:user)
1698 User.follow(user, other_user)
1699
1700 {:ok, post} = CommonAPI.post(user, %{status: "yo"})
1701 {:ok, other_post} = CommonAPI.post(third_user, %{status: "yo"})
1702 {:ok, _announce} = CommonAPI.repeat(post.id, other_user)
1703 {:ok, _announce} = CommonAPI.repeat(post.id, third_user)
1704 {:ok, announce} = CommonAPI.repeat(other_post.id, other_user)
1705
1706 params = %{
1707 type: ["Announce"]
1708 }
1709
1710 results =
1711 [user.ap_id | User.following(user)]
1712 |> ActivityPub.fetch_activities(params)
1713
1714 assert length(results) == 3
1715
1716 params = %{
1717 type: ["Announce"],
1718 announce_filtering_user: user
1719 }
1720
1721 [result] =
1722 [user.ap_id | User.following(user)]
1723 |> ActivityPub.fetch_activities(params)
1724
1725 assert result.id == announce.id
1726 end
1727 end
1728
1729 describe "replies filtering with private messages" do
1730 setup :private_messages
1731
1732 test "public timeline", %{users: %{u1: user}} do
1733 activities_ids =
1734 %{}
1735 |> Map.put(:type, ["Create", "Announce"])
1736 |> Map.put(:local_only, false)
1737 |> Map.put(:blocking_user, user)
1738 |> Map.put(:muting_user, user)
1739 |> Map.put(:user, user)
1740 |> ActivityPub.fetch_public_activities()
1741 |> Enum.map(& &1.id)
1742
1743 assert activities_ids == []
1744 end
1745
1746 test "public timeline with default reply_visibility `following`", %{users: %{u1: user}} do
1747 activities_ids =
1748 %{}
1749 |> Map.put(:type, ["Create", "Announce"])
1750 |> Map.put(:local_only, false)
1751 |> Map.put(:blocking_user, user)
1752 |> Map.put(:muting_user, user)
1753 |> Map.put(:reply_visibility, "following")
1754 |> Map.put(:reply_filtering_user, user)
1755 |> Map.put(:user, user)
1756 |> ActivityPub.fetch_public_activities()
1757 |> Enum.map(& &1.id)
1758
1759 assert activities_ids == []
1760 end
1761
1762 test "public timeline with default reply_visibility `self`", %{users: %{u1: user}} do
1763 activities_ids =
1764 %{}
1765 |> Map.put(:type, ["Create", "Announce"])
1766 |> Map.put(:local_only, false)
1767 |> Map.put(:blocking_user, user)
1768 |> Map.put(:muting_user, user)
1769 |> Map.put(:reply_visibility, "self")
1770 |> Map.put(:reply_filtering_user, user)
1771 |> Map.put(:user, user)
1772 |> ActivityPub.fetch_public_activities()
1773 |> Enum.map(& &1.id)
1774
1775 assert activities_ids == []
1776
1777 activities_ids =
1778 %{}
1779 |> Map.put(:reply_visibility, "self")
1780 |> Map.put(:reply_filtering_user, nil)
1781 |> ActivityPub.fetch_public_activities()
1782
1783 assert activities_ids == []
1784 end
1785
1786 test "home timeline", %{users: %{u1: user}} do
1787 params =
1788 %{}
1789 |> Map.put(:type, ["Create", "Announce"])
1790 |> Map.put(:blocking_user, user)
1791 |> Map.put(:muting_user, user)
1792 |> Map.put(:user, user)
1793
1794 activities_ids =
1795 ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
1796 |> Enum.map(& &1.id)
1797
1798 assert length(activities_ids) == 12
1799 end
1800
1801 test "home timeline with default reply_visibility `following`", %{users: %{u1: user}} do
1802 params =
1803 %{}
1804 |> Map.put(:type, ["Create", "Announce"])
1805 |> Map.put(:blocking_user, user)
1806 |> Map.put(:muting_user, user)
1807 |> Map.put(:user, user)
1808 |> Map.put(:reply_visibility, "following")
1809 |> Map.put(:reply_filtering_user, user)
1810
1811 activities_ids =
1812 ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
1813 |> Enum.map(& &1.id)
1814
1815 assert length(activities_ids) == 12
1816 end
1817
1818 test "home timeline with default reply_visibility `self`", %{
1819 users: %{u1: user},
1820 activities: activities,
1821 u1: u1,
1822 u2: u2,
1823 u3: u3,
1824 u4: u4
1825 } do
1826 params =
1827 %{}
1828 |> Map.put(:type, ["Create", "Announce"])
1829 |> Map.put(:blocking_user, user)
1830 |> Map.put(:muting_user, user)
1831 |> Map.put(:user, user)
1832 |> Map.put(:reply_visibility, "self")
1833 |> Map.put(:reply_filtering_user, user)
1834
1835 activities_ids =
1836 ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
1837 |> Enum.map(& &1.id)
1838
1839 assert length(activities_ids) == 10
1840
1841 visible_ids =
1842 Map.values(u1) ++ Map.values(u4) ++ [u2[:r1], u3[:r1]] ++ Map.values(activities)
1843
1844 assert Enum.all?(visible_ids, &(&1 in activities_ids))
1845 end
1846 end
1847
1848 defp public_messages(_) do
1849 [u1, u2, u3, u4] = insert_list(4, :user)
1850 {:ok, u1} = User.follow(u1, u2)
1851 {:ok, u2} = User.follow(u2, u1)
1852 {:ok, u1} = User.follow(u1, u4)
1853 {:ok, u4} = User.follow(u4, u1)
1854
1855 {:ok, u2} = User.follow(u2, u3)
1856 {:ok, u3} = User.follow(u3, u2)
1857
1858 {:ok, a1} = CommonAPI.post(u1, %{status: "Status"})
1859
1860 {:ok, r1_1} =
1861 CommonAPI.post(u2, %{
1862 status: "@#{u1.nickname} reply from u2 to u1",
1863 in_reply_to_status_id: a1.id
1864 })
1865
1866 {:ok, r1_2} =
1867 CommonAPI.post(u3, %{
1868 status: "@#{u1.nickname} reply from u3 to u1",
1869 in_reply_to_status_id: a1.id
1870 })
1871
1872 {:ok, r1_3} =
1873 CommonAPI.post(u4, %{
1874 status: "@#{u1.nickname} reply from u4 to u1",
1875 in_reply_to_status_id: a1.id
1876 })
1877
1878 {:ok, a2} = CommonAPI.post(u2, %{status: "Status"})
1879
1880 {:ok, r2_1} =
1881 CommonAPI.post(u1, %{
1882 status: "@#{u2.nickname} reply from u1 to u2",
1883 in_reply_to_status_id: a2.id
1884 })
1885
1886 {:ok, r2_2} =
1887 CommonAPI.post(u3, %{
1888 status: "@#{u2.nickname} reply from u3 to u2",
1889 in_reply_to_status_id: a2.id
1890 })
1891
1892 {:ok, r2_3} =
1893 CommonAPI.post(u4, %{
1894 status: "@#{u2.nickname} reply from u4 to u2",
1895 in_reply_to_status_id: a2.id
1896 })
1897
1898 {:ok, a3} = CommonAPI.post(u3, %{status: "Status"})
1899
1900 {:ok, r3_1} =
1901 CommonAPI.post(u1, %{
1902 status: "@#{u3.nickname} reply from u1 to u3",
1903 in_reply_to_status_id: a3.id
1904 })
1905
1906 {:ok, r3_2} =
1907 CommonAPI.post(u2, %{
1908 status: "@#{u3.nickname} reply from u2 to u3",
1909 in_reply_to_status_id: a3.id
1910 })
1911
1912 {:ok, r3_3} =
1913 CommonAPI.post(u4, %{
1914 status: "@#{u3.nickname} reply from u4 to u3",
1915 in_reply_to_status_id: a3.id
1916 })
1917
1918 {:ok, a4} = CommonAPI.post(u4, %{status: "Status"})
1919
1920 {:ok, r4_1} =
1921 CommonAPI.post(u1, %{
1922 status: "@#{u4.nickname} reply from u1 to u4",
1923 in_reply_to_status_id: a4.id
1924 })
1925
1926 {:ok, r4_2} =
1927 CommonAPI.post(u2, %{
1928 status: "@#{u4.nickname} reply from u2 to u4",
1929 in_reply_to_status_id: a4.id
1930 })
1931
1932 {:ok, r4_3} =
1933 CommonAPI.post(u3, %{
1934 status: "@#{u4.nickname} reply from u3 to u4",
1935 in_reply_to_status_id: a4.id
1936 })
1937
1938 {:ok,
1939 users: %{u1: u1, u2: u2, u3: u3, u4: u4},
1940 activities: %{a1: a1.id, a2: a2.id, a3: a3.id, a4: a4.id},
1941 u1: %{r1: r1_1.id, r2: r1_2.id, r3: r1_3.id},
1942 u2: %{r1: r2_1.id, r2: r2_2.id, r3: r2_3.id},
1943 u3: %{r1: r3_1.id, r2: r3_2.id, r3: r3_3.id},
1944 u4: %{r1: r4_1.id, r2: r4_2.id, r3: r4_3.id}}
1945 end
1946
1947 defp private_messages(_) do
1948 [u1, u2, u3, u4] = insert_list(4, :user)
1949 {:ok, u1} = User.follow(u1, u2)
1950 {:ok, u2} = User.follow(u2, u1)
1951 {:ok, u1} = User.follow(u1, u3)
1952 {:ok, u3} = User.follow(u3, u1)
1953 {:ok, u1} = User.follow(u1, u4)
1954 {:ok, u4} = User.follow(u4, u1)
1955
1956 {:ok, u2} = User.follow(u2, u3)
1957 {:ok, u3} = User.follow(u3, u2)
1958
1959 {:ok, a1} = CommonAPI.post(u1, %{status: "Status", visibility: "private"})
1960
1961 {:ok, r1_1} =
1962 CommonAPI.post(u2, %{
1963 status: "@#{u1.nickname} reply from u2 to u1",
1964 in_reply_to_status_id: a1.id,
1965 visibility: "private"
1966 })
1967
1968 {:ok, r1_2} =
1969 CommonAPI.post(u3, %{
1970 status: "@#{u1.nickname} reply from u3 to u1",
1971 in_reply_to_status_id: a1.id,
1972 visibility: "private"
1973 })
1974
1975 {:ok, r1_3} =
1976 CommonAPI.post(u4, %{
1977 status: "@#{u1.nickname} reply from u4 to u1",
1978 in_reply_to_status_id: a1.id,
1979 visibility: "private"
1980 })
1981
1982 {:ok, a2} = CommonAPI.post(u2, %{status: "Status", visibility: "private"})
1983
1984 {:ok, r2_1} =
1985 CommonAPI.post(u1, %{
1986 status: "@#{u2.nickname} reply from u1 to u2",
1987 in_reply_to_status_id: a2.id,
1988 visibility: "private"
1989 })
1990
1991 {:ok, r2_2} =
1992 CommonAPI.post(u3, %{
1993 status: "@#{u2.nickname} reply from u3 to u2",
1994 in_reply_to_status_id: a2.id,
1995 visibility: "private"
1996 })
1997
1998 {:ok, a3} = CommonAPI.post(u3, %{status: "Status", visibility: "private"})
1999
2000 {:ok, r3_1} =
2001 CommonAPI.post(u1, %{
2002 status: "@#{u3.nickname} reply from u1 to u3",
2003 in_reply_to_status_id: a3.id,
2004 visibility: "private"
2005 })
2006
2007 {:ok, r3_2} =
2008 CommonAPI.post(u2, %{
2009 status: "@#{u3.nickname} reply from u2 to u3",
2010 in_reply_to_status_id: a3.id,
2011 visibility: "private"
2012 })
2013
2014 {:ok, a4} = CommonAPI.post(u4, %{status: "Status", visibility: "private"})
2015
2016 {:ok, r4_1} =
2017 CommonAPI.post(u1, %{
2018 status: "@#{u4.nickname} reply from u1 to u4",
2019 in_reply_to_status_id: a4.id,
2020 visibility: "private"
2021 })
2022
2023 {:ok,
2024 users: %{u1: u1, u2: u2, u3: u3, u4: u4},
2025 activities: %{a1: a1.id, a2: a2.id, a3: a3.id, a4: a4.id},
2026 u1: %{r1: r1_1.id, r2: r1_2.id, r3: r1_3.id},
2027 u2: %{r1: r2_1.id, r2: r2_2.id},
2028 u3: %{r1: r3_1.id, r2: r3_2.id},
2029 u4: %{r1: r4_1.id}}
2030 end
2031
2032 describe "maybe_update_follow_information/1" do
2033 setup do
2034 clear_config([:instance, :external_user_synchronization], true)
2035
2036 user = %{
2037 local: false,
2038 ap_id: "https://gensokyo.2hu/users/raymoo",
2039 following_address: "https://gensokyo.2hu/users/following",
2040 follower_address: "https://gensokyo.2hu/users/followers",
2041 type: "Person"
2042 }
2043
2044 %{user: user}
2045 end
2046
2047 test "logs an error when it can't fetch the info", %{user: user} do
2048 assert capture_log(fn ->
2049 ActivityPub.maybe_update_follow_information(user)
2050 end) =~ "Follower/Following counter update for #{user.ap_id} failed"
2051 end
2052
2053 test "just returns the input if the user type is Application", %{
2054 user: user
2055 } do
2056 user =
2057 user
2058 |> Map.put(:type, "Application")
2059
2060 refute capture_log(fn ->
2061 assert ^user = ActivityPub.maybe_update_follow_information(user)
2062 end) =~ "Follower/Following counter update for #{user.ap_id} failed"
2063 end
2064
2065 test "it just returns the input if the user has no following/follower addresses", %{
2066 user: user
2067 } do
2068 user =
2069 user
2070 |> Map.put(:following_address, nil)
2071 |> Map.put(:follower_address, nil)
2072
2073 refute capture_log(fn ->
2074 assert ^user = ActivityPub.maybe_update_follow_information(user)
2075 end) =~ "Follower/Following counter update for #{user.ap_id} failed"
2076 end
2077 end
2078
2079 describe "global activity expiration" do
2080 setup do: clear_config([:mrf, :policies])
2081
2082 test "creates an activity expiration for local Create activities" do
2083 Pleroma.Config.put(
2084 [:mrf, :policies],
2085 Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy
2086 )
2087
2088 {:ok, %{id: id_create}} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
2089 {:ok, _follow} = ActivityBuilder.insert(%{"type" => "Follow", "context" => "3hu"})
2090
2091 assert [%{activity_id: ^id_create}] = Pleroma.ActivityExpiration |> Repo.all()
2092 end
2093 end
2094
2095 describe "handling of clashing nicknames" do
2096 test "renames an existing user with a clashing nickname and a different ap id" do
2097 orig_user =
2098 insert(
2099 :user,
2100 local: false,
2101 nickname: "admin@mastodon.example.org",
2102 ap_id: "http://mastodon.example.org/users/harinezumigari"
2103 )
2104
2105 %{
2106 nickname: orig_user.nickname,
2107 ap_id: orig_user.ap_id <> "part_2"
2108 }
2109 |> ActivityPub.maybe_handle_clashing_nickname()
2110
2111 user = User.get_by_id(orig_user.id)
2112
2113 assert user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
2114 end
2115
2116 test "does nothing with a clashing nickname and the same ap id" do
2117 orig_user =
2118 insert(
2119 :user,
2120 local: false,
2121 nickname: "admin@mastodon.example.org",
2122 ap_id: "http://mastodon.example.org/users/harinezumigari"
2123 )
2124
2125 %{
2126 nickname: orig_user.nickname,
2127 ap_id: orig_user.ap_id
2128 }
2129 |> ActivityPub.maybe_handle_clashing_nickname()
2130
2131 user = User.get_by_id(orig_user.id)
2132
2133 assert user.nickname == orig_user.nickname
2134 end
2135 end
2136 end