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