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