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)
575 |> Map.put(:registration_reason, "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.")
577 changeset = User.register_changeset(%User{}, params)
579 refute changeset.valid?
583 describe "get_or_fetch/1" do
584 test "gets an existing user by nickname" do
586 {:ok, fetched_user} = User.get_or_fetch(user.nickname)
588 assert user == fetched_user
591 test "gets an existing user by ap_id" do
592 ap_id = "http://mastodon.example.org/users/admin"
598 nickname: "admin@mastodon.example.org",
602 {:ok, fetched_user} = User.get_or_fetch(ap_id)
603 freshed_user = refresh_record(user)
604 assert freshed_user == fetched_user
608 describe "fetching a user from nickname or trying to build one" do
609 test "gets an existing user" do
611 {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
613 assert user == fetched_user
616 test "gets an existing user, case insensitive" do
617 user = insert(:user, nickname: "nick")
618 {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
620 assert user == fetched_user
623 test "gets an existing user by fully qualified nickname" do
626 {:ok, fetched_user} =
627 User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
629 assert user == fetched_user
632 test "gets an existing user by fully qualified nickname, case insensitive" do
633 user = insert(:user, nickname: "nick")
634 casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
636 {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
638 assert user == fetched_user
641 @tag capture_log: true
642 test "returns nil if no user could be fetched" do
643 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
644 assert fetched_user == "not found nonexistant@social.heldscal.la"
647 test "returns nil for nonexistant local user" do
648 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
649 assert fetched_user == "not found nonexistant"
652 test "updates an existing user, if stale" do
653 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
659 nickname: "admin@mastodon.example.org",
660 ap_id: "http://mastodon.example.org/users/admin",
661 last_refreshed_at: a_week_ago
664 assert orig_user.last_refreshed_at == a_week_ago
666 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
670 refute user.last_refreshed_at == orig_user.last_refreshed_at
673 test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
674 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
680 nickname: "admin@mastodon.example.org",
681 ap_id: "http://mastodon.example.org/users/harinezumigari",
682 last_refreshed_at: a_week_ago
685 assert orig_user.last_refreshed_at == a_week_ago
687 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
691 refute user.id == orig_user.id
693 orig_user = User.get_by_id(orig_user.id)
695 assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
698 @tag capture_log: true
699 test "it returns the old user if stale, but unfetchable" do
700 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
706 nickname: "admin@mastodon.example.org",
707 ap_id: "http://mastodon.example.org/users/raymoo",
708 last_refreshed_at: a_week_ago
711 assert orig_user.last_refreshed_at == a_week_ago
713 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/raymoo")
715 assert user.last_refreshed_at == orig_user.last_refreshed_at
719 test "returns an ap_id for a user" do
722 assert User.ap_id(user) ==
723 Pleroma.Web.Router.Helpers.user_feed_url(
724 Pleroma.Web.Endpoint,
730 test "returns an ap_followers link for a user" do
733 assert User.ap_followers(user) ==
734 Pleroma.Web.Router.Helpers.user_feed_url(
735 Pleroma.Web.Endpoint,
741 describe "remote user changeset" do
747 avatar: %{some: "avatar"}
749 setup do: clear_config([:instance, :user_bio_length])
750 setup do: clear_config([:instance, :user_name_length])
752 test "it confirms validity" do
753 cs = User.remote_user_changeset(@valid_remote)
757 test "it sets the follower_adress" do
758 cs = User.remote_user_changeset(@valid_remote)
759 # remote users get a fake local follower address
760 assert cs.changes.follower_address ==
761 User.ap_followers(%User{nickname: @valid_remote[:nickname]})
764 test "it enforces the fqn format for nicknames" do
765 cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})
766 assert Ecto.Changeset.get_field(cs, :local) == false
767 assert cs.changes.avatar
771 test "it has required fields" do
773 |> Enum.each(fn field ->
774 cs = User.remote_user_changeset(Map.delete(@valid_remote, field))
780 describe "followers and friends" do
781 test "gets all followers for a given user" do
783 follower_one = insert(:user)
784 follower_two = insert(:user)
785 not_follower = insert(:user)
787 {:ok, follower_one} = User.follow(follower_one, user)
788 {:ok, follower_two} = User.follow(follower_two, user)
790 res = User.get_followers(user)
792 assert Enum.member?(res, follower_one)
793 assert Enum.member?(res, follower_two)
794 refute Enum.member?(res, not_follower)
797 test "gets all friends (followed users) for a given user" do
799 followed_one = insert(:user)
800 followed_two = insert(:user)
801 not_followed = insert(:user)
803 {:ok, user} = User.follow(user, followed_one)
804 {:ok, user} = User.follow(user, followed_two)
806 res = User.get_friends(user)
808 followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
809 followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
810 assert Enum.member?(res, followed_one)
811 assert Enum.member?(res, followed_two)
812 refute Enum.member?(res, not_followed)
816 describe "updating note and follower count" do
817 test "it sets the note_count property" do
820 user = User.get_cached_by_ap_id(note.data["actor"])
822 assert user.note_count == 0
824 {:ok, user} = User.update_note_count(user)
826 assert user.note_count == 1
829 test "it increases the note_count property" do
831 user = User.get_cached_by_ap_id(note.data["actor"])
833 assert user.note_count == 0
835 {:ok, user} = User.increase_note_count(user)
837 assert user.note_count == 1
839 {:ok, user} = User.increase_note_count(user)
841 assert user.note_count == 2
844 test "it decreases the note_count property" do
846 user = User.get_cached_by_ap_id(note.data["actor"])
848 assert user.note_count == 0
850 {:ok, user} = User.increase_note_count(user)
852 assert user.note_count == 1
854 {:ok, user} = User.decrease_note_count(user)
856 assert user.note_count == 0
858 {:ok, user} = User.decrease_note_count(user)
860 assert user.note_count == 0
863 test "it sets the follower_count property" do
865 follower = insert(:user)
867 User.follow(follower, user)
869 assert user.follower_count == 0
871 {:ok, user} = User.update_follower_count(user)
873 assert user.follower_count == 1
877 describe "follow_import" do
878 test "it imports user followings from list" do
879 [user1, user2, user3] = insert_list(3, :user)
886 {:ok, job} = User.follow_import(user1, identifiers)
888 assert {:ok, result} = ObanHelpers.perform(job)
889 assert is_list(result)
890 assert result == [user2, user3]
895 test "it mutes people" do
897 muted_user = insert(:user)
899 refute User.mutes?(user, muted_user)
900 refute User.muted_notifications?(user, muted_user)
902 {:ok, _user_relationships} = User.mute(user, muted_user)
904 assert User.mutes?(user, muted_user)
905 assert User.muted_notifications?(user, muted_user)
908 test "it unmutes users" do
910 muted_user = insert(:user)
912 {:ok, _user_relationships} = User.mute(user, muted_user)
913 {:ok, _user_mute} = User.unmute(user, muted_user)
915 refute User.mutes?(user, muted_user)
916 refute User.muted_notifications?(user, muted_user)
919 test "it mutes user without notifications" do
921 muted_user = insert(:user)
923 refute User.mutes?(user, muted_user)
924 refute User.muted_notifications?(user, muted_user)
926 {:ok, _user_relationships} = User.mute(user, muted_user, false)
928 assert User.mutes?(user, muted_user)
929 refute User.muted_notifications?(user, muted_user)
934 test "it blocks people" do
936 blocked_user = insert(:user)
938 refute User.blocks?(user, blocked_user)
940 {:ok, _user_relationship} = User.block(user, blocked_user)
942 assert User.blocks?(user, blocked_user)
945 test "it unblocks users" do
947 blocked_user = insert(:user)
949 {:ok, _user_relationship} = User.block(user, blocked_user)
950 {:ok, _user_block} = User.unblock(user, blocked_user)
952 refute User.blocks?(user, blocked_user)
955 test "blocks tear down cyclical follow relationships" do
956 blocker = insert(:user)
957 blocked = insert(:user)
959 {:ok, blocker} = User.follow(blocker, blocked)
960 {:ok, blocked} = User.follow(blocked, blocker)
962 assert User.following?(blocker, blocked)
963 assert User.following?(blocked, blocker)
965 {:ok, _user_relationship} = User.block(blocker, blocked)
966 blocked = User.get_cached_by_id(blocked.id)
968 assert User.blocks?(blocker, blocked)
970 refute User.following?(blocker, blocked)
971 refute User.following?(blocked, blocker)
974 test "blocks tear down blocker->blocked follow relationships" do
975 blocker = insert(:user)
976 blocked = insert(:user)
978 {:ok, blocker} = User.follow(blocker, blocked)
980 assert User.following?(blocker, blocked)
981 refute User.following?(blocked, blocker)
983 {:ok, _user_relationship} = User.block(blocker, blocked)
984 blocked = User.get_cached_by_id(blocked.id)
986 assert User.blocks?(blocker, blocked)
988 refute User.following?(blocker, blocked)
989 refute User.following?(blocked, blocker)
992 test "blocks tear down blocked->blocker follow relationships" do
993 blocker = insert(:user)
994 blocked = insert(:user)
996 {:ok, blocked} = User.follow(blocked, blocker)
998 refute User.following?(blocker, blocked)
999 assert User.following?(blocked, blocker)
1001 {:ok, _user_relationship} = User.block(blocker, blocked)
1002 blocked = User.get_cached_by_id(blocked.id)
1004 assert User.blocks?(blocker, blocked)
1006 refute User.following?(blocker, blocked)
1007 refute User.following?(blocked, blocker)
1010 test "blocks tear down blocked->blocker subscription relationships" do
1011 blocker = insert(:user)
1012 blocked = insert(:user)
1014 {:ok, _subscription} = User.subscribe(blocked, blocker)
1016 assert User.subscribed_to?(blocked, blocker)
1017 refute User.subscribed_to?(blocker, blocked)
1019 {:ok, _user_relationship} = User.block(blocker, blocked)
1021 assert User.blocks?(blocker, blocked)
1022 refute User.subscribed_to?(blocker, blocked)
1023 refute User.subscribed_to?(blocked, blocker)
1027 describe "domain blocking" do
1028 test "blocks domains" do
1029 user = insert(:user)
1030 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1032 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1034 assert User.blocks?(user, collateral_user)
1037 test "does not block domain with same end" do
1038 user = insert(:user)
1041 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1043 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1045 refute User.blocks?(user, collateral_user)
1048 test "does not block domain with same end if wildcard added" do
1049 user = insert(:user)
1052 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1054 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1056 refute User.blocks?(user, collateral_user)
1059 test "blocks domain with wildcard for subdomain" do
1060 user = insert(:user)
1062 user_from_subdomain =
1063 insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
1065 user_with_two_subdomains =
1067 ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
1070 user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1072 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1074 assert User.blocks?(user, user_from_subdomain)
1075 assert User.blocks?(user, user_with_two_subdomains)
1076 assert User.blocks?(user, user_domain)
1079 test "unblocks domains" do
1080 user = insert(:user)
1081 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1083 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1084 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
1086 refute User.blocks?(user, collateral_user)
1089 test "follows take precedence over domain blocks" do
1090 user = insert(:user)
1091 good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
1093 {:ok, user} = User.block_domain(user, "meanies.social")
1094 {:ok, user} = User.follow(user, good_eggo)
1096 refute User.blocks?(user, good_eggo)
1100 describe "blocks_import" do
1101 test "it imports user blocks from list" do
1102 [user1, user2, user3] = insert_list(3, :user)
1109 {:ok, job} = User.blocks_import(user1, identifiers)
1111 assert {:ok, result} = ObanHelpers.perform(job)
1112 assert is_list(result)
1113 assert result == [user2, user3]
1117 describe "get_recipients_from_activity" do
1118 test "works for announces" do
1119 actor = insert(:user)
1120 user = insert(:user, local: true)
1122 {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
1123 {:ok, announce} = CommonAPI.repeat(activity.id, user)
1125 recipients = User.get_recipients_from_activity(announce)
1127 assert user in recipients
1130 test "get recipients" do
1131 actor = insert(:user)
1132 user = insert(:user, local: true)
1133 user_two = insert(:user, local: false)
1134 addressed = insert(:user, local: true)
1135 addressed_remote = insert(:user, local: false)
1138 CommonAPI.post(actor, %{
1139 status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
1142 assert Enum.map([actor, addressed], & &1.ap_id) --
1143 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1145 {:ok, user} = User.follow(user, actor)
1146 {:ok, _user_two} = User.follow(user_two, actor)
1147 recipients = User.get_recipients_from_activity(activity)
1148 assert length(recipients) == 3
1149 assert user in recipients
1150 assert addressed in recipients
1153 test "has following" do
1154 actor = insert(:user)
1155 user = insert(:user)
1156 user_two = insert(:user)
1157 addressed = insert(:user, local: true)
1160 CommonAPI.post(actor, %{
1161 status: "hey @#{addressed.nickname}"
1164 assert Enum.map([actor, addressed], & &1.ap_id) --
1165 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1167 {:ok, _actor} = User.follow(actor, user)
1168 {:ok, _actor} = User.follow(actor, user_two)
1169 recipients = User.get_recipients_from_activity(activity)
1170 assert length(recipients) == 2
1171 assert addressed in recipients
1175 describe ".deactivate" do
1176 test "can de-activate then re-activate a user" do
1177 user = insert(:user)
1178 assert false == user.deactivated
1179 {:ok, user} = User.deactivate(user)
1180 assert true == user.deactivated
1181 {:ok, user} = User.deactivate(user, false)
1182 assert false == user.deactivated
1185 test "hide a user from followers" do
1186 user = insert(:user)
1187 user2 = insert(:user)
1189 {:ok, user} = User.follow(user, user2)
1190 {:ok, _user} = User.deactivate(user)
1192 user2 = User.get_cached_by_id(user2.id)
1194 assert user2.follower_count == 0
1195 assert [] = User.get_followers(user2)
1198 test "hide a user from friends" do
1199 user = insert(:user)
1200 user2 = insert(:user)
1202 {:ok, user2} = User.follow(user2, user)
1203 assert user2.following_count == 1
1204 assert User.following_count(user2) == 1
1206 {:ok, _user} = User.deactivate(user)
1208 user2 = User.get_cached_by_id(user2.id)
1210 assert refresh_record(user2).following_count == 0
1211 assert user2.following_count == 0
1212 assert User.following_count(user2) == 0
1213 assert [] = User.get_friends(user2)
1216 test "hide a user's statuses from timelines and notifications" do
1217 user = insert(:user)
1218 user2 = insert(:user)
1220 {:ok, user2} = User.follow(user2, user)
1222 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
1224 activity = Repo.preload(activity, :bookmark)
1226 [notification] = Pleroma.Notification.for_user(user2)
1227 assert notification.activity.id == activity.id
1229 assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
1231 assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
1232 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1236 {:ok, _user} = User.deactivate(user)
1238 assert [] == ActivityPub.fetch_public_activities(%{})
1239 assert [] == Pleroma.Notification.for_user(user2)
1242 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1248 describe "approve" do
1249 test "approves a user" do
1250 user = insert(:user, approval_pending: true)
1251 assert true == user.approval_pending
1252 {:ok, user} = User.approve(user)
1253 assert false == user.approval_pending
1256 test "approves a list of users" do
1257 unapproved_users = [
1258 insert(:user, approval_pending: true),
1259 insert(:user, approval_pending: true),
1260 insert(:user, approval_pending: true)
1263 {:ok, users} = User.approve(unapproved_users)
1265 assert Enum.count(users) == 3
1267 Enum.each(users, fn user ->
1268 assert false == user.approval_pending
1273 describe "delete" do
1275 {:ok, user} = insert(:user) |> User.set_cache()
1280 setup do: clear_config([:instance, :federating])
1282 test ".delete_user_activities deletes all create activities", %{user: user} do
1283 {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
1285 User.delete_user_activities(user)
1287 # TODO: Test removal favorites, repeats, delete activities.
1288 refute Activity.get_by_id(activity.id)
1291 test "it deactivates a user, all follow relationships and all activities", %{user: user} do
1292 follower = insert(:user)
1293 {:ok, follower} = User.follow(follower, user)
1295 locked_user = insert(:user, name: "locked", locked: true)
1296 {:ok, _} = User.follow(user, locked_user, :follow_pending)
1298 object = insert(:note, user: user)
1299 activity = insert(:note_activity, user: user, note: object)
1301 object_two = insert(:note, user: follower)
1302 activity_two = insert(:note_activity, user: follower, note: object_two)
1304 {:ok, like} = CommonAPI.favorite(user, activity_two.id)
1305 {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
1306 {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
1308 {:ok, job} = User.delete(user)
1309 {:ok, _user} = ObanHelpers.perform(job)
1311 follower = User.get_cached_by_id(follower.id)
1313 refute User.following?(follower, user)
1314 assert %{deactivated: true} = User.get_by_id(user.id)
1316 assert [] == User.get_follow_requests(locked_user)
1320 |> Activity.Queries.by_actor()
1322 |> Enum.map(fn act -> act.data["type"] end)
1324 assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
1326 refute Activity.get_by_id(activity.id)
1327 refute Activity.get_by_id(like.id)
1328 refute Activity.get_by_id(like_two.id)
1329 refute Activity.get_by_id(repeat.id)
1333 describe "delete/1 when confirmation is pending" do
1335 user = insert(:user, confirmation_pending: true)
1339 test "deletes user from database when activation required", %{user: user} do
1340 clear_config([:instance, :account_activation_required], true)
1342 {:ok, job} = User.delete(user)
1343 {:ok, _} = ObanHelpers.perform(job)
1345 refute User.get_cached_by_id(user.id)
1346 refute User.get_by_id(user.id)
1349 test "deactivates user when activation is not required", %{user: user} do
1350 clear_config([:instance, :account_activation_required], false)
1352 {:ok, job} = User.delete(user)
1353 {:ok, _} = ObanHelpers.perform(job)
1355 assert %{deactivated: true} = User.get_cached_by_id(user.id)
1356 assert %{deactivated: true} = User.get_by_id(user.id)
1360 test "delete/1 when approval is pending deletes the user" do
1361 user = insert(:user, approval_pending: true)
1364 {:ok, job} = User.delete(user)
1365 {:ok, _} = ObanHelpers.perform(job)
1367 refute User.get_cached_by_id(user.id)
1368 refute User.get_by_id(user.id)
1371 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1372 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1375 describe "per-user rich-text filtering" do
1376 test "html_filter_policy returns default policies, when rich-text is enabled" do
1377 user = insert(:user)
1379 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1382 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1383 user = insert(:user, no_rich_text: true)
1385 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1389 describe "caching" do
1390 test "invalidate_cache works" do
1391 user = insert(:user)
1393 User.set_cache(user)
1394 User.invalidate_cache(user)
1396 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1397 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1400 test "User.delete() plugs any possible zombie objects" do
1401 user = insert(:user)
1403 {:ok, job} = User.delete(user)
1404 {:ok, _} = ObanHelpers.perform(job)
1406 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1408 assert cached_user != user
1410 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1412 assert cached_user != user
1416 describe "account_status/1" do
1417 setup do: clear_config([:instance, :account_activation_required])
1419 test "return confirmation_pending for unconfirm user" do
1420 Pleroma.Config.put([:instance, :account_activation_required], true)
1421 user = insert(:user, confirmation_pending: true)
1422 assert User.account_status(user) == :confirmation_pending
1425 test "return active for confirmed user" do
1426 Pleroma.Config.put([:instance, :account_activation_required], true)
1427 user = insert(:user, confirmation_pending: false)
1428 assert User.account_status(user) == :active
1431 test "return active for remote user" do
1432 user = insert(:user, local: false)
1433 assert User.account_status(user) == :active
1436 test "returns :password_reset_pending for user with reset password" do
1437 user = insert(:user, password_reset_pending: true)
1438 assert User.account_status(user) == :password_reset_pending
1441 test "returns :deactivated for deactivated user" do
1442 user = insert(:user, local: true, confirmation_pending: false, deactivated: true)
1443 assert User.account_status(user) == :deactivated
1446 test "returns :approval_pending for unapproved user" do
1447 user = insert(:user, local: true, approval_pending: true)
1448 assert User.account_status(user) == :approval_pending
1450 user = insert(:user, local: true, confirmation_pending: true, approval_pending: true)
1451 assert User.account_status(user) == :approval_pending
1455 describe "superuser?/1" do
1456 test "returns false for unprivileged users" do
1457 user = insert(:user, local: true)
1459 refute User.superuser?(user)
1462 test "returns false for remote users" do
1463 user = insert(:user, local: false)
1464 remote_admin_user = insert(:user, local: false, is_admin: true)
1466 refute User.superuser?(user)
1467 refute User.superuser?(remote_admin_user)
1470 test "returns true for local moderators" do
1471 user = insert(:user, local: true, is_moderator: true)
1473 assert User.superuser?(user)
1476 test "returns true for local admins" do
1477 user = insert(:user, local: true, is_admin: true)
1479 assert User.superuser?(user)
1483 describe "invisible?/1" do
1484 test "returns true for an invisible user" do
1485 user = insert(:user, local: true, invisible: true)
1487 assert User.invisible?(user)
1490 test "returns false for a non-invisible user" do
1491 user = insert(:user, local: true)
1493 refute User.invisible?(user)
1497 describe "visible_for/2" do
1498 test "returns true when the account is itself" do
1499 user = insert(:user, local: true)
1501 assert User.visible_for(user, user) == :visible
1504 test "returns false when the account is unauthenticated and auth is required" do
1505 Pleroma.Config.put([:instance, :account_activation_required], true)
1507 user = insert(:user, local: true, confirmation_pending: true)
1508 other_user = insert(:user, local: true)
1510 refute User.visible_for(user, other_user) == :visible
1513 test "returns true when the account is unauthenticated and auth is not required" do
1514 user = insert(:user, local: true, confirmation_pending: true)
1515 other_user = insert(:user, local: true)
1517 assert User.visible_for(user, other_user) == :visible
1520 test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
1521 Pleroma.Config.put([:instance, :account_activation_required], true)
1523 user = insert(:user, local: true, confirmation_pending: true)
1524 other_user = insert(:user, local: true, is_admin: true)
1526 assert User.visible_for(user, other_user) == :visible
1530 describe "parse_bio/2" do
1531 test "preserves hosts in user links text" do
1532 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1533 user = insert(:user)
1534 bio = "A.k.a. @nick@domain.com"
1537 ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
1539 }" rel="ugc">@<span>nick@domain.com</span></a></span>)
1541 assert expected_text == User.parse_bio(bio, user)
1544 test "Adds rel=me on linkbacked urls" do
1545 user = insert(:user, ap_id: "https://social.example.org/users/lain")
1547 bio = "http://example.com/rel_me/null"
1548 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1549 assert expected_text == User.parse_bio(bio, user)
1551 bio = "http://example.com/rel_me/link"
1552 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1553 assert expected_text == User.parse_bio(bio, user)
1555 bio = "http://example.com/rel_me/anchor"
1556 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1557 assert expected_text == User.parse_bio(bio, user)
1561 test "follower count is updated when a follower is blocked" do
1562 user = insert(:user)
1563 follower = insert(:user)
1564 follower2 = insert(:user)
1565 follower3 = insert(:user)
1567 {:ok, follower} = User.follow(follower, user)
1568 {:ok, _follower2} = User.follow(follower2, user)
1569 {:ok, _follower3} = User.follow(follower3, user)
1571 {:ok, _user_relationship} = User.block(user, follower)
1572 user = refresh_record(user)
1574 assert user.follower_count == 2
1577 describe "list_inactive_users_query/1" do
1578 defp days_ago(days) do
1580 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
1581 -days * 60 * 60 * 24,
1586 test "Users are inactive by default" do
1590 Enum.map(1..total, fn _ ->
1591 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1594 inactive_users_ids =
1595 Pleroma.User.list_inactive_users_query()
1596 |> Pleroma.Repo.all()
1597 |> Enum.map(& &1.id)
1599 Enum.each(users, fn user ->
1600 assert user.id in inactive_users_ids
1604 test "Only includes users who has no recent activity" do
1608 Enum.map(1..total, fn _ ->
1609 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1612 {inactive, active} = Enum.split(users, trunc(total / 2))
1614 Enum.map(active, fn user ->
1615 to = Enum.random(users -- [user])
1618 CommonAPI.post(user, %{
1619 status: "hey @#{to.nickname}"
1623 inactive_users_ids =
1624 Pleroma.User.list_inactive_users_query()
1625 |> Pleroma.Repo.all()
1626 |> Enum.map(& &1.id)
1628 Enum.each(active, fn user ->
1629 refute user.id in inactive_users_ids
1632 Enum.each(inactive, fn user ->
1633 assert user.id in inactive_users_ids
1637 test "Only includes users with no read notifications" do
1641 Enum.map(1..total, fn _ ->
1642 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1645 [sender | recipients] = users
1646 {inactive, active} = Enum.split(recipients, trunc(total / 2))
1648 Enum.each(recipients, fn to ->
1650 CommonAPI.post(sender, %{
1651 status: "hey @#{to.nickname}"
1655 CommonAPI.post(sender, %{
1656 status: "hey again @#{to.nickname}"
1660 Enum.each(active, fn user ->
1661 [n1, _n2] = Pleroma.Notification.for_user(user)
1662 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
1665 inactive_users_ids =
1666 Pleroma.User.list_inactive_users_query()
1667 |> Pleroma.Repo.all()
1668 |> Enum.map(& &1.id)
1670 Enum.each(active, fn user ->
1671 refute user.id in inactive_users_ids
1674 Enum.each(inactive, fn user ->
1675 assert user.id in inactive_users_ids
1680 describe "toggle_confirmation/1" do
1681 test "if user is confirmed" do
1682 user = insert(:user, confirmation_pending: false)
1683 {:ok, user} = User.toggle_confirmation(user)
1685 assert user.confirmation_pending
1686 assert user.confirmation_token
1689 test "if user is unconfirmed" do
1690 user = insert(:user, confirmation_pending: true, confirmation_token: "some token")
1691 {:ok, user} = User.toggle_confirmation(user)
1693 refute user.confirmation_pending
1694 refute user.confirmation_token
1698 describe "ensure_keys_present" do
1699 test "it creates keys for a user and stores them in info" do
1700 user = insert(:user)
1701 refute is_binary(user.keys)
1702 {:ok, user} = User.ensure_keys_present(user)
1703 assert is_binary(user.keys)
1706 test "it doesn't create keys if there already are some" do
1707 user = insert(:user, keys: "xxx")
1708 {:ok, user} = User.ensure_keys_present(user)
1709 assert user.keys == "xxx"
1713 describe "get_ap_ids_by_nicknames" do
1714 test "it returns a list of AP ids for a given set of nicknames" do
1715 user = insert(:user)
1716 user_two = insert(:user)
1718 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
1719 assert length(ap_ids) == 2
1720 assert user.ap_id in ap_ids
1721 assert user_two.ap_id in ap_ids
1725 describe "sync followers count" do
1727 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
1728 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
1729 insert(:user, local: true)
1730 insert(:user, local: false, deactivated: true)
1731 {:ok, user1: user1, user2: user2}
1734 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
1735 [fdb_user1] = User.external_users(limit: 1)
1737 assert fdb_user1.ap_id
1738 assert fdb_user1.ap_id == user1.ap_id
1739 assert fdb_user1.id == user1.id
1741 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
1743 assert fdb_user2.ap_id
1744 assert fdb_user2.ap_id == user2.ap_id
1745 assert fdb_user2.id == user2.id
1747 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
1751 describe "is_internal_user?/1" do
1752 test "non-internal user returns false" do
1753 user = insert(:user)
1754 refute User.is_internal_user?(user)
1757 test "user with no nickname returns true" do
1758 user = insert(:user, %{nickname: nil})
1759 assert User.is_internal_user?(user)
1762 test "user with internal-prefixed nickname returns true" do
1763 user = insert(:user, %{nickname: "internal.test"})
1764 assert User.is_internal_user?(user)
1768 describe "update_and_set_cache/1" do
1769 test "returns error when user is stale instead Ecto.StaleEntryError" do
1770 user = insert(:user)
1772 changeset = Ecto.Changeset.change(user, bio: "test")
1776 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
1777 User.update_and_set_cache(changeset)
1780 test "performs update cache if user updated" do
1781 user = insert(:user)
1782 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1784 changeset = Ecto.Changeset.change(user, bio: "test-bio")
1786 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
1787 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1788 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
1792 describe "following/followers synchronization" do
1793 setup do: clear_config([:instance, :external_user_synchronization])
1795 test "updates the counters normally on following/getting a follow when disabled" do
1796 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1797 user = insert(:user)
1802 follower_address: "http://localhost:4001/users/masto_closed/followers",
1803 following_address: "http://localhost:4001/users/masto_closed/following",
1807 assert other_user.following_count == 0
1808 assert other_user.follower_count == 0
1810 {:ok, user} = Pleroma.User.follow(user, other_user)
1811 other_user = Pleroma.User.get_by_id(other_user.id)
1813 assert user.following_count == 1
1814 assert other_user.follower_count == 1
1817 test "syncronizes the counters with the remote instance for the followed when enabled" do
1818 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1820 user = insert(:user)
1825 follower_address: "http://localhost:4001/users/masto_closed/followers",
1826 following_address: "http://localhost:4001/users/masto_closed/following",
1830 assert other_user.following_count == 0
1831 assert other_user.follower_count == 0
1833 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1834 {:ok, _user} = User.follow(user, other_user)
1835 other_user = User.get_by_id(other_user.id)
1837 assert other_user.follower_count == 437
1840 test "syncronizes the counters with the remote instance for the follower when enabled" do
1841 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1843 user = insert(:user)
1848 follower_address: "http://localhost:4001/users/masto_closed/followers",
1849 following_address: "http://localhost:4001/users/masto_closed/following",
1853 assert other_user.following_count == 0
1854 assert other_user.follower_count == 0
1856 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1857 {:ok, other_user} = User.follow(other_user, user)
1859 assert other_user.following_count == 152
1863 describe "change_email/2" do
1865 [user: insert(:user)]
1868 test "blank email returns error", %{user: user} do
1869 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
1870 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
1873 test "non unique email returns error", %{user: user} do
1874 %{email: email} = insert(:user)
1876 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
1877 User.change_email(user, email)
1880 test "invalid email returns error", %{user: user} do
1881 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
1882 User.change_email(user, "cofe")
1885 test "changes email", %{user: user} do
1886 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
1890 describe "get_cached_by_nickname_or_id" do
1892 local_user = insert(:user)
1893 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
1895 [local_user: local_user, remote_user: remote_user]
1898 setup do: clear_config([:instance, :limit_to_local_content])
1900 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
1901 remote_user: remote_user
1903 Pleroma.Config.put([:instance, :limit_to_local_content], false)
1904 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
1906 Pleroma.Config.put([:instance, :limit_to_local_content], true)
1907 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
1909 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1910 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
1913 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
1914 %{remote_user: remote_user} do
1915 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1916 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
1919 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
1920 %{remote_user: remote_user, local_user: local_user} do
1921 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1922 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
1925 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
1926 %{remote_user: remote_user} do
1927 Pleroma.Config.put([:instance, :limit_to_local_content], true)
1928 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
1931 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
1932 %{local_user: local_user} do
1933 Pleroma.Config.put([:instance, :limit_to_local_content], false)
1934 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
1936 Pleroma.Config.put([:instance, :limit_to_local_content], true)
1937 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
1939 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1940 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
1944 describe "update_email_notifications/2" do
1946 user = insert(:user, email_notifications: %{"digest" => true})
1951 test "Notifications are updated", %{user: user} do
1952 true = user.email_notifications["digest"]
1953 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
1954 assert result.email_notifications["digest"] == false
1958 test "avatar fallback" do
1959 user = insert(:user)
1960 assert User.avatar_url(user) =~ "/images/avi.png"
1962 clear_config([:assets, :default_user_avatar], "avatar.png")
1964 user = User.get_cached_by_nickname_or_id(user.nickname)
1965 assert User.avatar_url(user) =~ "avatar.png"
1967 assert User.avatar_url(user, no_default: true) == nil