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