1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.UserTest do
7 alias Pleroma.Builders.UserBuilder
10 alias Pleroma.Tests.ObanHelpers
12 alias Pleroma.Web.ActivityPub.ActivityPub
13 alias Pleroma.Web.CommonAPI
16 use Oban.Testing, repo: Pleroma.Repo
18 import Pleroma.Factory
19 import ExUnit.CaptureLog
20 import Swoosh.TestAssertions
23 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
27 setup do: clear_config([:instance, :account_activation_required])
29 describe "service actors" do
30 test "returns updated invisible actor" do
31 uri = "#{Pleroma.Web.Endpoint.url()}/relay"
32 followers_uri = "#{uri}/followers"
41 follower_address: followers_uri
45 actor = User.get_or_create_service_actor_by_ap_id(uri, "relay")
46 assert actor.invisible
49 test "returns relay user" do
50 uri = "#{Pleroma.Web.Endpoint.url()}/relay"
51 followers_uri = "#{uri}/followers"
58 follower_address: ^followers_uri
59 } = User.get_or_create_service_actor_by_ap_id(uri, "relay")
61 assert capture_log(fn ->
62 refute User.get_or_create_service_actor_by_ap_id("/relay", "relay")
63 end) =~ "Cannot create service actor:"
66 test "returns invisible actor" do
67 uri = "#{Pleroma.Web.Endpoint.url()}/internal/fetch-test"
68 followers_uri = "#{uri}/followers"
69 user = User.get_or_create_service_actor_by_ap_id(uri, "internal.fetch-test")
72 nickname: "internal.fetch-test",
76 follower_address: ^followers_uri
79 user2 = User.get_or_create_service_actor_by_ap_id(uri, "internal.fetch-test")
80 assert user.id == user2.id
84 describe "AP ID user relationships" do
86 {:ok, user: insert(:user)}
89 test "outgoing_relationships_ap_ids/1", %{user: user} do
90 rel_types = [:block, :mute, :notification_mute, :reblog_mute, :inverse_subscription]
98 insert_list(2, :user_relationship, %{source: user, relationship_type: rel_type})
100 ap_ids = Enum.map(rel_records, fn rr -> Repo.preload(rr, :target).target.ap_id end)
101 {rel_type, Enum.sort(ap_ids)}
105 assert ap_ids_by_rel[:block] == Enum.sort(User.blocked_users_ap_ids(user))
106 assert ap_ids_by_rel[:block] == Enum.sort(Enum.map(User.blocked_users(user), & &1.ap_id))
108 assert ap_ids_by_rel[:mute] == Enum.sort(User.muted_users_ap_ids(user))
109 assert ap_ids_by_rel[:mute] == Enum.sort(Enum.map(User.muted_users(user), & &1.ap_id))
111 assert ap_ids_by_rel[:notification_mute] ==
112 Enum.sort(User.notification_muted_users_ap_ids(user))
114 assert ap_ids_by_rel[:notification_mute] ==
115 Enum.sort(Enum.map(User.notification_muted_users(user), & &1.ap_id))
117 assert ap_ids_by_rel[:reblog_mute] == Enum.sort(User.reblog_muted_users_ap_ids(user))
119 assert ap_ids_by_rel[:reblog_mute] ==
120 Enum.sort(Enum.map(User.reblog_muted_users(user), & &1.ap_id))
122 assert ap_ids_by_rel[:inverse_subscription] == Enum.sort(User.subscriber_users_ap_ids(user))
124 assert ap_ids_by_rel[:inverse_subscription] ==
125 Enum.sort(Enum.map(User.subscriber_users(user), & &1.ap_id))
127 outgoing_relationships_ap_ids = User.outgoing_relationships_ap_ids(user, rel_types)
129 assert ap_ids_by_rel ==
130 Enum.into(outgoing_relationships_ap_ids, %{}, fn {k, v} -> {k, Enum.sort(v)} end)
134 describe "when tags are nil" do
135 test "tagging a user" do
136 user = insert(:user, %{tags: nil})
137 user = User.tag(user, ["cool", "dude"])
139 assert "cool" in user.tags
140 assert "dude" in user.tags
143 test "untagging a user" do
144 user = insert(:user, %{tags: nil})
145 user = User.untag(user, ["cool", "dude"])
147 assert user.tags == []
151 test "ap_id returns the activity pub id for the user" do
152 user = UserBuilder.build()
154 expected_ap_id = "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
156 assert expected_ap_id == User.ap_id(user)
159 test "ap_followers returns the followers collection for the user" do
160 user = UserBuilder.build()
162 expected_followers_collection = "#{User.ap_id(user)}/followers"
164 assert expected_followers_collection == User.ap_followers(user)
167 test "ap_following returns the following collection for the user" do
168 user = UserBuilder.build()
170 expected_followers_collection = "#{User.ap_id(user)}/following"
172 assert expected_followers_collection == User.ap_following(user)
175 test "returns all pending follow requests" do
176 unlocked = insert(:user)
177 locked = insert(:user, locked: true)
178 follower = insert(:user)
180 CommonAPI.follow(follower, unlocked)
181 CommonAPI.follow(follower, locked)
183 assert [] = User.get_follow_requests(unlocked)
184 assert [activity] = User.get_follow_requests(locked)
189 test "doesn't return already accepted or duplicate follow requests" do
190 locked = insert(:user, locked: true)
191 pending_follower = insert(:user)
192 accepted_follower = insert(:user)
194 CommonAPI.follow(pending_follower, locked)
195 CommonAPI.follow(pending_follower, locked)
196 CommonAPI.follow(accepted_follower, locked)
198 Pleroma.FollowingRelationship.update(accepted_follower, locked, :follow_accept)
200 assert [^pending_follower] = User.get_follow_requests(locked)
203 test "doesn't return follow requests for deactivated accounts" do
204 locked = insert(:user, locked: true)
205 pending_follower = insert(:user, %{deactivated: true})
207 CommonAPI.follow(pending_follower, locked)
209 assert true == pending_follower.deactivated
210 assert [] = User.get_follow_requests(locked)
213 test "clears follow requests when requester is blocked" do
214 followed = insert(:user, locked: true)
215 follower = insert(:user)
217 CommonAPI.follow(follower, followed)
218 assert [_activity] = User.get_follow_requests(followed)
220 {:ok, _user_relationship} = User.block(followed, follower)
221 assert [] = User.get_follow_requests(followed)
224 test "follow_all follows mutliple users" do
226 followed_zero = insert(:user)
227 followed_one = insert(:user)
228 followed_two = insert(:user)
229 blocked = insert(:user)
230 not_followed = insert(:user)
231 reverse_blocked = insert(:user)
233 {:ok, _user_relationship} = User.block(user, blocked)
234 {:ok, _user_relationship} = User.block(reverse_blocked, user)
236 {:ok, user} = User.follow(user, followed_zero)
238 {:ok, user} = User.follow_all(user, [followed_one, followed_two, blocked, reverse_blocked])
240 assert User.following?(user, followed_one)
241 assert User.following?(user, followed_two)
242 assert User.following?(user, followed_zero)
243 refute User.following?(user, not_followed)
244 refute User.following?(user, blocked)
245 refute User.following?(user, reverse_blocked)
248 test "follow_all follows mutliple users without duplicating" do
250 followed_zero = insert(:user)
251 followed_one = insert(:user)
252 followed_two = insert(:user)
254 {:ok, user} = User.follow_all(user, [followed_zero, followed_one])
255 assert length(User.following(user)) == 3
257 {:ok, user} = User.follow_all(user, [followed_one, followed_two])
258 assert length(User.following(user)) == 4
261 test "follow takes a user and another user" do
263 followed = insert(:user)
265 {:ok, user} = User.follow(user, followed)
267 user = User.get_cached_by_id(user.id)
268 followed = User.get_cached_by_ap_id(followed.ap_id)
270 assert followed.follower_count == 1
271 assert user.following_count == 1
273 assert User.ap_followers(followed) in User.following(user)
276 test "can't follow a deactivated users" do
278 followed = insert(:user, %{deactivated: true})
280 {:error, _} = User.follow(user, followed)
283 test "can't follow a user who blocked us" do
284 blocker = insert(:user)
285 blockee = insert(:user)
287 {:ok, _user_relationship} = User.block(blocker, blockee)
289 {:error, _} = User.follow(blockee, blocker)
292 test "can't subscribe to a user who blocked us" do
293 blocker = insert(:user)
294 blocked = insert(:user)
296 {:ok, _user_relationship} = User.block(blocker, blocked)
298 {:error, _} = User.subscribe(blocked, blocker)
301 test "local users do not automatically follow local locked accounts" do
302 follower = insert(:user, locked: true)
303 followed = insert(:user, locked: true)
305 {:ok, follower} = User.maybe_direct_follow(follower, followed)
307 refute User.following?(follower, followed)
310 describe "unfollow/2" do
311 setup do: clear_config([:instance, :external_user_synchronization])
313 test "unfollow with syncronizes external user" do
314 Pleroma.Config.put([:instance, :external_user_synchronization], true)
319 follower_address: "http://localhost:4001/users/fuser1/followers",
320 following_address: "http://localhost:4001/users/fuser1/following",
321 ap_id: "http://localhost:4001/users/fuser1"
328 ap_id: "http://localhost:4001/users/fuser2",
329 follower_address: "http://localhost:4001/users/fuser2/followers",
330 following_address: "http://localhost:4001/users/fuser2/following"
333 {:ok, user} = User.follow(user, followed, :follow_accept)
335 {:ok, user, _activity} = User.unfollow(user, followed)
337 user = User.get_cached_by_id(user.id)
339 assert User.following(user) == []
342 test "unfollow takes a user and another user" do
343 followed = insert(:user)
346 {:ok, user} = User.follow(user, followed, :follow_accept)
348 assert User.following(user) == [user.follower_address, followed.follower_address]
350 {:ok, user, _activity} = User.unfollow(user, followed)
352 assert User.following(user) == [user.follower_address]
355 test "unfollow doesn't unfollow yourself" do
358 {:error, _} = User.unfollow(user, user)
360 assert User.following(user) == [user.follower_address]
364 test "test if a user is following another user" do
365 followed = insert(:user)
367 User.follow(user, followed, :follow_accept)
369 assert User.following?(user, followed)
370 refute User.following?(followed, user)
373 test "fetches correct profile for nickname beginning with number" do
374 # Use old-style integer ID to try to reproduce the problem
375 user = insert(:user, %{id: 1080})
376 user_with_numbers = insert(:user, %{nickname: "#{user.id}garbage"})
377 assert user_with_numbers == User.get_cached_by_nickname_or_id(user_with_numbers.nickname)
380 describe "user registration" do
386 password_confirmation: "test",
387 email: "email@example.com"
390 setup do: clear_config([:instance, :autofollowed_nicknames])
391 setup do: clear_config([:welcome])
392 setup do: clear_config([:instance, :account_activation_required])
394 test "it autofollows accounts that are set for it" do
396 remote_user = insert(:user, %{local: false})
398 Pleroma.Config.put([:instance, :autofollowed_nicknames], [
403 cng = User.register_changeset(%User{}, @full_user_data)
405 {:ok, registered_user} = User.register(cng)
407 assert User.following?(registered_user, user)
408 refute User.following?(registered_user, remote_user)
411 test "it sends a welcome message if it is set" do
412 welcome_user = insert(:user)
413 Pleroma.Config.put([:welcome, :direct_message, :enabled], true)
414 Pleroma.Config.put([:welcome, :direct_message, :sender_nickname], welcome_user.nickname)
415 Pleroma.Config.put([:welcome, :direct_message, :message], "Hello, this is a cool site")
417 Pleroma.Config.put([:welcome, :email, :enabled], true)
418 Pleroma.Config.put([:welcome, :email, :sender], welcome_user.email)
421 [:welcome, :email, :subject],
422 "Hello, welcome to cool site: <%= instance_name %>"
425 instance_name = Pleroma.Config.get([:instance, :name])
427 cng = User.register_changeset(%User{}, @full_user_data)
428 {:ok, registered_user} = User.register(cng)
429 ObanHelpers.perform_all()
431 activity = Repo.one(Pleroma.Activity)
432 assert registered_user.ap_id in activity.recipients
433 assert Object.normalize(activity).data["content"] =~ "cool site"
434 assert activity.actor == welcome_user.ap_id
437 from: {instance_name, welcome_user.email},
438 to: {registered_user.name, registered_user.email},
439 subject: "Hello, welcome to cool site: #{instance_name}",
440 html_body: "Welcome to #{instance_name}"
444 test "it sends a confirm email" do
445 Pleroma.Config.put([:instance, :account_activation_required], true)
447 cng = User.register_changeset(%User{}, @full_user_data)
448 {:ok, registered_user} = User.register(cng)
449 ObanHelpers.perform_all()
450 assert_email_sent(Pleroma.Emails.UserEmail.account_confirmation_email(registered_user))
453 test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do
454 Pleroma.Config.put([:instance, :account_activation_required], true)
458 |> Enum.each(fn key ->
459 params = Map.delete(@full_user_data, key)
460 changeset = User.register_changeset(%User{}, params)
462 assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
466 test "it requires an name, nickname and password, bio and email are optional when account_activation_required is disabled" do
467 Pleroma.Config.put([:instance, :account_activation_required], false)
471 |> Enum.each(fn key ->
472 params = Map.delete(@full_user_data, key)
473 changeset = User.register_changeset(%User{}, params)
475 assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid?
479 test "it restricts certain nicknames" do
480 [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
482 assert is_bitstring(restricted_name)
486 |> Map.put(:nickname, restricted_name)
488 changeset = User.register_changeset(%User{}, params)
490 refute changeset.valid?
493 test "it sets the password_hash and ap_id" do
494 changeset = User.register_changeset(%User{}, @full_user_data)
496 assert changeset.valid?
498 assert is_binary(changeset.changes[:password_hash])
499 assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
501 assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
505 describe "user registration, with :account_activation_required" do
511 password_confirmation: "test",
512 email: "email@example.com"
514 setup do: clear_config([:instance, :account_activation_required], true)
516 test "it sets the 'accepts_chat_messages' set to true" do
517 changeset = User.register_changeset(%User{}, @full_user_data)
518 assert changeset.valid?
520 {:ok, user} = Repo.insert(changeset)
522 assert user.accepts_chat_messages
525 test "it creates unconfirmed user" do
526 changeset = User.register_changeset(%User{}, @full_user_data)
527 assert changeset.valid?
529 {:ok, user} = Repo.insert(changeset)
531 assert user.confirmation_pending
532 assert user.confirmation_token
535 test "it creates confirmed user if :confirmed option is given" do
536 changeset = User.register_changeset(%User{}, @full_user_data, need_confirmation: false)
537 assert changeset.valid?
539 {:ok, user} = Repo.insert(changeset)
541 refute user.confirmation_pending
542 refute user.confirmation_token
546 describe "user registration, with :account_approval_required" do
552 password_confirmation: "test",
553 email: "email@example.com",
554 registration_reason: "I'm a cool guy :)"
556 setup do: clear_config([:instance, :account_approval_required], true)
558 test "it creates unapproved user" do
559 changeset = User.register_changeset(%User{}, @full_user_data)
560 assert changeset.valid?
562 {:ok, user} = Repo.insert(changeset)
564 assert user.approval_pending
565 assert user.registration_reason == "I'm a cool guy :)"
568 test "it restricts length of registration reason" do
569 reason_limit = Pleroma.Config.get([:instance, :registration_reason_length])
571 assert is_integer(reason_limit)
576 :registration_reason,
577 "Quia et nesciunt dolores numquam ipsam nisi sapiente soluta. Ullam repudiandae nisi quam porro officiis officiis ad. Consequatur animi velit ex quia. Odit voluptatem perferendis quia ut nisi. Dignissimos sit soluta atque aliquid dolorem ut dolorum ut. Labore voluptates iste iusto amet voluptatum earum. Ad fugit illum nam eos ut nemo. Pariatur ea fuga non aspernatur. Dignissimos debitis officia corporis est nisi ab et. Atque itaque alias eius voluptas minus. Accusamus numquam tempore occaecati in."
580 changeset = User.register_changeset(%User{}, params)
582 refute changeset.valid?
586 describe "get_or_fetch/1" do
587 test "gets an existing user by nickname" do
589 {:ok, fetched_user} = User.get_or_fetch(user.nickname)
591 assert user == fetched_user
594 test "gets an existing user by ap_id" do
595 ap_id = "http://mastodon.example.org/users/admin"
601 nickname: "admin@mastodon.example.org",
605 {:ok, fetched_user} = User.get_or_fetch(ap_id)
606 freshed_user = refresh_record(user)
607 assert freshed_user == fetched_user
611 describe "fetching a user from nickname or trying to build one" do
612 test "gets an existing user" do
614 {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
616 assert user == fetched_user
619 test "gets an existing user, case insensitive" do
620 user = insert(:user, nickname: "nick")
621 {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
623 assert user == fetched_user
626 test "gets an existing user by fully qualified nickname" do
629 {:ok, fetched_user} =
630 User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
632 assert user == fetched_user
635 test "gets an existing user by fully qualified nickname, case insensitive" do
636 user = insert(:user, nickname: "nick")
637 casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
639 {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
641 assert user == fetched_user
644 @tag capture_log: true
645 test "returns nil if no user could be fetched" do
646 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
647 assert fetched_user == "not found nonexistant@social.heldscal.la"
650 test "returns nil for nonexistant local user" do
651 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
652 assert fetched_user == "not found nonexistant"
655 test "updates an existing user, if stale" do
656 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
662 nickname: "admin@mastodon.example.org",
663 ap_id: "http://mastodon.example.org/users/admin",
664 last_refreshed_at: a_week_ago
667 assert orig_user.last_refreshed_at == a_week_ago
669 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
673 refute user.last_refreshed_at == orig_user.last_refreshed_at
676 test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
677 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
683 nickname: "admin@mastodon.example.org",
684 ap_id: "http://mastodon.example.org/users/harinezumigari",
685 last_refreshed_at: a_week_ago
688 assert orig_user.last_refreshed_at == a_week_ago
690 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
694 refute user.id == orig_user.id
696 orig_user = User.get_by_id(orig_user.id)
698 assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
701 @tag capture_log: true
702 test "it returns the old user if stale, but unfetchable" do
703 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
709 nickname: "admin@mastodon.example.org",
710 ap_id: "http://mastodon.example.org/users/raymoo",
711 last_refreshed_at: a_week_ago
714 assert orig_user.last_refreshed_at == a_week_ago
716 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/raymoo")
718 assert user.last_refreshed_at == orig_user.last_refreshed_at
722 test "returns an ap_id for a user" do
725 assert User.ap_id(user) ==
726 Pleroma.Web.Router.Helpers.user_feed_url(
727 Pleroma.Web.Endpoint,
733 test "returns an ap_followers link for a user" do
736 assert User.ap_followers(user) ==
737 Pleroma.Web.Router.Helpers.user_feed_url(
738 Pleroma.Web.Endpoint,
744 describe "remote user changeset" do
750 avatar: %{some: "avatar"}
752 setup do: clear_config([:instance, :user_bio_length])
753 setup do: clear_config([:instance, :user_name_length])
755 test "it confirms validity" do
756 cs = User.remote_user_changeset(@valid_remote)
760 test "it sets the follower_adress" do
761 cs = User.remote_user_changeset(@valid_remote)
762 # remote users get a fake local follower address
763 assert cs.changes.follower_address ==
764 User.ap_followers(%User{nickname: @valid_remote[:nickname]})
767 test "it enforces the fqn format for nicknames" do
768 cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})
769 assert Ecto.Changeset.get_field(cs, :local) == false
770 assert cs.changes.avatar
774 test "it has required fields" do
776 |> Enum.each(fn field ->
777 cs = User.remote_user_changeset(Map.delete(@valid_remote, field))
783 describe "followers and friends" do
784 test "gets all followers for a given user" do
786 follower_one = insert(:user)
787 follower_two = insert(:user)
788 not_follower = insert(:user)
790 {:ok, follower_one} = User.follow(follower_one, user)
791 {:ok, follower_two} = User.follow(follower_two, user)
793 res = User.get_followers(user)
795 assert Enum.member?(res, follower_one)
796 assert Enum.member?(res, follower_two)
797 refute Enum.member?(res, not_follower)
800 test "gets all friends (followed users) for a given user" do
802 followed_one = insert(:user)
803 followed_two = insert(:user)
804 not_followed = insert(:user)
806 {:ok, user} = User.follow(user, followed_one)
807 {:ok, user} = User.follow(user, followed_two)
809 res = User.get_friends(user)
811 followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
812 followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
813 assert Enum.member?(res, followed_one)
814 assert Enum.member?(res, followed_two)
815 refute Enum.member?(res, not_followed)
819 describe "updating note and follower count" do
820 test "it sets the note_count property" do
823 user = User.get_cached_by_ap_id(note.data["actor"])
825 assert user.note_count == 0
827 {:ok, user} = User.update_note_count(user)
829 assert user.note_count == 1
832 test "it increases the note_count property" do
834 user = User.get_cached_by_ap_id(note.data["actor"])
836 assert user.note_count == 0
838 {:ok, user} = User.increase_note_count(user)
840 assert user.note_count == 1
842 {:ok, user} = User.increase_note_count(user)
844 assert user.note_count == 2
847 test "it decreases the note_count property" do
849 user = User.get_cached_by_ap_id(note.data["actor"])
851 assert user.note_count == 0
853 {:ok, user} = User.increase_note_count(user)
855 assert user.note_count == 1
857 {:ok, user} = User.decrease_note_count(user)
859 assert user.note_count == 0
861 {:ok, user} = User.decrease_note_count(user)
863 assert user.note_count == 0
866 test "it sets the follower_count property" do
868 follower = insert(:user)
870 User.follow(follower, user)
872 assert user.follower_count == 0
874 {:ok, user} = User.update_follower_count(user)
876 assert user.follower_count == 1
880 describe "follow_import" do
881 test "it imports user followings from list" do
882 [user1, user2, user3] = insert_list(3, :user)
889 {:ok, job} = User.follow_import(user1, identifiers)
891 assert {:ok, result} = ObanHelpers.perform(job)
892 assert is_list(result)
893 assert result == [user2, user3]
898 test "it mutes people" do
900 muted_user = insert(:user)
902 refute User.mutes?(user, muted_user)
903 refute User.muted_notifications?(user, muted_user)
905 {:ok, _user_relationships} = User.mute(user, muted_user)
907 assert User.mutes?(user, muted_user)
908 assert User.muted_notifications?(user, muted_user)
911 test "it unmutes users" do
913 muted_user = insert(:user)
915 {:ok, _user_relationships} = User.mute(user, muted_user)
916 {:ok, _user_mute} = User.unmute(user, muted_user)
918 refute User.mutes?(user, muted_user)
919 refute User.muted_notifications?(user, muted_user)
922 test "it mutes user without notifications" do
924 muted_user = insert(:user)
926 refute User.mutes?(user, muted_user)
927 refute User.muted_notifications?(user, muted_user)
929 {:ok, _user_relationships} = User.mute(user, muted_user, false)
931 assert User.mutes?(user, muted_user)
932 refute User.muted_notifications?(user, muted_user)
937 test "it blocks people" do
939 blocked_user = insert(:user)
941 refute User.blocks?(user, blocked_user)
943 {:ok, _user_relationship} = User.block(user, blocked_user)
945 assert User.blocks?(user, blocked_user)
948 test "it unblocks users" do
950 blocked_user = insert(:user)
952 {:ok, _user_relationship} = User.block(user, blocked_user)
953 {:ok, _user_block} = User.unblock(user, blocked_user)
955 refute User.blocks?(user, blocked_user)
958 test "blocks tear down cyclical follow relationships" do
959 blocker = insert(:user)
960 blocked = insert(:user)
962 {:ok, blocker} = User.follow(blocker, blocked)
963 {:ok, blocked} = User.follow(blocked, blocker)
965 assert User.following?(blocker, blocked)
966 assert User.following?(blocked, blocker)
968 {:ok, _user_relationship} = User.block(blocker, blocked)
969 blocked = User.get_cached_by_id(blocked.id)
971 assert User.blocks?(blocker, blocked)
973 refute User.following?(blocker, blocked)
974 refute User.following?(blocked, blocker)
977 test "blocks tear down blocker->blocked follow relationships" do
978 blocker = insert(:user)
979 blocked = insert(:user)
981 {:ok, blocker} = User.follow(blocker, blocked)
983 assert User.following?(blocker, blocked)
984 refute User.following?(blocked, blocker)
986 {:ok, _user_relationship} = User.block(blocker, blocked)
987 blocked = User.get_cached_by_id(blocked.id)
989 assert User.blocks?(blocker, blocked)
991 refute User.following?(blocker, blocked)
992 refute User.following?(blocked, blocker)
995 test "blocks tear down blocked->blocker follow relationships" do
996 blocker = insert(:user)
997 blocked = insert(:user)
999 {:ok, blocked} = User.follow(blocked, blocker)
1001 refute User.following?(blocker, blocked)
1002 assert User.following?(blocked, blocker)
1004 {:ok, _user_relationship} = User.block(blocker, blocked)
1005 blocked = User.get_cached_by_id(blocked.id)
1007 assert User.blocks?(blocker, blocked)
1009 refute User.following?(blocker, blocked)
1010 refute User.following?(blocked, blocker)
1013 test "blocks tear down blocked->blocker subscription relationships" do
1014 blocker = insert(:user)
1015 blocked = insert(:user)
1017 {:ok, _subscription} = User.subscribe(blocked, blocker)
1019 assert User.subscribed_to?(blocked, blocker)
1020 refute User.subscribed_to?(blocker, blocked)
1022 {:ok, _user_relationship} = User.block(blocker, blocked)
1024 assert User.blocks?(blocker, blocked)
1025 refute User.subscribed_to?(blocker, blocked)
1026 refute User.subscribed_to?(blocked, blocker)
1030 describe "domain blocking" do
1031 test "blocks domains" do
1032 user = insert(:user)
1033 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1035 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1037 assert User.blocks?(user, collateral_user)
1040 test "does not block domain with same end" do
1041 user = insert(:user)
1044 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1046 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1048 refute User.blocks?(user, collateral_user)
1051 test "does not block domain with same end if wildcard added" do
1052 user = insert(:user)
1055 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1057 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1059 refute User.blocks?(user, collateral_user)
1062 test "blocks domain with wildcard for subdomain" do
1063 user = insert(:user)
1065 user_from_subdomain =
1066 insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
1068 user_with_two_subdomains =
1070 ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
1073 user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1075 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1077 assert User.blocks?(user, user_from_subdomain)
1078 assert User.blocks?(user, user_with_two_subdomains)
1079 assert User.blocks?(user, user_domain)
1082 test "unblocks domains" do
1083 user = insert(:user)
1084 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1086 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1087 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
1089 refute User.blocks?(user, collateral_user)
1092 test "follows take precedence over domain blocks" do
1093 user = insert(:user)
1094 good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
1096 {:ok, user} = User.block_domain(user, "meanies.social")
1097 {:ok, user} = User.follow(user, good_eggo)
1099 refute User.blocks?(user, good_eggo)
1103 describe "blocks_import" do
1104 test "it imports user blocks from list" do
1105 [user1, user2, user3] = insert_list(3, :user)
1112 {:ok, job} = User.blocks_import(user1, identifiers)
1114 assert {:ok, result} = ObanHelpers.perform(job)
1115 assert is_list(result)
1116 assert result == [user2, user3]
1120 describe "get_recipients_from_activity" do
1121 test "works for announces" do
1122 actor = insert(:user)
1123 user = insert(:user, local: true)
1125 {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
1126 {:ok, announce} = CommonAPI.repeat(activity.id, user)
1128 recipients = User.get_recipients_from_activity(announce)
1130 assert user in recipients
1133 test "get recipients" do
1134 actor = insert(:user)
1135 user = insert(:user, local: true)
1136 user_two = insert(:user, local: false)
1137 addressed = insert(:user, local: true)
1138 addressed_remote = insert(:user, local: false)
1141 CommonAPI.post(actor, %{
1142 status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
1145 assert Enum.map([actor, addressed], & &1.ap_id) --
1146 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1148 {:ok, user} = User.follow(user, actor)
1149 {:ok, _user_two} = User.follow(user_two, actor)
1150 recipients = User.get_recipients_from_activity(activity)
1151 assert length(recipients) == 3
1152 assert user in recipients
1153 assert addressed in recipients
1156 test "has following" do
1157 actor = insert(:user)
1158 user = insert(:user)
1159 user_two = insert(:user)
1160 addressed = insert(:user, local: true)
1163 CommonAPI.post(actor, %{
1164 status: "hey @#{addressed.nickname}"
1167 assert Enum.map([actor, addressed], & &1.ap_id) --
1168 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1170 {:ok, _actor} = User.follow(actor, user)
1171 {:ok, _actor} = User.follow(actor, user_two)
1172 recipients = User.get_recipients_from_activity(activity)
1173 assert length(recipients) == 2
1174 assert addressed in recipients
1178 describe ".deactivate" do
1179 test "can de-activate then re-activate a user" do
1180 user = insert(:user)
1181 assert false == user.deactivated
1182 {:ok, user} = User.deactivate(user)
1183 assert true == user.deactivated
1184 {:ok, user} = User.deactivate(user, false)
1185 assert false == user.deactivated
1188 test "hide a user from followers" do
1189 user = insert(:user)
1190 user2 = insert(:user)
1192 {:ok, user} = User.follow(user, user2)
1193 {:ok, _user} = User.deactivate(user)
1195 user2 = User.get_cached_by_id(user2.id)
1197 assert user2.follower_count == 0
1198 assert [] = User.get_followers(user2)
1201 test "hide a user from friends" do
1202 user = insert(:user)
1203 user2 = insert(:user)
1205 {:ok, user2} = User.follow(user2, user)
1206 assert user2.following_count == 1
1207 assert User.following_count(user2) == 1
1209 {:ok, _user} = User.deactivate(user)
1211 user2 = User.get_cached_by_id(user2.id)
1213 assert refresh_record(user2).following_count == 0
1214 assert user2.following_count == 0
1215 assert User.following_count(user2) == 0
1216 assert [] = User.get_friends(user2)
1219 test "hide a user's statuses from timelines and notifications" do
1220 user = insert(:user)
1221 user2 = insert(:user)
1223 {:ok, user2} = User.follow(user2, user)
1225 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
1227 activity = Repo.preload(activity, :bookmark)
1229 [notification] = Pleroma.Notification.for_user(user2)
1230 assert notification.activity.id == activity.id
1232 assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
1234 assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
1235 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1239 {:ok, _user} = User.deactivate(user)
1241 assert [] == ActivityPub.fetch_public_activities(%{})
1242 assert [] == Pleroma.Notification.for_user(user2)
1245 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1251 describe "approve" do
1252 test "approves a user" do
1253 user = insert(:user, approval_pending: true)
1254 assert true == user.approval_pending
1255 {:ok, user} = User.approve(user)
1256 assert false == user.approval_pending
1259 test "approves a list of users" do
1260 unapproved_users = [
1261 insert(:user, approval_pending: true),
1262 insert(:user, approval_pending: true),
1263 insert(:user, approval_pending: true)
1266 {:ok, users} = User.approve(unapproved_users)
1268 assert Enum.count(users) == 3
1270 Enum.each(users, fn user ->
1271 assert false == user.approval_pending
1276 describe "delete" do
1278 {:ok, user} = insert(:user) |> User.set_cache()
1283 setup do: clear_config([:instance, :federating])
1285 test ".delete_user_activities deletes all create activities", %{user: user} do
1286 {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
1288 User.delete_user_activities(user)
1290 # TODO: Test removal favorites, repeats, delete activities.
1291 refute Activity.get_by_id(activity.id)
1294 test "it deactivates a user, all follow relationships and all activities", %{user: user} do
1295 follower = insert(:user)
1296 {:ok, follower} = User.follow(follower, user)
1298 locked_user = insert(:user, name: "locked", locked: true)
1299 {:ok, _} = User.follow(user, locked_user, :follow_pending)
1301 object = insert(:note, user: user)
1302 activity = insert(:note_activity, user: user, note: object)
1304 object_two = insert(:note, user: follower)
1305 activity_two = insert(:note_activity, user: follower, note: object_two)
1307 {:ok, like} = CommonAPI.favorite(user, activity_two.id)
1308 {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
1309 {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
1311 {:ok, job} = User.delete(user)
1312 {:ok, _user} = ObanHelpers.perform(job)
1314 follower = User.get_cached_by_id(follower.id)
1316 refute User.following?(follower, user)
1317 assert %{deactivated: true} = User.get_by_id(user.id)
1319 assert [] == User.get_follow_requests(locked_user)
1323 |> Activity.Queries.by_actor()
1325 |> Enum.map(fn act -> act.data["type"] end)
1327 assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
1329 refute Activity.get_by_id(activity.id)
1330 refute Activity.get_by_id(like.id)
1331 refute Activity.get_by_id(like_two.id)
1332 refute Activity.get_by_id(repeat.id)
1336 describe "delete/1 when confirmation is pending" do
1338 user = insert(:user, confirmation_pending: true)
1342 test "deletes user from database when activation required", %{user: user} do
1343 clear_config([:instance, :account_activation_required], true)
1345 {:ok, job} = User.delete(user)
1346 {:ok, _} = ObanHelpers.perform(job)
1348 refute User.get_cached_by_id(user.id)
1349 refute User.get_by_id(user.id)
1352 test "deactivates user when activation is not required", %{user: user} do
1353 clear_config([:instance, :account_activation_required], false)
1355 {:ok, job} = User.delete(user)
1356 {:ok, _} = ObanHelpers.perform(job)
1358 assert %{deactivated: true} = User.get_cached_by_id(user.id)
1359 assert %{deactivated: true} = User.get_by_id(user.id)
1363 test "delete/1 when approval is pending deletes the user" do
1364 user = insert(:user, approval_pending: true)
1367 {:ok, job} = User.delete(user)
1368 {:ok, _} = ObanHelpers.perform(job)
1370 refute User.get_cached_by_id(user.id)
1371 refute User.get_by_id(user.id)
1374 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1375 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1378 describe "per-user rich-text filtering" do
1379 test "html_filter_policy returns default policies, when rich-text is enabled" do
1380 user = insert(:user)
1382 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1385 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1386 user = insert(:user, no_rich_text: true)
1388 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1392 describe "caching" do
1393 test "invalidate_cache works" do
1394 user = insert(:user)
1396 User.set_cache(user)
1397 User.invalidate_cache(user)
1399 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1400 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1403 test "User.delete() plugs any possible zombie objects" do
1404 user = insert(:user)
1406 {:ok, job} = User.delete(user)
1407 {:ok, _} = ObanHelpers.perform(job)
1409 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1411 assert cached_user != user
1413 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1415 assert cached_user != user
1419 describe "account_status/1" do
1420 setup do: clear_config([:instance, :account_activation_required])
1422 test "return confirmation_pending for unconfirm user" do
1423 Pleroma.Config.put([:instance, :account_activation_required], true)
1424 user = insert(:user, confirmation_pending: true)
1425 assert User.account_status(user) == :confirmation_pending
1428 test "return active for confirmed user" do
1429 Pleroma.Config.put([:instance, :account_activation_required], true)
1430 user = insert(:user, confirmation_pending: false)
1431 assert User.account_status(user) == :active
1434 test "return active for remote user" do
1435 user = insert(:user, local: false)
1436 assert User.account_status(user) == :active
1439 test "returns :password_reset_pending for user with reset password" do
1440 user = insert(:user, password_reset_pending: true)
1441 assert User.account_status(user) == :password_reset_pending
1444 test "returns :deactivated for deactivated user" do
1445 user = insert(:user, local: true, confirmation_pending: false, deactivated: true)
1446 assert User.account_status(user) == :deactivated
1449 test "returns :approval_pending for unapproved user" do
1450 user = insert(:user, local: true, approval_pending: true)
1451 assert User.account_status(user) == :approval_pending
1453 user = insert(:user, local: true, confirmation_pending: true, approval_pending: true)
1454 assert User.account_status(user) == :approval_pending
1458 describe "superuser?/1" do
1459 test "returns false for unprivileged users" do
1460 user = insert(:user, local: true)
1462 refute User.superuser?(user)
1465 test "returns false for remote users" do
1466 user = insert(:user, local: false)
1467 remote_admin_user = insert(:user, local: false, is_admin: true)
1469 refute User.superuser?(user)
1470 refute User.superuser?(remote_admin_user)
1473 test "returns true for local moderators" do
1474 user = insert(:user, local: true, is_moderator: true)
1476 assert User.superuser?(user)
1479 test "returns true for local admins" do
1480 user = insert(:user, local: true, is_admin: true)
1482 assert User.superuser?(user)
1486 describe "invisible?/1" do
1487 test "returns true for an invisible user" do
1488 user = insert(:user, local: true, invisible: true)
1490 assert User.invisible?(user)
1493 test "returns false for a non-invisible user" do
1494 user = insert(:user, local: true)
1496 refute User.invisible?(user)
1500 describe "visible_for/2" do
1501 test "returns true when the account is itself" do
1502 user = insert(:user, local: true)
1504 assert User.visible_for(user, user) == :visible
1507 test "returns false when the account is unauthenticated and auth is required" do
1508 Pleroma.Config.put([:instance, :account_activation_required], true)
1510 user = insert(:user, local: true, confirmation_pending: true)
1511 other_user = insert(:user, local: true)
1513 refute User.visible_for(user, other_user) == :visible
1516 test "returns true when the account is unauthenticated and auth is not required" do
1517 user = insert(:user, local: true, confirmation_pending: true)
1518 other_user = insert(:user, local: true)
1520 assert User.visible_for(user, other_user) == :visible
1523 test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
1524 Pleroma.Config.put([:instance, :account_activation_required], true)
1526 user = insert(:user, local: true, confirmation_pending: true)
1527 other_user = insert(:user, local: true, is_admin: true)
1529 assert User.visible_for(user, other_user) == :visible
1533 describe "parse_bio/2" do
1534 test "preserves hosts in user links text" do
1535 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1536 user = insert(:user)
1537 bio = "A.k.a. @nick@domain.com"
1540 ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
1542 }" rel="ugc">@<span>nick@domain.com</span></a></span>)
1544 assert expected_text == User.parse_bio(bio, user)
1547 test "Adds rel=me on linkbacked urls" do
1548 user = insert(:user, ap_id: "https://social.example.org/users/lain")
1550 bio = "http://example.com/rel_me/null"
1551 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1552 assert expected_text == User.parse_bio(bio, user)
1554 bio = "http://example.com/rel_me/link"
1555 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1556 assert expected_text == User.parse_bio(bio, user)
1558 bio = "http://example.com/rel_me/anchor"
1559 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1560 assert expected_text == User.parse_bio(bio, user)
1564 test "follower count is updated when a follower is blocked" do
1565 user = insert(:user)
1566 follower = insert(:user)
1567 follower2 = insert(:user)
1568 follower3 = insert(:user)
1570 {:ok, follower} = User.follow(follower, user)
1571 {:ok, _follower2} = User.follow(follower2, user)
1572 {:ok, _follower3} = User.follow(follower3, user)
1574 {:ok, _user_relationship} = User.block(user, follower)
1575 user = refresh_record(user)
1577 assert user.follower_count == 2
1580 describe "list_inactive_users_query/1" do
1581 defp days_ago(days) do
1583 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
1584 -days * 60 * 60 * 24,
1589 test "Users are inactive by default" do
1593 Enum.map(1..total, fn _ ->
1594 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1597 inactive_users_ids =
1598 Pleroma.User.list_inactive_users_query()
1599 |> Pleroma.Repo.all()
1600 |> Enum.map(& &1.id)
1602 Enum.each(users, fn user ->
1603 assert user.id in inactive_users_ids
1607 test "Only includes users who has no recent activity" do
1611 Enum.map(1..total, fn _ ->
1612 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1615 {inactive, active} = Enum.split(users, trunc(total / 2))
1617 Enum.map(active, fn user ->
1618 to = Enum.random(users -- [user])
1621 CommonAPI.post(user, %{
1622 status: "hey @#{to.nickname}"
1626 inactive_users_ids =
1627 Pleroma.User.list_inactive_users_query()
1628 |> Pleroma.Repo.all()
1629 |> Enum.map(& &1.id)
1631 Enum.each(active, fn user ->
1632 refute user.id in inactive_users_ids
1635 Enum.each(inactive, fn user ->
1636 assert user.id in inactive_users_ids
1640 test "Only includes users with no read notifications" do
1644 Enum.map(1..total, fn _ ->
1645 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1648 [sender | recipients] = users
1649 {inactive, active} = Enum.split(recipients, trunc(total / 2))
1651 Enum.each(recipients, fn to ->
1653 CommonAPI.post(sender, %{
1654 status: "hey @#{to.nickname}"
1658 CommonAPI.post(sender, %{
1659 status: "hey again @#{to.nickname}"
1663 Enum.each(active, fn user ->
1664 [n1, _n2] = Pleroma.Notification.for_user(user)
1665 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
1668 inactive_users_ids =
1669 Pleroma.User.list_inactive_users_query()
1670 |> Pleroma.Repo.all()
1671 |> Enum.map(& &1.id)
1673 Enum.each(active, fn user ->
1674 refute user.id in inactive_users_ids
1677 Enum.each(inactive, fn user ->
1678 assert user.id in inactive_users_ids
1683 describe "toggle_confirmation/1" do
1684 test "if user is confirmed" do
1685 user = insert(:user, confirmation_pending: false)
1686 {:ok, user} = User.toggle_confirmation(user)
1688 assert user.confirmation_pending
1689 assert user.confirmation_token
1692 test "if user is unconfirmed" do
1693 user = insert(:user, confirmation_pending: true, confirmation_token: "some token")
1694 {:ok, user} = User.toggle_confirmation(user)
1696 refute user.confirmation_pending
1697 refute user.confirmation_token
1701 describe "ensure_keys_present" do
1702 test "it creates keys for a user and stores them in info" do
1703 user = insert(:user)
1704 refute is_binary(user.keys)
1705 {:ok, user} = User.ensure_keys_present(user)
1706 assert is_binary(user.keys)
1709 test "it doesn't create keys if there already are some" do
1710 user = insert(:user, keys: "xxx")
1711 {:ok, user} = User.ensure_keys_present(user)
1712 assert user.keys == "xxx"
1716 describe "get_ap_ids_by_nicknames" do
1717 test "it returns a list of AP ids for a given set of nicknames" do
1718 user = insert(:user)
1719 user_two = insert(:user)
1721 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
1722 assert length(ap_ids) == 2
1723 assert user.ap_id in ap_ids
1724 assert user_two.ap_id in ap_ids
1728 describe "sync followers count" do
1730 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
1731 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
1732 insert(:user, local: true)
1733 insert(:user, local: false, deactivated: true)
1734 {:ok, user1: user1, user2: user2}
1737 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
1738 [fdb_user1] = User.external_users(limit: 1)
1740 assert fdb_user1.ap_id
1741 assert fdb_user1.ap_id == user1.ap_id
1742 assert fdb_user1.id == user1.id
1744 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
1746 assert fdb_user2.ap_id
1747 assert fdb_user2.ap_id == user2.ap_id
1748 assert fdb_user2.id == user2.id
1750 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
1754 describe "is_internal_user?/1" do
1755 test "non-internal user returns false" do
1756 user = insert(:user)
1757 refute User.is_internal_user?(user)
1760 test "user with no nickname returns true" do
1761 user = insert(:user, %{nickname: nil})
1762 assert User.is_internal_user?(user)
1765 test "user with internal-prefixed nickname returns true" do
1766 user = insert(:user, %{nickname: "internal.test"})
1767 assert User.is_internal_user?(user)
1771 describe "update_and_set_cache/1" do
1772 test "returns error when user is stale instead Ecto.StaleEntryError" do
1773 user = insert(:user)
1775 changeset = Ecto.Changeset.change(user, bio: "test")
1779 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
1780 User.update_and_set_cache(changeset)
1783 test "performs update cache if user updated" do
1784 user = insert(:user)
1785 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1787 changeset = Ecto.Changeset.change(user, bio: "test-bio")
1789 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
1790 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1791 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
1795 describe "following/followers synchronization" do
1796 setup do: clear_config([:instance, :external_user_synchronization])
1798 test "updates the counters normally on following/getting a follow when disabled" do
1799 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1800 user = insert(:user)
1805 follower_address: "http://localhost:4001/users/masto_closed/followers",
1806 following_address: "http://localhost:4001/users/masto_closed/following",
1810 assert other_user.following_count == 0
1811 assert other_user.follower_count == 0
1813 {:ok, user} = Pleroma.User.follow(user, other_user)
1814 other_user = Pleroma.User.get_by_id(other_user.id)
1816 assert user.following_count == 1
1817 assert other_user.follower_count == 1
1820 test "syncronizes the counters with the remote instance for the followed when enabled" do
1821 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1823 user = insert(:user)
1828 follower_address: "http://localhost:4001/users/masto_closed/followers",
1829 following_address: "http://localhost:4001/users/masto_closed/following",
1833 assert other_user.following_count == 0
1834 assert other_user.follower_count == 0
1836 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1837 {:ok, _user} = User.follow(user, other_user)
1838 other_user = User.get_by_id(other_user.id)
1840 assert other_user.follower_count == 437
1843 test "syncronizes the counters with the remote instance for the follower when enabled" do
1844 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1846 user = insert(:user)
1851 follower_address: "http://localhost:4001/users/masto_closed/followers",
1852 following_address: "http://localhost:4001/users/masto_closed/following",
1856 assert other_user.following_count == 0
1857 assert other_user.follower_count == 0
1859 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1860 {:ok, other_user} = User.follow(other_user, user)
1862 assert other_user.following_count == 152
1866 describe "change_email/2" do
1868 [user: insert(:user)]
1871 test "blank email returns error", %{user: user} do
1872 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
1873 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
1876 test "non unique email returns error", %{user: user} do
1877 %{email: email} = insert(:user)
1879 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
1880 User.change_email(user, email)
1883 test "invalid email returns error", %{user: user} do
1884 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
1885 User.change_email(user, "cofe")
1888 test "changes email", %{user: user} do
1889 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
1893 describe "get_cached_by_nickname_or_id" do
1895 local_user = insert(:user)
1896 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
1898 [local_user: local_user, remote_user: remote_user]
1901 setup do: clear_config([:instance, :limit_to_local_content])
1903 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
1904 remote_user: remote_user
1906 Pleroma.Config.put([:instance, :limit_to_local_content], false)
1907 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
1909 Pleroma.Config.put([:instance, :limit_to_local_content], true)
1910 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
1912 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1913 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
1916 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
1917 %{remote_user: remote_user} do
1918 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1919 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
1922 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
1923 %{remote_user: remote_user, local_user: local_user} do
1924 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1925 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
1928 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
1929 %{remote_user: remote_user} do
1930 Pleroma.Config.put([:instance, :limit_to_local_content], true)
1931 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
1934 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
1935 %{local_user: local_user} do
1936 Pleroma.Config.put([:instance, :limit_to_local_content], false)
1937 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
1939 Pleroma.Config.put([:instance, :limit_to_local_content], true)
1940 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
1942 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1943 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
1947 describe "update_email_notifications/2" do
1949 user = insert(:user, email_notifications: %{"digest" => true})
1954 test "Notifications are updated", %{user: user} do
1955 true = user.email_notifications["digest"]
1956 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
1957 assert result.email_notifications["digest"] == false
1961 test "avatar fallback" do
1962 user = insert(:user)
1963 assert User.avatar_url(user) =~ "/images/avi.png"
1965 clear_config([:assets, :default_user_avatar], "avatar.png")
1967 user = User.get_cached_by_nickname_or_id(user.nickname)
1968 assert User.avatar_url(user) =~ "avatar.png"
1970 assert User.avatar_url(user, no_default: true) == nil