Merge branch 'bugfix/activitypub-reserialization' 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.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 end
882
883 test "auth_active?/1 works correctly" do
884 Pleroma.Config.put([:instance, :account_activation_required], true)
885
886 local_user = insert(:user, local: true, info: %{confirmation_pending: true})
887 confirmed_user = insert(:user, local: true, info: %{confirmation_pending: false})
888 remote_user = insert(:user, local: false)
889
890 refute User.auth_active?(local_user)
891 assert User.auth_active?(confirmed_user)
892 assert User.auth_active?(remote_user)
893
894 Pleroma.Config.put([:instance, :account_activation_required], false)
895 end
896
897 describe "superuser?/1" do
898 test "returns false for unprivileged users" do
899 user = insert(:user, local: true)
900
901 refute User.superuser?(user)
902 end
903
904 test "returns false for remote users" do
905 user = insert(:user, local: false)
906 remote_admin_user = insert(:user, local: false, info: %{is_admin: true})
907
908 refute User.superuser?(user)
909 refute User.superuser?(remote_admin_user)
910 end
911
912 test "returns true for local moderators" do
913 user = insert(:user, local: true, info: %{is_moderator: true})
914
915 assert User.superuser?(user)
916 end
917
918 test "returns true for local admins" do
919 user = insert(:user, local: true, info: %{is_admin: true})
920
921 assert User.superuser?(user)
922 end
923 end
924
925 describe "visible_for?/2" do
926 test "returns true when the account is itself" do
927 user = insert(:user, local: true)
928
929 assert User.visible_for?(user, user)
930 end
931
932 test "returns false when the account is unauthenticated and auth is required" do
933 Pleroma.Config.put([:instance, :account_activation_required], true)
934
935 user = insert(:user, local: true, info: %{confirmation_pending: true})
936 other_user = insert(:user, local: true)
937
938 refute User.visible_for?(user, other_user)
939
940 Pleroma.Config.put([:instance, :account_activation_required], false)
941 end
942
943 test "returns true when the account is unauthenticated and auth is not required" do
944 user = insert(:user, local: true, info: %{confirmation_pending: true})
945 other_user = insert(:user, local: true)
946
947 assert User.visible_for?(user, other_user)
948 end
949
950 test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
951 Pleroma.Config.put([:instance, :account_activation_required], true)
952
953 user = insert(:user, local: true, info: %{confirmation_pending: true})
954 other_user = insert(:user, local: true, info: %{is_admin: true})
955
956 assert User.visible_for?(user, other_user)
957
958 Pleroma.Config.put([:instance, :account_activation_required], false)
959 end
960 end
961
962 describe "parse_bio/2" do
963 test "preserves hosts in user links text" do
964 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
965 user = insert(:user)
966 bio = "A.k.a. @nick@domain.com"
967
968 expected_text =
969 "A.k.a. <span class='h-card'><a data-user='#{remote_user.id}' class='u-url mention' href='#{
970 remote_user.ap_id
971 }'>" <> "@<span>nick@domain.com</span></a></span>"
972
973 assert expected_text == User.parse_bio(bio, user)
974 end
975 end
976
977 test "bookmarks" do
978 user = insert(:user)
979
980 {:ok, activity1} =
981 CommonAPI.post(user, %{
982 "status" => "heweoo!"
983 })
984
985 id1 = activity1.data["object"]["id"]
986
987 {:ok, activity2} =
988 CommonAPI.post(user, %{
989 "status" => "heweoo!"
990 })
991
992 id2 = activity2.data["object"]["id"]
993
994 assert {:ok, user_state1} = User.bookmark(user, id1)
995 assert user_state1.bookmarks == [id1]
996
997 assert {:ok, user_state2} = User.unbookmark(user, id1)
998 assert user_state2.bookmarks == []
999
1000 assert {:ok, user_state3} = User.bookmark(user, id2)
1001 assert user_state3.bookmarks == [id2]
1002 end
1003 end