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