a6fd35edeaf45769650a6abaacc85a256b64b3e0
[akkoma] / test / user_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.UserTest do
6 alias Pleroma.Activity
7 alias Pleroma.Builders.UserBuilder
8 alias Pleroma.Repo
9 alias Pleroma.User
10 alias Pleroma.Web.CommonAPI
11
12 use Pleroma.DataCase
13
14 import Pleroma.Factory
15
16 setup_all do
17 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
18 :ok
19 end
20
21 describe "when tags are nil" do
22 test "tagging a user" do
23 user = insert(:user, %{tags: nil})
24 user = User.tag(user, ["cool", "dude"])
25
26 assert "cool" in user.tags
27 assert "dude" in user.tags
28 end
29
30 test "untagging a user" do
31 user = insert(:user, %{tags: nil})
32 user = User.untag(user, ["cool", "dude"])
33
34 assert user.tags == []
35 end
36 end
37
38 test "ap_id returns the activity pub id for the user" do
39 user = UserBuilder.build()
40
41 expected_ap_id = "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
42
43 assert expected_ap_id == User.ap_id(user)
44 end
45
46 test "ap_followers returns the followers collection for the user" do
47 user = UserBuilder.build()
48
49 expected_followers_collection = "#{User.ap_id(user)}/followers"
50
51 assert expected_followers_collection == User.ap_followers(user)
52 end
53
54 test "returns all pending follow requests" do
55 unlocked = insert(:user)
56 locked = insert(:user, %{info: %{locked: true}})
57 follower = insert(:user)
58
59 Pleroma.Web.TwitterAPI.TwitterAPI.follow(follower, %{"user_id" => unlocked.id})
60 Pleroma.Web.TwitterAPI.TwitterAPI.follow(follower, %{"user_id" => locked.id})
61
62 assert {:ok, []} = User.get_follow_requests(unlocked)
63 assert {:ok, [activity]} = User.get_follow_requests(locked)
64
65 assert activity
66 end
67
68 test "doesn't return already accepted or duplicate follow requests" do
69 locked = insert(:user, %{info: %{locked: true}})
70 pending_follower = insert(:user)
71 accepted_follower = insert(:user)
72
73 Pleroma.Web.TwitterAPI.TwitterAPI.follow(pending_follower, %{"user_id" => locked.id})
74 Pleroma.Web.TwitterAPI.TwitterAPI.follow(pending_follower, %{"user_id" => locked.id})
75 Pleroma.Web.TwitterAPI.TwitterAPI.follow(accepted_follower, %{"user_id" => locked.id})
76 User.maybe_follow(accepted_follower, locked)
77
78 assert {:ok, [activity]} = User.get_follow_requests(locked)
79 assert activity
80 end
81
82 test "follow_all follows mutliple users" do
83 user = insert(:user)
84 followed_zero = insert(:user)
85 followed_one = insert(:user)
86 followed_two = insert(:user)
87 blocked = insert(:user)
88 not_followed = insert(:user)
89 reverse_blocked = insert(:user)
90
91 {:ok, user} = User.block(user, blocked)
92 {:ok, reverse_blocked} = User.block(reverse_blocked, user)
93
94 {:ok, user} = User.follow(user, followed_zero)
95
96 {:ok, user} = User.follow_all(user, [followed_one, followed_two, blocked, reverse_blocked])
97
98 assert User.following?(user, followed_one)
99 assert User.following?(user, followed_two)
100 assert User.following?(user, followed_zero)
101 refute User.following?(user, not_followed)
102 refute User.following?(user, blocked)
103 refute User.following?(user, reverse_blocked)
104 end
105
106 test "follow_all follows mutliple users without duplicating" do
107 user = insert(:user)
108 followed_zero = insert(:user)
109 followed_one = insert(:user)
110 followed_two = insert(:user)
111
112 {:ok, user} = User.follow_all(user, [followed_zero, followed_one])
113 assert length(user.following) == 3
114
115 {:ok, user} = User.follow_all(user, [followed_one, followed_two])
116 assert length(user.following) == 4
117 end
118
119 test "follow takes a user and another user" do
120 user = insert(:user)
121 followed = insert(:user)
122
123 {:ok, user} = User.follow(user, followed)
124
125 user = Repo.get(User, user.id)
126
127 followed = User.get_by_ap_id(followed.ap_id)
128 assert followed.info.follower_count == 1
129
130 assert User.ap_followers(followed) in user.following
131 end
132
133 test "can't follow a deactivated users" do
134 user = insert(:user)
135 followed = insert(:user, info: %{deactivated: true})
136
137 {:error, _} = User.follow(user, followed)
138 end
139
140 test "can't follow a user who blocked us" do
141 blocker = insert(:user)
142 blockee = insert(:user)
143
144 {:ok, blocker} = User.block(blocker, blockee)
145
146 {:error, _} = User.follow(blockee, blocker)
147 end
148
149 test "local users do not automatically follow local locked accounts" do
150 follower = insert(:user, info: %{locked: true})
151 followed = insert(:user, info: %{locked: true})
152
153 {:ok, follower} = User.maybe_direct_follow(follower, followed)
154
155 refute User.following?(follower, followed)
156 end
157
158 # This is a somewhat useless test.
159 # test "following a remote user will ensure a websub subscription is present" do
160 # user = insert(:user)
161 # {:ok, followed} = OStatus.make_user("shp@social.heldscal.la")
162
163 # assert followed.local == false
164
165 # {:ok, user} = User.follow(user, followed)
166 # assert User.ap_followers(followed) in user.following
167
168 # query = from w in WebsubClientSubscription,
169 # where: w.topic == ^followed.info["topic"]
170 # websub = Repo.one(query)
171
172 # assert websub
173 # end
174
175 test "unfollow takes a user and another user" do
176 followed = insert(:user)
177 user = insert(:user, %{following: [User.ap_followers(followed)]})
178
179 {:ok, user, _activity} = User.unfollow(user, followed)
180
181 user = Repo.get(User, user.id)
182
183 assert user.following == []
184 end
185
186 test "unfollow doesn't unfollow yourself" do
187 user = insert(:user)
188
189 {:error, _} = User.unfollow(user, user)
190
191 user = Repo.get(User, user.id)
192 assert user.following == [user.ap_id]
193 end
194
195 test "test if a user is following another user" do
196 followed = insert(:user)
197 user = insert(:user, %{following: [User.ap_followers(followed)]})
198
199 assert User.following?(user, followed)
200 refute User.following?(followed, user)
201 end
202
203 describe "user registration" do
204 @full_user_data %{
205 bio: "A guy",
206 name: "my name",
207 nickname: "nick",
208 password: "test",
209 password_confirmation: "test",
210 email: "email@example.com"
211 }
212
213 test "it autofollows accounts that are set for it" do
214 user = insert(:user)
215 remote_user = insert(:user, %{local: false})
216
217 Pleroma.Config.put([:instance, :autofollowed_nicknames], [
218 user.nickname,
219 remote_user.nickname
220 ])
221
222 cng = User.register_changeset(%User{}, @full_user_data)
223
224 {:ok, registered_user} = User.register(cng)
225
226 assert User.following?(registered_user, user)
227 refute User.following?(registered_user, remote_user)
228
229 Pleroma.Config.put([:instance, :autofollowed_nicknames], [])
230 end
231
232 test "it sends a welcome message if it is set" do
233 welcome_user = insert(:user)
234
235 Pleroma.Config.put([:instance, :welcome_user_nickname], welcome_user.nickname)
236 Pleroma.Config.put([:instance, :welcome_message], "Hello, this is a cool site")
237
238 cng = User.register_changeset(%User{}, @full_user_data)
239 {:ok, registered_user} = User.register(cng)
240
241 activity = Repo.one(Pleroma.Activity)
242 assert registered_user.ap_id in activity.recipients
243 assert activity.data["object"]["content"] =~ "cool site"
244 assert activity.actor == welcome_user.ap_id
245
246 Pleroma.Config.put([:instance, :welcome_user_nickname], nil)
247 Pleroma.Config.put([:instance, :welcome_message], nil)
248 end
249
250 test "it requires an email, name, nickname and password, bio is optional" do
251 @full_user_data
252 |> Map.keys()
253 |> Enum.each(fn key ->
254 params = Map.delete(@full_user_data, key)
255 changeset = User.register_changeset(%User{}, params)
256
257 assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
258 end)
259 end
260
261 test "it restricts certain nicknames" do
262 [restricted_name | _] = Pleroma.Config.get([Pleroma.User, :restricted_nicknames])
263
264 assert is_bitstring(restricted_name)
265
266 params =
267 @full_user_data
268 |> Map.put(:nickname, restricted_name)
269
270 changeset = User.register_changeset(%User{}, params)
271
272 refute changeset.valid?
273 end
274
275 test "it sets the password_hash, ap_id and following fields" do
276 changeset = User.register_changeset(%User{}, @full_user_data)
277
278 assert changeset.valid?
279
280 assert is_binary(changeset.changes[:password_hash])
281 assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
282
283 assert changeset.changes[:following] == [
284 User.ap_followers(%User{nickname: @full_user_data.nickname})
285 ]
286
287 assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
288 end
289
290 test "it ensures info is not nil" do
291 changeset = User.register_changeset(%User{}, @full_user_data)
292
293 assert changeset.valid?
294
295 {:ok, user} =
296 changeset
297 |> Repo.insert()
298
299 refute is_nil(user.info)
300 end
301 end
302
303 describe "user registration, with :account_activation_required" do
304 @full_user_data %{
305 bio: "A guy",
306 name: "my name",
307 nickname: "nick",
308 password: "test",
309 password_confirmation: "test",
310 email: "email@example.com"
311 }
312
313 setup do
314 setting = Pleroma.Config.get([:instance, :account_activation_required])
315
316 unless setting do
317 Pleroma.Config.put([:instance, :account_activation_required], true)
318 on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
319 end
320
321 :ok
322 end
323
324 test "it creates unconfirmed user" do
325 changeset = User.register_changeset(%User{}, @full_user_data)
326 assert changeset.valid?
327
328 {:ok, user} = Repo.insert(changeset)
329
330 assert user.info.confirmation_pending
331 assert user.info.confirmation_token
332 end
333
334 test "it creates confirmed user if :confirmed option is given" do
335 changeset = User.register_changeset(%User{}, @full_user_data, confirmed: true)
336 assert changeset.valid?
337
338 {:ok, user} = Repo.insert(changeset)
339
340 refute user.info.confirmation_pending
341 refute user.info.confirmation_token
342 end
343 end
344
345 describe "get_or_fetch/1" do
346 test "gets an existing user by nickname" do
347 user = insert(:user)
348 fetched_user = User.get_or_fetch(user.nickname)
349
350 assert user == fetched_user
351 end
352
353 test "gets an existing user by ap_id" do
354 ap_id = "http://mastodon.example.org/users/admin"
355
356 user =
357 insert(
358 :user,
359 local: false,
360 nickname: "admin@mastodon.example.org",
361 ap_id: ap_id,
362 info: %{}
363 )
364
365 fetched_user = User.get_or_fetch(ap_id)
366 freshed_user = refresh_record(user)
367 assert freshed_user == fetched_user
368 end
369 end
370
371 describe "fetching a user from nickname or trying to build one" do
372 test "gets an existing user" do
373 user = insert(:user)
374 fetched_user = User.get_or_fetch_by_nickname(user.nickname)
375
376 assert user == fetched_user
377 end
378
379 test "gets an existing user, case insensitive" do
380 user = insert(:user, nickname: "nick")
381 fetched_user = User.get_or_fetch_by_nickname("NICK")
382
383 assert user == fetched_user
384 end
385
386 test "gets an existing user by fully qualified nickname" do
387 user = insert(:user)
388
389 fetched_user =
390 User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
391
392 assert user == fetched_user
393 end
394
395 test "gets an existing user by fully qualified nickname, case insensitive" do
396 user = insert(:user, nickname: "nick")
397 casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
398
399 fetched_user = User.get_or_fetch_by_nickname(casing_altered_fqn)
400
401 assert user == fetched_user
402 end
403
404 test "fetches an external user via ostatus if no user exists" do
405 fetched_user = User.get_or_fetch_by_nickname("shp@social.heldscal.la")
406 assert fetched_user.nickname == "shp@social.heldscal.la"
407 end
408
409 test "returns nil if no user could be fetched" do
410 fetched_user = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
411 assert fetched_user == nil
412 end
413
414 test "returns nil for nonexistant local user" do
415 fetched_user = User.get_or_fetch_by_nickname("nonexistant")
416 assert fetched_user == nil
417 end
418
419 test "updates an existing user, if stale" do
420 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
421
422 orig_user =
423 insert(
424 :user,
425 local: false,
426 nickname: "admin@mastodon.example.org",
427 ap_id: "http://mastodon.example.org/users/admin",
428 last_refreshed_at: a_week_ago,
429 info: %{}
430 )
431
432 assert orig_user.last_refreshed_at == a_week_ago
433
434 user = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
435 assert user.info.source_data["endpoints"]
436
437 refute user.last_refreshed_at == orig_user.last_refreshed_at
438 end
439 end
440
441 test "returns an ap_id for a user" do
442 user = insert(:user)
443
444 assert User.ap_id(user) ==
445 Pleroma.Web.Router.Helpers.o_status_url(
446 Pleroma.Web.Endpoint,
447 :feed_redirect,
448 user.nickname
449 )
450 end
451
452 test "returns an ap_followers link for a user" do
453 user = insert(:user)
454
455 assert User.ap_followers(user) ==
456 Pleroma.Web.Router.Helpers.o_status_url(
457 Pleroma.Web.Endpoint,
458 :feed_redirect,
459 user.nickname
460 ) <> "/followers"
461 end
462
463 describe "remote user creation changeset" do
464 @valid_remote %{
465 bio: "hello",
466 name: "Someone",
467 nickname: "a@b.de",
468 ap_id: "http...",
469 info: %{some: "info"},
470 avatar: %{some: "avatar"}
471 }
472
473 test "it confirms validity" do
474 cs = User.remote_user_creation(@valid_remote)
475 assert cs.valid?
476 end
477
478 test "it sets the follower_adress" do
479 cs = User.remote_user_creation(@valid_remote)
480 # remote users get a fake local follower address
481 assert cs.changes.follower_address ==
482 User.ap_followers(%User{nickname: @valid_remote[:nickname]})
483 end
484
485 test "it enforces the fqn format for nicknames" do
486 cs = User.remote_user_creation(%{@valid_remote | nickname: "bla"})
487 assert cs.changes.local == false
488 assert cs.changes.avatar
489 refute cs.valid?
490 end
491
492 test "it has required fields" do
493 [:name, :ap_id]
494 |> Enum.each(fn field ->
495 cs = User.remote_user_creation(Map.delete(@valid_remote, field))
496 refute cs.valid?
497 end)
498 end
499
500 test "it restricts some sizes" do
501 [bio: 5000, name: 100]
502 |> Enum.each(fn {field, size} ->
503 string = String.pad_leading(".", size)
504 cs = User.remote_user_creation(Map.put(@valid_remote, field, string))
505 assert cs.valid?
506
507 string = String.pad_leading(".", size + 1)
508 cs = User.remote_user_creation(Map.put(@valid_remote, field, string))
509 refute cs.valid?
510 end)
511 end
512 end
513
514 describe "followers and friends" do
515 test "gets all followers for a given user" do
516 user = insert(:user)
517 follower_one = insert(:user)
518 follower_two = insert(:user)
519 not_follower = insert(:user)
520
521 {:ok, follower_one} = User.follow(follower_one, user)
522 {:ok, follower_two} = User.follow(follower_two, user)
523
524 {:ok, res} = User.get_followers(user)
525
526 assert Enum.member?(res, follower_one)
527 assert Enum.member?(res, follower_two)
528 refute Enum.member?(res, not_follower)
529 end
530
531 test "gets all friends (followed users) for a given user" do
532 user = insert(:user)
533 followed_one = insert(:user)
534 followed_two = insert(:user)
535 not_followed = insert(:user)
536
537 {:ok, user} = User.follow(user, followed_one)
538 {:ok, user} = User.follow(user, followed_two)
539
540 {:ok, res} = User.get_friends(user)
541
542 followed_one = User.get_by_ap_id(followed_one.ap_id)
543 followed_two = User.get_by_ap_id(followed_two.ap_id)
544 assert Enum.member?(res, followed_one)
545 assert Enum.member?(res, followed_two)
546 refute Enum.member?(res, not_followed)
547 end
548 end
549
550 describe "updating note and follower count" do
551 test "it sets the info->note_count property" do
552 note = insert(:note)
553
554 user = User.get_by_ap_id(note.data["actor"])
555
556 assert user.info.note_count == 0
557
558 {:ok, user} = User.update_note_count(user)
559
560 assert user.info.note_count == 1
561 end
562
563 test "it increases the info->note_count property" do
564 note = insert(:note)
565 user = User.get_by_ap_id(note.data["actor"])
566
567 assert user.info.note_count == 0
568
569 {:ok, user} = User.increase_note_count(user)
570
571 assert user.info.note_count == 1
572
573 {:ok, user} = User.increase_note_count(user)
574
575 assert user.info.note_count == 2
576 end
577
578 test "it decreases the info->note_count property" do
579 note = insert(:note)
580 user = User.get_by_ap_id(note.data["actor"])
581
582 assert user.info.note_count == 0
583
584 {:ok, user} = User.increase_note_count(user)
585
586 assert user.info.note_count == 1
587
588 {:ok, user} = User.decrease_note_count(user)
589
590 assert user.info.note_count == 0
591
592 {:ok, user} = User.decrease_note_count(user)
593
594 assert user.info.note_count == 0
595 end
596
597 test "it sets the info->follower_count property" do
598 user = insert(:user)
599 follower = insert(:user)
600
601 User.follow(follower, user)
602
603 assert user.info.follower_count == 0
604
605 {:ok, user} = User.update_follower_count(user)
606
607 assert user.info.follower_count == 1
608 end
609 end
610
611 describe "follow_import" do
612 test "it imports user followings from list" do
613 [user1, user2, user3] = insert_list(3, :user)
614
615 identifiers = [
616 user2.ap_id,
617 user3.nickname
618 ]
619
620 result = User.follow_import(user1, identifiers)
621 assert is_list(result)
622 assert result == [user2, user3]
623 end
624 end
625
626 describe "mutes" do
627 test "it mutes people" do
628 user = insert(:user)
629 muted_user = insert(:user)
630
631 refute User.mutes?(user, muted_user)
632
633 {:ok, user} = User.mute(user, muted_user)
634
635 assert User.mutes?(user, muted_user)
636 end
637
638 test "it unmutes users" do
639 user = insert(:user)
640 muted_user = insert(:user)
641
642 {:ok, user} = User.mute(user, muted_user)
643 {:ok, user} = User.unmute(user, muted_user)
644
645 refute User.mutes?(user, muted_user)
646 end
647 end
648
649 describe "blocks" do
650 test "it blocks people" do
651 user = insert(:user)
652 blocked_user = insert(:user)
653
654 refute User.blocks?(user, blocked_user)
655
656 {:ok, user} = User.block(user, blocked_user)
657
658 assert User.blocks?(user, blocked_user)
659 end
660
661 test "it unblocks users" do
662 user = insert(:user)
663 blocked_user = insert(:user)
664
665 {:ok, user} = User.block(user, blocked_user)
666 {:ok, user} = User.unblock(user, blocked_user)
667
668 refute User.blocks?(user, blocked_user)
669 end
670
671 test "blocks tear down cyclical follow relationships" do
672 blocker = insert(:user)
673 blocked = insert(:user)
674
675 {:ok, blocker} = User.follow(blocker, blocked)
676 {:ok, blocked} = User.follow(blocked, blocker)
677
678 assert User.following?(blocker, blocked)
679 assert User.following?(blocked, blocker)
680
681 {:ok, blocker} = User.block(blocker, blocked)
682 blocked = Repo.get(User, blocked.id)
683
684 assert User.blocks?(blocker, blocked)
685
686 refute User.following?(blocker, blocked)
687 refute User.following?(blocked, blocker)
688 end
689
690 test "blocks tear down blocker->blocked follow relationships" do
691 blocker = insert(:user)
692 blocked = insert(:user)
693
694 {:ok, blocker} = User.follow(blocker, blocked)
695
696 assert User.following?(blocker, blocked)
697 refute User.following?(blocked, blocker)
698
699 {:ok, blocker} = User.block(blocker, blocked)
700 blocked = Repo.get(User, blocked.id)
701
702 assert User.blocks?(blocker, blocked)
703
704 refute User.following?(blocker, blocked)
705 refute User.following?(blocked, blocker)
706 end
707
708 test "blocks tear down blocked->blocker follow relationships" do
709 blocker = insert(:user)
710 blocked = insert(:user)
711
712 {:ok, blocked} = User.follow(blocked, blocker)
713
714 refute User.following?(blocker, blocked)
715 assert User.following?(blocked, blocker)
716
717 {:ok, blocker} = User.block(blocker, blocked)
718 blocked = Repo.get(User, blocked.id)
719
720 assert User.blocks?(blocker, blocked)
721
722 refute User.following?(blocker, blocked)
723 refute User.following?(blocked, blocker)
724 end
725 end
726
727 describe "domain blocking" do
728 test "blocks domains" do
729 user = insert(:user)
730 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
731
732 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
733
734 assert User.blocks?(user, collateral_user)
735 end
736
737 test "unblocks domains" do
738 user = insert(:user)
739 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
740
741 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
742 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
743
744 refute User.blocks?(user, collateral_user)
745 end
746 end
747
748 describe "blocks_import" do
749 test "it imports user blocks from list" do
750 [user1, user2, user3] = insert_list(3, :user)
751
752 identifiers = [
753 user2.ap_id,
754 user3.nickname
755 ]
756
757 result = User.blocks_import(user1, identifiers)
758 assert is_list(result)
759 assert result == [user2, user3]
760 end
761 end
762
763 test "get recipients from activity" do
764 actor = insert(:user)
765 user = insert(:user, local: true)
766 user_two = insert(:user, local: false)
767 addressed = insert(:user, local: true)
768 addressed_remote = insert(:user, local: false)
769
770 {:ok, activity} =
771 CommonAPI.post(actor, %{
772 "status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
773 })
774
775 assert Enum.map([actor, addressed], & &1.ap_id) --
776 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
777
778 {:ok, user} = User.follow(user, actor)
779 {:ok, _user_two} = User.follow(user_two, actor)
780 recipients = User.get_recipients_from_activity(activity)
781 assert length(recipients) == 3
782 assert user in recipients
783 assert addressed in recipients
784 end
785
786 test ".deactivate can de-activate then re-activate a user" do
787 user = insert(:user)
788 assert false == user.info.deactivated
789 {:ok, user} = User.deactivate(user)
790 assert true == user.info.deactivated
791 {:ok, user} = User.deactivate(user, false)
792 assert false == user.info.deactivated
793 end
794
795 test ".delete_user_activities deletes all create activities" do
796 user = insert(:user)
797
798 {:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
799 {:ok, _} = User.delete_user_activities(user)
800
801 # TODO: Remove favorites, repeats, delete activities.
802 refute Activity.get_by_id(activity.id)
803 end
804
805 test ".delete deactivates a user, all follow relationships and all create activities" do
806 user = insert(:user)
807 followed = insert(:user)
808 follower = insert(:user)
809
810 {:ok, user} = User.follow(user, followed)
811 {:ok, follower} = User.follow(follower, user)
812
813 {:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
814 {:ok, activity_two} = CommonAPI.post(follower, %{"status" => "3hu"})
815
816 {:ok, _, _} = CommonAPI.favorite(activity_two.id, user)
817 {:ok, _, _} = CommonAPI.favorite(activity.id, follower)
818 {:ok, _, _} = CommonAPI.repeat(activity.id, follower)
819
820 {:ok, _} = User.delete(user)
821
822 followed = Repo.get(User, followed.id)
823 follower = Repo.get(User, follower.id)
824 user = Repo.get(User, user.id)
825
826 assert user.info.deactivated
827
828 refute User.following?(user, followed)
829 refute User.following?(followed, follower)
830
831 # TODO: Remove favorites, repeats, delete activities.
832
833 refute Repo.get(Activity, activity.id)
834 end
835
836 test "get_public_key_for_ap_id fetches a user that's not in the db" do
837 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
838 end
839
840 test "insert or update a user from given data" do
841 user = insert(:user, %{nickname: "nick@name.de"})
842 data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname}
843
844 assert {:ok, %User{}} = User.insert_or_update_user(data)
845 end
846
847 describe "per-user rich-text filtering" do
848 test "html_filter_policy returns default policies, when rich-text is enabled" do
849 user = insert(:user)
850
851 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
852 end
853
854 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
855 user = insert(:user, %{info: %{no_rich_text: true}})
856
857 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
858 end
859 end
860
861 describe "caching" do
862 test "invalidate_cache works" do
863 user = insert(:user)
864 _user_info = User.get_cached_user_info(user)
865
866 User.invalidate_cache(user)
867
868 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
869 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
870 {:ok, nil} = Cachex.get(:user_cache, "user_info:#{user.id}")
871 end
872
873 test "User.delete() plugs any possible zombie objects" do
874 user = insert(:user)
875
876 {:ok, _} = User.delete(user)
877
878 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
879
880 assert cached_user != user
881
882 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
883
884 assert cached_user != user
885 end
886 end
887
888 describe "User.search" do
889 test "finds a user by full or partial nickname" do
890 user = insert(:user, %{nickname: "john"})
891
892 Enum.each(["john", "jo", "j"], fn query ->
893 assert user ==
894 User.search(query)
895 |> List.first()
896 |> Map.put(:search_rank, nil)
897 |> Map.put(:search_type, nil)
898 end)
899 end
900
901 test "finds a user by full or partial name" do
902 user = insert(:user, %{name: "John Doe"})
903
904 Enum.each(["John Doe", "JOHN", "doe", "j d", "j", "d"], fn query ->
905 assert user ==
906 User.search(query)
907 |> List.first()
908 |> Map.put(:search_rank, nil)
909 |> Map.put(:search_type, nil)
910 end)
911 end
912
913 test "finds users, preferring nickname matches over name matches" do
914 u1 = insert(:user, %{name: "lain", nickname: "nick1"})
915 u2 = insert(:user, %{nickname: "lain", name: "nick1"})
916
917 assert [u2.id, u1.id] == Enum.map(User.search("lain"), & &1.id)
918 end
919
920 test "finds users, considering density of matched tokens" do
921 u1 = insert(:user, %{name: "Bar Bar plus Word Word"})
922 u2 = insert(:user, %{name: "Word Word Bar Bar Bar"})
923
924 assert [u2.id, u1.id] == Enum.map(User.search("bar word"), & &1.id)
925 end
926
927 test "finds users, ranking by similarity" do
928 u1 = insert(:user, %{name: "lain"})
929 _u2 = insert(:user, %{name: "ean"})
930 u3 = insert(:user, %{name: "ebn", nickname: "lain@mastodon.social"})
931 u4 = insert(:user, %{nickname: "lain@pleroma.soykaf.com"})
932
933 assert [u4.id, u3.id, u1.id] == Enum.map(User.search("lain@ple"), & &1.id)
934 end
935
936 test "finds users, handling misspelled requests" do
937 u1 = insert(:user, %{name: "lain"})
938
939 assert [u1.id] == Enum.map(User.search("laiin"), & &1.id)
940 end
941
942 test "finds users, boosting ranks of friends and followers" do
943 u1 = insert(:user)
944 u2 = insert(:user, %{name: "Doe"})
945 follower = insert(:user, %{name: "Doe"})
946 friend = insert(:user, %{name: "Doe"})
947
948 {:ok, follower} = User.follow(follower, u1)
949 {:ok, u1} = User.follow(u1, friend)
950
951 assert [friend.id, follower.id, u2.id] --
952 Enum.map(User.search("doe", resolve: false, for_user: u1), & &1.id) == []
953 end
954
955 test "finds a user whose name is nil" do
956 _user = insert(:user, %{name: "notamatch", nickname: "testuser@pleroma.amplifie.red"})
957 user_two = insert(:user, %{name: nil, nickname: "lain@pleroma.soykaf.com"})
958
959 assert user_two ==
960 User.search("lain@pleroma.soykaf.com")
961 |> List.first()
962 |> Map.put(:search_rank, nil)
963 |> Map.put(:search_type, nil)
964 end
965
966 test "does not yield false-positive matches" do
967 insert(:user, %{name: "John Doe"})
968
969 Enum.each(["mary", "a", ""], fn query ->
970 assert [] == User.search(query)
971 end)
972 end
973
974 test "works with URIs" do
975 results = User.search("http://mastodon.example.org/users/admin", resolve: true)
976 result = results |> List.first()
977
978 user = User.get_by_ap_id("http://mastodon.example.org/users/admin")
979
980 assert length(results) == 1
981 assert user == result |> Map.put(:search_rank, nil) |> Map.put(:search_type, nil)
982 end
983 end
984
985 test "auth_active?/1 works correctly" do
986 Pleroma.Config.put([:instance, :account_activation_required], true)
987
988 local_user = insert(:user, local: true, info: %{confirmation_pending: true})
989 confirmed_user = insert(:user, local: true, info: %{confirmation_pending: false})
990 remote_user = insert(:user, local: false)
991
992 refute User.auth_active?(local_user)
993 assert User.auth_active?(confirmed_user)
994 assert User.auth_active?(remote_user)
995
996 Pleroma.Config.put([:instance, :account_activation_required], false)
997 end
998
999 describe "superuser?/1" do
1000 test "returns false for unprivileged users" do
1001 user = insert(:user, local: true)
1002
1003 refute User.superuser?(user)
1004 end
1005
1006 test "returns false for remote users" do
1007 user = insert(:user, local: false)
1008 remote_admin_user = insert(:user, local: false, info: %{is_admin: true})
1009
1010 refute User.superuser?(user)
1011 refute User.superuser?(remote_admin_user)
1012 end
1013
1014 test "returns true for local moderators" do
1015 user = insert(:user, local: true, info: %{is_moderator: true})
1016
1017 assert User.superuser?(user)
1018 end
1019
1020 test "returns true for local admins" do
1021 user = insert(:user, local: true, info: %{is_admin: true})
1022
1023 assert User.superuser?(user)
1024 end
1025 end
1026
1027 describe "visible_for?/2" do
1028 test "returns true when the account is itself" do
1029 user = insert(:user, local: true)
1030
1031 assert User.visible_for?(user, user)
1032 end
1033
1034 test "returns false when the account is unauthenticated and auth is required" do
1035 Pleroma.Config.put([:instance, :account_activation_required], true)
1036
1037 user = insert(:user, local: true, info: %{confirmation_pending: true})
1038 other_user = insert(:user, local: true)
1039
1040 refute User.visible_for?(user, other_user)
1041
1042 Pleroma.Config.put([:instance, :account_activation_required], false)
1043 end
1044
1045 test "returns true when the account is unauthenticated and auth is not required" do
1046 user = insert(:user, local: true, info: %{confirmation_pending: true})
1047 other_user = insert(:user, local: true)
1048
1049 assert User.visible_for?(user, other_user)
1050 end
1051
1052 test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
1053 Pleroma.Config.put([:instance, :account_activation_required], true)
1054
1055 user = insert(:user, local: true, info: %{confirmation_pending: true})
1056 other_user = insert(:user, local: true, info: %{is_admin: true})
1057
1058 assert User.visible_for?(user, other_user)
1059
1060 Pleroma.Config.put([:instance, :account_activation_required], false)
1061 end
1062 end
1063
1064 describe "parse_bio/2" do
1065 test "preserves hosts in user links text" do
1066 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1067 user = insert(:user)
1068 bio = "A.k.a. @nick@domain.com"
1069
1070 expected_text =
1071 "A.k.a. <span class='h-card'><a data-user='#{remote_user.id}' class='u-url mention' href='#{
1072 remote_user.ap_id
1073 }'>" <> "@<span>nick@domain.com</span></a></span>"
1074
1075 assert expected_text == User.parse_bio(bio, user)
1076 end
1077
1078 test "Adds rel=me on linkbacked urls" do
1079 user = insert(:user, ap_id: "http://social.example.org/users/lain")
1080
1081 bio = "http://example.org/rel_me/null"
1082 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1083 assert expected_text == User.parse_bio(bio, user)
1084
1085 bio = "http://example.org/rel_me/link"
1086 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1087 assert expected_text == User.parse_bio(bio, user)
1088
1089 bio = "http://example.org/rel_me/anchor"
1090 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1091 assert expected_text == User.parse_bio(bio, user)
1092 end
1093 end
1094
1095 test "bookmarks" do
1096 user = insert(:user)
1097
1098 {:ok, activity1} =
1099 CommonAPI.post(user, %{
1100 "status" => "heweoo!"
1101 })
1102
1103 id1 = activity1.data["object"]["id"]
1104
1105 {:ok, activity2} =
1106 CommonAPI.post(user, %{
1107 "status" => "heweoo!"
1108 })
1109
1110 id2 = activity2.data["object"]["id"]
1111
1112 assert {:ok, user_state1} = User.bookmark(user, id1)
1113 assert user_state1.bookmarks == [id1]
1114
1115 assert {:ok, user_state2} = User.unbookmark(user, id1)
1116 assert user_state2.bookmarks == []
1117
1118 assert {:ok, user_state3} = User.bookmark(user, id2)
1119 assert user_state3.bookmarks == [id2]
1120 end
1121 end