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