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