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"
504 test "it sets the 'accepts_chat_messages' set to true" do
505 changeset = User.register_changeset(%User{}, @full_user_data)
506 assert changeset.valid?
508 {:ok, user} = Repo.insert(changeset)
510 assert user.accepts_chat_messages
513 test "it creates a confirmed user" do
514 changeset = User.register_changeset(%User{}, @full_user_data)
515 assert changeset.valid?
517 {:ok, user} = Repo.insert(changeset)
519 refute user.confirmation_pending
523 describe "user registration, with :account_activation_required" do
529 password_confirmation: "test",
530 email: "email@example.com"
532 setup do: clear_config([:instance, :account_activation_required], true)
534 test "it creates unconfirmed user" do
535 changeset = User.register_changeset(%User{}, @full_user_data)
536 assert changeset.valid?
538 {:ok, user} = Repo.insert(changeset)
540 assert user.confirmation_pending
541 assert user.confirmation_token
544 test "it creates confirmed user if :confirmed option is given" do
545 changeset = User.register_changeset(%User{}, @full_user_data, need_confirmation: false)
546 assert changeset.valid?
548 {:ok, user} = Repo.insert(changeset)
550 refute user.confirmation_pending
551 refute user.confirmation_token
555 describe "user registration, with :account_approval_required" do
561 password_confirmation: "test",
562 email: "email@example.com",
563 registration_reason: "I'm a cool guy :)"
565 setup do: clear_config([:instance, :account_approval_required], true)
567 test "it creates unapproved user" do
568 changeset = User.register_changeset(%User{}, @full_user_data)
569 assert changeset.valid?
571 {:ok, user} = Repo.insert(changeset)
573 assert user.approval_pending
574 assert user.registration_reason == "I'm a cool guy :)"
577 test "it restricts length of registration reason" do
578 reason_limit = Pleroma.Config.get([:instance, :registration_reason_length])
580 assert is_integer(reason_limit)
585 :registration_reason,
586 "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."
589 changeset = User.register_changeset(%User{}, params)
591 refute changeset.valid?
595 describe "get_or_fetch/1" do
596 test "gets an existing user by nickname" do
598 {:ok, fetched_user} = User.get_or_fetch(user.nickname)
600 assert user == fetched_user
603 test "gets an existing user by ap_id" do
604 ap_id = "http://mastodon.example.org/users/admin"
610 nickname: "admin@mastodon.example.org",
614 {:ok, fetched_user} = User.get_or_fetch(ap_id)
615 freshed_user = refresh_record(user)
616 assert freshed_user == fetched_user
620 describe "fetching a user from nickname or trying to build one" do
621 test "gets an existing user" do
623 {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
625 assert user == fetched_user
628 test "gets an existing user, case insensitive" do
629 user = insert(:user, nickname: "nick")
630 {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
632 assert user == fetched_user
635 test "gets an existing user by fully qualified nickname" do
638 {:ok, fetched_user} =
639 User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
641 assert user == fetched_user
644 test "gets an existing user by fully qualified nickname, case insensitive" do
645 user = insert(:user, nickname: "nick")
646 casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
648 {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
650 assert user == fetched_user
653 @tag capture_log: true
654 test "returns nil if no user could be fetched" do
655 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
656 assert fetched_user == "not found nonexistant@social.heldscal.la"
659 test "returns nil for nonexistant local user" do
660 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
661 assert fetched_user == "not found nonexistant"
664 test "updates an existing user, if stale" do
665 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
671 nickname: "admin@mastodon.example.org",
672 ap_id: "http://mastodon.example.org/users/admin",
673 last_refreshed_at: a_week_ago
676 assert orig_user.last_refreshed_at == a_week_ago
678 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
682 refute user.last_refreshed_at == orig_user.last_refreshed_at
685 test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
686 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
692 nickname: "admin@mastodon.example.org",
693 ap_id: "http://mastodon.example.org/users/harinezumigari",
694 last_refreshed_at: a_week_ago
697 assert orig_user.last_refreshed_at == a_week_ago
699 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
703 refute user.id == orig_user.id
705 orig_user = User.get_by_id(orig_user.id)
707 assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
710 @tag capture_log: true
711 test "it returns the old user if stale, but unfetchable" do
712 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
718 nickname: "admin@mastodon.example.org",
719 ap_id: "http://mastodon.example.org/users/raymoo",
720 last_refreshed_at: a_week_ago
723 assert orig_user.last_refreshed_at == a_week_ago
725 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/raymoo")
727 assert user.last_refreshed_at == orig_user.last_refreshed_at
731 test "returns an ap_id for a user" do
734 assert User.ap_id(user) ==
735 Pleroma.Web.Router.Helpers.user_feed_url(
736 Pleroma.Web.Endpoint,
742 test "returns an ap_followers link for a user" do
745 assert User.ap_followers(user) ==
746 Pleroma.Web.Router.Helpers.user_feed_url(
747 Pleroma.Web.Endpoint,
753 describe "remote user changeset" do
759 avatar: %{some: "avatar"}
761 setup do: clear_config([:instance, :user_bio_length])
762 setup do: clear_config([:instance, :user_name_length])
764 test "it confirms validity" do
765 cs = User.remote_user_changeset(@valid_remote)
769 test "it sets the follower_adress" do
770 cs = User.remote_user_changeset(@valid_remote)
771 # remote users get a fake local follower address
772 assert cs.changes.follower_address ==
773 User.ap_followers(%User{nickname: @valid_remote[:nickname]})
776 test "it enforces the fqn format for nicknames" do
777 cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})
778 assert Ecto.Changeset.get_field(cs, :local) == false
779 assert cs.changes.avatar
783 test "it has required fields" do
785 |> Enum.each(fn field ->
786 cs = User.remote_user_changeset(Map.delete(@valid_remote, field))
792 describe "followers and friends" do
793 test "gets all followers for a given user" do
795 follower_one = insert(:user)
796 follower_two = insert(:user)
797 not_follower = insert(:user)
799 {:ok, follower_one} = User.follow(follower_one, user)
800 {:ok, follower_two} = User.follow(follower_two, user)
802 res = User.get_followers(user)
804 assert Enum.member?(res, follower_one)
805 assert Enum.member?(res, follower_two)
806 refute Enum.member?(res, not_follower)
809 test "gets all friends (followed users) for a given user" do
811 followed_one = insert(:user)
812 followed_two = insert(:user)
813 not_followed = insert(:user)
815 {:ok, user} = User.follow(user, followed_one)
816 {:ok, user} = User.follow(user, followed_two)
818 res = User.get_friends(user)
820 followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
821 followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
822 assert Enum.member?(res, followed_one)
823 assert Enum.member?(res, followed_two)
824 refute Enum.member?(res, not_followed)
828 describe "updating note and follower count" do
829 test "it sets the note_count property" do
832 user = User.get_cached_by_ap_id(note.data["actor"])
834 assert user.note_count == 0
836 {:ok, user} = User.update_note_count(user)
838 assert user.note_count == 1
841 test "it increases the note_count property" do
843 user = User.get_cached_by_ap_id(note.data["actor"])
845 assert user.note_count == 0
847 {:ok, user} = User.increase_note_count(user)
849 assert user.note_count == 1
851 {:ok, user} = User.increase_note_count(user)
853 assert user.note_count == 2
856 test "it decreases the note_count property" do
858 user = User.get_cached_by_ap_id(note.data["actor"])
860 assert user.note_count == 0
862 {:ok, user} = User.increase_note_count(user)
864 assert user.note_count == 1
866 {:ok, user} = User.decrease_note_count(user)
868 assert user.note_count == 0
870 {:ok, user} = User.decrease_note_count(user)
872 assert user.note_count == 0
875 test "it sets the follower_count property" do
877 follower = insert(:user)
879 User.follow(follower, user)
881 assert user.follower_count == 0
883 {:ok, user} = User.update_follower_count(user)
885 assert user.follower_count == 1
889 describe "follow_import" do
890 test "it imports user followings from list" do
891 [user1, user2, user3] = insert_list(3, :user)
898 {:ok, job} = User.follow_import(user1, identifiers)
900 assert {:ok, result} = ObanHelpers.perform(job)
901 assert is_list(result)
902 assert result == [user2, user3]
907 test "it mutes people" do
909 muted_user = insert(:user)
911 refute User.mutes?(user, muted_user)
912 refute User.muted_notifications?(user, muted_user)
914 {:ok, _user_relationships} = User.mute(user, muted_user)
916 assert User.mutes?(user, muted_user)
917 assert User.muted_notifications?(user, muted_user)
920 test "it unmutes users" do
922 muted_user = insert(:user)
924 {:ok, _user_relationships} = User.mute(user, muted_user)
925 {:ok, _user_mute} = User.unmute(user, muted_user)
927 refute User.mutes?(user, muted_user)
928 refute User.muted_notifications?(user, muted_user)
931 test "it mutes user without notifications" do
933 muted_user = insert(:user)
935 refute User.mutes?(user, muted_user)
936 refute User.muted_notifications?(user, muted_user)
938 {:ok, _user_relationships} = User.mute(user, muted_user, false)
940 assert User.mutes?(user, muted_user)
941 refute User.muted_notifications?(user, muted_user)
946 test "it blocks people" do
948 blocked_user = insert(:user)
950 refute User.blocks?(user, blocked_user)
952 {:ok, _user_relationship} = User.block(user, blocked_user)
954 assert User.blocks?(user, blocked_user)
957 test "it unblocks users" do
959 blocked_user = insert(:user)
961 {:ok, _user_relationship} = User.block(user, blocked_user)
962 {:ok, _user_block} = User.unblock(user, blocked_user)
964 refute User.blocks?(user, blocked_user)
967 test "blocks tear down cyclical follow relationships" do
968 blocker = insert(:user)
969 blocked = insert(:user)
971 {:ok, blocker} = User.follow(blocker, blocked)
972 {:ok, blocked} = User.follow(blocked, blocker)
974 assert User.following?(blocker, blocked)
975 assert User.following?(blocked, blocker)
977 {:ok, _user_relationship} = User.block(blocker, blocked)
978 blocked = User.get_cached_by_id(blocked.id)
980 assert User.blocks?(blocker, blocked)
982 refute User.following?(blocker, blocked)
983 refute User.following?(blocked, blocker)
986 test "blocks tear down blocker->blocked follow relationships" do
987 blocker = insert(:user)
988 blocked = insert(:user)
990 {:ok, blocker} = User.follow(blocker, blocked)
992 assert User.following?(blocker, blocked)
993 refute User.following?(blocked, blocker)
995 {:ok, _user_relationship} = User.block(blocker, blocked)
996 blocked = User.get_cached_by_id(blocked.id)
998 assert User.blocks?(blocker, blocked)
1000 refute User.following?(blocker, blocked)
1001 refute User.following?(blocked, blocker)
1004 test "blocks tear down blocked->blocker follow relationships" do
1005 blocker = insert(:user)
1006 blocked = insert(:user)
1008 {:ok, blocked} = User.follow(blocked, blocker)
1010 refute User.following?(blocker, blocked)
1011 assert User.following?(blocked, blocker)
1013 {:ok, _user_relationship} = User.block(blocker, blocked)
1014 blocked = User.get_cached_by_id(blocked.id)
1016 assert User.blocks?(blocker, blocked)
1018 refute User.following?(blocker, blocked)
1019 refute User.following?(blocked, blocker)
1022 test "blocks tear down blocked->blocker subscription relationships" do
1023 blocker = insert(:user)
1024 blocked = insert(:user)
1026 {:ok, _subscription} = User.subscribe(blocked, blocker)
1028 assert User.subscribed_to?(blocked, blocker)
1029 refute User.subscribed_to?(blocker, blocked)
1031 {:ok, _user_relationship} = User.block(blocker, blocked)
1033 assert User.blocks?(blocker, blocked)
1034 refute User.subscribed_to?(blocker, blocked)
1035 refute User.subscribed_to?(blocked, blocker)
1039 describe "domain blocking" do
1040 test "blocks domains" do
1041 user = insert(:user)
1042 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1044 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1046 assert User.blocks?(user, collateral_user)
1049 test "does not block domain with same end" do
1050 user = insert(:user)
1053 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1055 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1057 refute User.blocks?(user, collateral_user)
1060 test "does not block domain with same end if wildcard added" do
1061 user = insert(:user)
1064 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1066 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1068 refute User.blocks?(user, collateral_user)
1071 test "blocks domain with wildcard for subdomain" do
1072 user = insert(:user)
1074 user_from_subdomain =
1075 insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
1077 user_with_two_subdomains =
1079 ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
1082 user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1084 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1086 assert User.blocks?(user, user_from_subdomain)
1087 assert User.blocks?(user, user_with_two_subdomains)
1088 assert User.blocks?(user, user_domain)
1091 test "unblocks domains" do
1092 user = insert(:user)
1093 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1095 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1096 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
1098 refute User.blocks?(user, collateral_user)
1101 test "follows take precedence over domain blocks" do
1102 user = insert(:user)
1103 good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
1105 {:ok, user} = User.block_domain(user, "meanies.social")
1106 {:ok, user} = User.follow(user, good_eggo)
1108 refute User.blocks?(user, good_eggo)
1112 describe "blocks_import" do
1113 test "it imports user blocks from list" do
1114 [user1, user2, user3] = insert_list(3, :user)
1121 {:ok, job} = User.blocks_import(user1, identifiers)
1123 assert {:ok, result} = ObanHelpers.perform(job)
1124 assert is_list(result)
1125 assert result == [user2, user3]
1129 describe "get_recipients_from_activity" do
1130 test "works for announces" do
1131 actor = insert(:user)
1132 user = insert(:user, local: true)
1134 {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
1135 {:ok, announce} = CommonAPI.repeat(activity.id, user)
1137 recipients = User.get_recipients_from_activity(announce)
1139 assert user in recipients
1142 test "get recipients" do
1143 actor = insert(:user)
1144 user = insert(:user, local: true)
1145 user_two = insert(:user, local: false)
1146 addressed = insert(:user, local: true)
1147 addressed_remote = insert(:user, local: false)
1150 CommonAPI.post(actor, %{
1151 status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
1154 assert Enum.map([actor, addressed], & &1.ap_id) --
1155 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1157 {:ok, user} = User.follow(user, actor)
1158 {:ok, _user_two} = User.follow(user_two, actor)
1159 recipients = User.get_recipients_from_activity(activity)
1160 assert length(recipients) == 3
1161 assert user in recipients
1162 assert addressed in recipients
1165 test "has following" do
1166 actor = insert(:user)
1167 user = insert(:user)
1168 user_two = insert(:user)
1169 addressed = insert(:user, local: true)
1172 CommonAPI.post(actor, %{
1173 status: "hey @#{addressed.nickname}"
1176 assert Enum.map([actor, addressed], & &1.ap_id) --
1177 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1179 {:ok, _actor} = User.follow(actor, user)
1180 {:ok, _actor} = User.follow(actor, user_two)
1181 recipients = User.get_recipients_from_activity(activity)
1182 assert length(recipients) == 2
1183 assert addressed in recipients
1187 describe ".deactivate" do
1188 test "can de-activate then re-activate a user" do
1189 user = insert(:user)
1190 assert false == user.deactivated
1191 {:ok, user} = User.deactivate(user)
1192 assert true == user.deactivated
1193 {:ok, user} = User.deactivate(user, false)
1194 assert false == user.deactivated
1197 test "hide a user from followers" do
1198 user = insert(:user)
1199 user2 = insert(:user)
1201 {:ok, user} = User.follow(user, user2)
1202 {:ok, _user} = User.deactivate(user)
1204 user2 = User.get_cached_by_id(user2.id)
1206 assert user2.follower_count == 0
1207 assert [] = User.get_followers(user2)
1210 test "hide a user from friends" do
1211 user = insert(:user)
1212 user2 = insert(:user)
1214 {:ok, user2} = User.follow(user2, user)
1215 assert user2.following_count == 1
1216 assert User.following_count(user2) == 1
1218 {:ok, _user} = User.deactivate(user)
1220 user2 = User.get_cached_by_id(user2.id)
1222 assert refresh_record(user2).following_count == 0
1223 assert user2.following_count == 0
1224 assert User.following_count(user2) == 0
1225 assert [] = User.get_friends(user2)
1228 test "hide a user's statuses from timelines and notifications" do
1229 user = insert(:user)
1230 user2 = insert(:user)
1232 {:ok, user2} = User.follow(user2, user)
1234 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
1236 activity = Repo.preload(activity, :bookmark)
1238 [notification] = Pleroma.Notification.for_user(user2)
1239 assert notification.activity.id == activity.id
1241 assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
1243 assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
1244 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1248 {:ok, _user} = User.deactivate(user)
1250 assert [] == ActivityPub.fetch_public_activities(%{})
1251 assert [] == Pleroma.Notification.for_user(user2)
1254 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1260 describe "approve" do
1261 test "approves a user" do
1262 user = insert(:user, approval_pending: true)
1263 assert true == user.approval_pending
1264 {:ok, user} = User.approve(user)
1265 assert false == user.approval_pending
1268 test "approves a list of users" do
1269 unapproved_users = [
1270 insert(:user, approval_pending: true),
1271 insert(:user, approval_pending: true),
1272 insert(:user, approval_pending: true)
1275 {:ok, users} = User.approve(unapproved_users)
1277 assert Enum.count(users) == 3
1279 Enum.each(users, fn user ->
1280 assert false == user.approval_pending
1285 describe "delete" do
1287 {:ok, user} = insert(:user) |> User.set_cache()
1292 setup do: clear_config([:instance, :federating])
1294 test ".delete_user_activities deletes all create activities", %{user: user} do
1295 {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
1297 User.delete_user_activities(user)
1299 # TODO: Test removal favorites, repeats, delete activities.
1300 refute Activity.get_by_id(activity.id)
1303 test "it deactivates a user, all follow relationships and all activities", %{user: user} do
1304 follower = insert(:user)
1305 {:ok, follower} = User.follow(follower, user)
1307 locked_user = insert(:user, name: "locked", locked: true)
1308 {:ok, _} = User.follow(user, locked_user, :follow_pending)
1310 object = insert(:note, user: user)
1311 activity = insert(:note_activity, user: user, note: object)
1313 object_two = insert(:note, user: follower)
1314 activity_two = insert(:note_activity, user: follower, note: object_two)
1316 {:ok, like} = CommonAPI.favorite(user, activity_two.id)
1317 {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
1318 {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
1320 {:ok, job} = User.delete(user)
1321 {:ok, _user} = ObanHelpers.perform(job)
1323 follower = User.get_cached_by_id(follower.id)
1325 refute User.following?(follower, user)
1326 assert %{deactivated: true} = User.get_by_id(user.id)
1328 assert [] == User.get_follow_requests(locked_user)
1332 |> Activity.Queries.by_actor()
1334 |> Enum.map(fn act -> act.data["type"] end)
1336 assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
1338 refute Activity.get_by_id(activity.id)
1339 refute Activity.get_by_id(like.id)
1340 refute Activity.get_by_id(like_two.id)
1341 refute Activity.get_by_id(repeat.id)
1345 describe "delete/1 when confirmation is pending" do
1347 user = insert(:user, confirmation_pending: true)
1351 test "deletes user from database when activation required", %{user: user} do
1352 clear_config([:instance, :account_activation_required], true)
1354 {:ok, job} = User.delete(user)
1355 {:ok, _} = ObanHelpers.perform(job)
1357 refute User.get_cached_by_id(user.id)
1358 refute User.get_by_id(user.id)
1361 test "deactivates user when activation is not required", %{user: user} do
1362 clear_config([:instance, :account_activation_required], false)
1364 {:ok, job} = User.delete(user)
1365 {:ok, _} = ObanHelpers.perform(job)
1367 assert %{deactivated: true} = User.get_cached_by_id(user.id)
1368 assert %{deactivated: true} = User.get_by_id(user.id)
1372 test "delete/1 when approval is pending deletes the user" do
1373 user = insert(:user, approval_pending: true)
1376 {:ok, job} = User.delete(user)
1377 {:ok, _} = ObanHelpers.perform(job)
1379 refute User.get_cached_by_id(user.id)
1380 refute User.get_by_id(user.id)
1383 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1384 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1387 describe "per-user rich-text filtering" do
1388 test "html_filter_policy returns default policies, when rich-text is enabled" do
1389 user = insert(:user)
1391 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1394 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1395 user = insert(:user, no_rich_text: true)
1397 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1401 describe "caching" do
1402 test "invalidate_cache works" do
1403 user = insert(:user)
1405 User.set_cache(user)
1406 User.invalidate_cache(user)
1408 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1409 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1412 test "User.delete() plugs any possible zombie objects" do
1413 user = insert(:user)
1415 {:ok, job} = User.delete(user)
1416 {:ok, _} = ObanHelpers.perform(job)
1418 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1420 assert cached_user != user
1422 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1424 assert cached_user != user
1428 describe "account_status/1" do
1429 setup do: clear_config([:instance, :account_activation_required])
1431 test "return confirmation_pending for unconfirm user" do
1432 Pleroma.Config.put([:instance, :account_activation_required], true)
1433 user = insert(:user, confirmation_pending: true)
1434 assert User.account_status(user) == :confirmation_pending
1437 test "return active for confirmed user" do
1438 Pleroma.Config.put([:instance, :account_activation_required], true)
1439 user = insert(:user, confirmation_pending: false)
1440 assert User.account_status(user) == :active
1443 test "return active for remote user" do
1444 user = insert(:user, local: false)
1445 assert User.account_status(user) == :active
1448 test "returns :password_reset_pending for user with reset password" do
1449 user = insert(:user, password_reset_pending: true)
1450 assert User.account_status(user) == :password_reset_pending
1453 test "returns :deactivated for deactivated user" do
1454 user = insert(:user, local: true, confirmation_pending: false, deactivated: true)
1455 assert User.account_status(user) == :deactivated
1458 test "returns :approval_pending for unapproved user" do
1459 user = insert(:user, local: true, approval_pending: true)
1460 assert User.account_status(user) == :approval_pending
1462 user = insert(:user, local: true, confirmation_pending: true, approval_pending: true)
1463 assert User.account_status(user) == :approval_pending
1467 describe "superuser?/1" do
1468 test "returns false for unprivileged users" do
1469 user = insert(:user, local: true)
1471 refute User.superuser?(user)
1474 test "returns false for remote users" do
1475 user = insert(:user, local: false)
1476 remote_admin_user = insert(:user, local: false, is_admin: true)
1478 refute User.superuser?(user)
1479 refute User.superuser?(remote_admin_user)
1482 test "returns true for local moderators" do
1483 user = insert(:user, local: true, is_moderator: true)
1485 assert User.superuser?(user)
1488 test "returns true for local admins" do
1489 user = insert(:user, local: true, is_admin: true)
1491 assert User.superuser?(user)
1495 describe "invisible?/1" do
1496 test "returns true for an invisible user" do
1497 user = insert(:user, local: true, invisible: true)
1499 assert User.invisible?(user)
1502 test "returns false for a non-invisible user" do
1503 user = insert(:user, local: true)
1505 refute User.invisible?(user)
1509 describe "visible_for/2" do
1510 test "returns true when the account is itself" do
1511 user = insert(:user, local: true)
1513 assert User.visible_for(user, user) == :visible
1516 test "returns false when the account is unauthenticated and auth is required" do
1517 Pleroma.Config.put([:instance, :account_activation_required], true)
1519 user = insert(:user, local: true, confirmation_pending: true)
1520 other_user = insert(:user, local: true)
1522 refute User.visible_for(user, other_user) == :visible
1525 test "returns true when the account is unauthenticated and auth is not required" do
1526 user = insert(:user, local: true, confirmation_pending: true)
1527 other_user = insert(:user, local: true)
1529 assert User.visible_for(user, other_user) == :visible
1532 test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
1533 Pleroma.Config.put([:instance, :account_activation_required], true)
1535 user = insert(:user, local: true, confirmation_pending: true)
1536 other_user = insert(:user, local: true, is_admin: true)
1538 assert User.visible_for(user, other_user) == :visible
1542 describe "parse_bio/2" do
1543 test "preserves hosts in user links text" do
1544 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1545 user = insert(:user)
1546 bio = "A.k.a. @nick@domain.com"
1549 ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
1551 }" rel="ugc">@<span>nick@domain.com</span></a></span>)
1553 assert expected_text == User.parse_bio(bio, user)
1556 test "Adds rel=me on linkbacked urls" do
1557 user = insert(:user, ap_id: "https://social.example.org/users/lain")
1559 bio = "http://example.com/rel_me/null"
1560 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1561 assert expected_text == User.parse_bio(bio, user)
1563 bio = "http://example.com/rel_me/link"
1564 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1565 assert expected_text == User.parse_bio(bio, user)
1567 bio = "http://example.com/rel_me/anchor"
1568 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1569 assert expected_text == User.parse_bio(bio, user)
1573 test "follower count is updated when a follower is blocked" do
1574 user = insert(:user)
1575 follower = insert(:user)
1576 follower2 = insert(:user)
1577 follower3 = insert(:user)
1579 {:ok, follower} = User.follow(follower, user)
1580 {:ok, _follower2} = User.follow(follower2, user)
1581 {:ok, _follower3} = User.follow(follower3, user)
1583 {:ok, _user_relationship} = User.block(user, follower)
1584 user = refresh_record(user)
1586 assert user.follower_count == 2
1589 describe "list_inactive_users_query/1" do
1590 defp days_ago(days) do
1592 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
1593 -days * 60 * 60 * 24,
1598 test "Users are inactive by default" do
1602 Enum.map(1..total, fn _ ->
1603 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1606 inactive_users_ids =
1607 Pleroma.User.list_inactive_users_query()
1608 |> Pleroma.Repo.all()
1609 |> Enum.map(& &1.id)
1611 Enum.each(users, fn user ->
1612 assert user.id in inactive_users_ids
1616 test "Only includes users who has no recent activity" do
1620 Enum.map(1..total, fn _ ->
1621 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1624 {inactive, active} = Enum.split(users, trunc(total / 2))
1626 Enum.map(active, fn user ->
1627 to = Enum.random(users -- [user])
1630 CommonAPI.post(user, %{
1631 status: "hey @#{to.nickname}"
1635 inactive_users_ids =
1636 Pleroma.User.list_inactive_users_query()
1637 |> Pleroma.Repo.all()
1638 |> Enum.map(& &1.id)
1640 Enum.each(active, fn user ->
1641 refute user.id in inactive_users_ids
1644 Enum.each(inactive, fn user ->
1645 assert user.id in inactive_users_ids
1649 test "Only includes users with no read notifications" do
1653 Enum.map(1..total, fn _ ->
1654 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1657 [sender | recipients] = users
1658 {inactive, active} = Enum.split(recipients, trunc(total / 2))
1660 Enum.each(recipients, fn to ->
1662 CommonAPI.post(sender, %{
1663 status: "hey @#{to.nickname}"
1667 CommonAPI.post(sender, %{
1668 status: "hey again @#{to.nickname}"
1672 Enum.each(active, fn user ->
1673 [n1, _n2] = Pleroma.Notification.for_user(user)
1674 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
1677 inactive_users_ids =
1678 Pleroma.User.list_inactive_users_query()
1679 |> Pleroma.Repo.all()
1680 |> Enum.map(& &1.id)
1682 Enum.each(active, fn user ->
1683 refute user.id in inactive_users_ids
1686 Enum.each(inactive, fn user ->
1687 assert user.id in inactive_users_ids
1692 describe "toggle_confirmation/1" do
1693 test "if user is confirmed" do
1694 user = insert(:user, confirmation_pending: false)
1695 {:ok, user} = User.toggle_confirmation(user)
1697 assert user.confirmation_pending
1698 assert user.confirmation_token
1701 test "if user is unconfirmed" do
1702 user = insert(:user, confirmation_pending: true, confirmation_token: "some token")
1703 {:ok, user} = User.toggle_confirmation(user)
1705 refute user.confirmation_pending
1706 refute user.confirmation_token
1710 describe "ensure_keys_present" do
1711 test "it creates keys for a user and stores them in info" do
1712 user = insert(:user)
1713 refute is_binary(user.keys)
1714 {:ok, user} = User.ensure_keys_present(user)
1715 assert is_binary(user.keys)
1718 test "it doesn't create keys if there already are some" do
1719 user = insert(:user, keys: "xxx")
1720 {:ok, user} = User.ensure_keys_present(user)
1721 assert user.keys == "xxx"
1725 describe "get_ap_ids_by_nicknames" do
1726 test "it returns a list of AP ids for a given set of nicknames" do
1727 user = insert(:user)
1728 user_two = insert(:user)
1730 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
1731 assert length(ap_ids) == 2
1732 assert user.ap_id in ap_ids
1733 assert user_two.ap_id in ap_ids
1737 describe "sync followers count" do
1739 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
1740 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
1741 insert(:user, local: true)
1742 insert(:user, local: false, deactivated: true)
1743 {:ok, user1: user1, user2: user2}
1746 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
1747 [fdb_user1] = User.external_users(limit: 1)
1749 assert fdb_user1.ap_id
1750 assert fdb_user1.ap_id == user1.ap_id
1751 assert fdb_user1.id == user1.id
1753 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
1755 assert fdb_user2.ap_id
1756 assert fdb_user2.ap_id == user2.ap_id
1757 assert fdb_user2.id == user2.id
1759 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
1763 describe "is_internal_user?/1" do
1764 test "non-internal user returns false" do
1765 user = insert(:user)
1766 refute User.is_internal_user?(user)
1769 test "user with no nickname returns true" do
1770 user = insert(:user, %{nickname: nil})
1771 assert User.is_internal_user?(user)
1774 test "user with internal-prefixed nickname returns true" do
1775 user = insert(:user, %{nickname: "internal.test"})
1776 assert User.is_internal_user?(user)
1780 describe "update_and_set_cache/1" do
1781 test "returns error when user is stale instead Ecto.StaleEntryError" do
1782 user = insert(:user)
1784 changeset = Ecto.Changeset.change(user, bio: "test")
1788 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
1789 User.update_and_set_cache(changeset)
1792 test "performs update cache if user updated" do
1793 user = insert(:user)
1794 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1796 changeset = Ecto.Changeset.change(user, bio: "test-bio")
1798 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
1799 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1800 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
1804 describe "following/followers synchronization" do
1805 setup do: clear_config([:instance, :external_user_synchronization])
1807 test "updates the counters normally on following/getting a follow when disabled" do
1808 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1809 user = insert(:user)
1814 follower_address: "http://localhost:4001/users/masto_closed/followers",
1815 following_address: "http://localhost:4001/users/masto_closed/following",
1819 assert other_user.following_count == 0
1820 assert other_user.follower_count == 0
1822 {:ok, user} = Pleroma.User.follow(user, other_user)
1823 other_user = Pleroma.User.get_by_id(other_user.id)
1825 assert user.following_count == 1
1826 assert other_user.follower_count == 1
1829 test "syncronizes the counters with the remote instance for the followed when enabled" do
1830 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1832 user = insert(:user)
1837 follower_address: "http://localhost:4001/users/masto_closed/followers",
1838 following_address: "http://localhost:4001/users/masto_closed/following",
1842 assert other_user.following_count == 0
1843 assert other_user.follower_count == 0
1845 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1846 {:ok, _user} = User.follow(user, other_user)
1847 other_user = User.get_by_id(other_user.id)
1849 assert other_user.follower_count == 437
1852 test "syncronizes the counters with the remote instance for the follower when enabled" do
1853 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1855 user = insert(:user)
1860 follower_address: "http://localhost:4001/users/masto_closed/followers",
1861 following_address: "http://localhost:4001/users/masto_closed/following",
1865 assert other_user.following_count == 0
1866 assert other_user.follower_count == 0
1868 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1869 {:ok, other_user} = User.follow(other_user, user)
1871 assert other_user.following_count == 152
1875 describe "change_email/2" do
1877 [user: insert(:user)]
1880 test "blank email returns error", %{user: user} do
1881 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
1882 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
1885 test "non unique email returns error", %{user: user} do
1886 %{email: email} = insert(:user)
1888 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
1889 User.change_email(user, email)
1892 test "invalid email returns error", %{user: user} do
1893 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
1894 User.change_email(user, "cofe")
1897 test "changes email", %{user: user} do
1898 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
1902 describe "get_cached_by_nickname_or_id" do
1904 local_user = insert(:user)
1905 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
1907 [local_user: local_user, remote_user: remote_user]
1910 setup do: clear_config([:instance, :limit_to_local_content])
1912 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
1913 remote_user: remote_user
1915 Pleroma.Config.put([:instance, :limit_to_local_content], false)
1916 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
1918 Pleroma.Config.put([:instance, :limit_to_local_content], true)
1919 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
1921 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1922 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
1925 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
1926 %{remote_user: remote_user} do
1927 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1928 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
1931 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
1932 %{remote_user: remote_user, local_user: local_user} do
1933 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1934 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
1937 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
1938 %{remote_user: remote_user} do
1939 Pleroma.Config.put([:instance, :limit_to_local_content], true)
1940 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
1943 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
1944 %{local_user: local_user} do
1945 Pleroma.Config.put([:instance, :limit_to_local_content], false)
1946 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
1948 Pleroma.Config.put([:instance, :limit_to_local_content], true)
1949 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
1951 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1952 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
1956 describe "update_email_notifications/2" do
1958 user = insert(:user, email_notifications: %{"digest" => true})
1963 test "Notifications are updated", %{user: user} do
1964 true = user.email_notifications["digest"]
1965 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
1966 assert result.email_notifications["digest"] == false
1970 test "avatar fallback" do
1971 user = insert(:user)
1972 assert User.avatar_url(user) =~ "/images/avi.png"
1974 clear_config([:assets, :default_user_avatar], "avatar.png")
1976 user = User.get_cached_by_nickname_or_id(user.nickname)
1977 assert User.avatar_url(user) =~ "avatar.png"
1979 assert User.avatar_url(user, no_default: true) == nil