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