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