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 direct message")
417 cng = User.register_changeset(%User{}, @full_user_data)
418 {:ok, registered_user} = User.register(cng)
419 ObanHelpers.perform_all()
421 activity = Repo.one(Pleroma.Activity)
422 assert registered_user.ap_id in activity.recipients
423 assert Object.normalize(activity).data["content"] =~ "direct message"
424 assert activity.actor == welcome_user.ap_id
427 test "it sends a welcome chat message if it is set" do
428 welcome_user = insert(:user)
429 Pleroma.Config.put([:welcome, :chat_message, :enabled], true)
430 Pleroma.Config.put([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
431 Pleroma.Config.put([:welcome, :chat_message, :message], "Hello, this is a chat message")
433 cng = User.register_changeset(%User{}, @full_user_data)
434 {:ok, registered_user} = User.register(cng)
435 ObanHelpers.perform_all()
437 activity = Repo.one(Pleroma.Activity)
438 assert registered_user.ap_id in activity.recipients
439 assert Object.normalize(activity).data["content"] =~ "chat message"
440 assert activity.actor == welcome_user.ap_id
443 test "it sends a welcome email message if it is set" do
444 welcome_user = insert(:user)
445 Pleroma.Config.put([:welcome, :email, :enabled], true)
446 Pleroma.Config.put([:welcome, :email, :sender], welcome_user.email)
449 [:welcome, :email, :subject],
450 "Hello, welcome to cool site: <%= instance_name %>"
453 instance_name = Pleroma.Config.get([:instance, :name])
455 cng = User.register_changeset(%User{}, @full_user_data)
456 {:ok, registered_user} = User.register(cng)
457 ObanHelpers.perform_all()
460 from: {instance_name, welcome_user.email},
461 to: {registered_user.name, registered_user.email},
462 subject: "Hello, welcome to cool site: #{instance_name}",
463 html_body: "Welcome to #{instance_name}"
467 test "it sends a confirm email" do
468 Pleroma.Config.put([:instance, :account_activation_required], true)
470 cng = User.register_changeset(%User{}, @full_user_data)
471 {:ok, registered_user} = User.register(cng)
472 ObanHelpers.perform_all()
473 assert_email_sent(Pleroma.Emails.UserEmail.account_confirmation_email(registered_user))
476 test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do
477 Pleroma.Config.put([:instance, :account_activation_required], true)
481 |> Enum.each(fn key ->
482 params = Map.delete(@full_user_data, key)
483 changeset = User.register_changeset(%User{}, params)
485 assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
489 test "it requires an name, nickname and password, bio and email are optional when account_activation_required is disabled" do
490 Pleroma.Config.put([:instance, :account_activation_required], false)
494 |> Enum.each(fn key ->
495 params = Map.delete(@full_user_data, key)
496 changeset = User.register_changeset(%User{}, params)
498 assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid?
502 test "it restricts certain nicknames" do
503 [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
505 assert is_bitstring(restricted_name)
509 |> Map.put(:nickname, restricted_name)
511 changeset = User.register_changeset(%User{}, params)
513 refute changeset.valid?
516 test "it blocks blacklisted email domains" do
517 clear_config([User, :email_blacklist], ["trolling.world"])
520 params = Map.put(@full_user_data, :email, "troll@trolling.world")
521 changeset = User.register_changeset(%User{}, params)
522 refute changeset.valid?
524 # Block with subdomain match
525 params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world")
526 changeset = User.register_changeset(%User{}, params)
527 refute changeset.valid?
529 # Pass with different domains that are similar
530 params = Map.put(@full_user_data, :email, "troll@gnomestrolling.world")
531 changeset = User.register_changeset(%User{}, params)
532 assert changeset.valid?
534 params = Map.put(@full_user_data, :email, "troll@trolling.world.us")
535 changeset = User.register_changeset(%User{}, params)
536 assert changeset.valid?
539 test "it sets the password_hash and ap_id" do
540 changeset = User.register_changeset(%User{}, @full_user_data)
542 assert changeset.valid?
544 assert is_binary(changeset.changes[:password_hash])
545 assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
547 assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
550 test "it sets the 'accepts_chat_messages' set to true" do
551 changeset = User.register_changeset(%User{}, @full_user_data)
552 assert changeset.valid?
554 {:ok, user} = Repo.insert(changeset)
556 assert user.accepts_chat_messages
559 test "it creates a confirmed user" do
560 changeset = User.register_changeset(%User{}, @full_user_data)
561 assert changeset.valid?
563 {:ok, user} = Repo.insert(changeset)
565 refute user.confirmation_pending
569 describe "user registration, with :account_activation_required" do
575 password_confirmation: "test",
576 email: "email@example.com"
578 setup do: clear_config([:instance, :account_activation_required], true)
580 test "it creates unconfirmed user" do
581 changeset = User.register_changeset(%User{}, @full_user_data)
582 assert changeset.valid?
584 {:ok, user} = Repo.insert(changeset)
586 assert user.confirmation_pending
587 assert user.confirmation_token
590 test "it creates confirmed user if :confirmed option is given" do
591 changeset = User.register_changeset(%User{}, @full_user_data, need_confirmation: false)
592 assert changeset.valid?
594 {:ok, user} = Repo.insert(changeset)
596 refute user.confirmation_pending
597 refute user.confirmation_token
601 describe "user registration, with :account_approval_required" do
607 password_confirmation: "test",
608 email: "email@example.com",
609 registration_reason: "I'm a cool guy :)"
611 setup do: clear_config([:instance, :account_approval_required], true)
613 test "it creates unapproved user" do
614 changeset = User.register_changeset(%User{}, @full_user_data)
615 assert changeset.valid?
617 {:ok, user} = Repo.insert(changeset)
619 assert user.approval_pending
620 assert user.registration_reason == "I'm a cool guy :)"
623 test "it restricts length of registration reason" do
624 reason_limit = Pleroma.Config.get([:instance, :registration_reason_length])
626 assert is_integer(reason_limit)
631 :registration_reason,
632 "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."
635 changeset = User.register_changeset(%User{}, params)
637 refute changeset.valid?
641 describe "get_or_fetch/1" do
642 test "gets an existing user by nickname" do
644 {:ok, fetched_user} = User.get_or_fetch(user.nickname)
646 assert user == fetched_user
649 test "gets an existing user by ap_id" do
650 ap_id = "http://mastodon.example.org/users/admin"
656 nickname: "admin@mastodon.example.org",
660 {:ok, fetched_user} = User.get_or_fetch(ap_id)
661 freshed_user = refresh_record(user)
662 assert freshed_user == fetched_user
666 describe "fetching a user from nickname or trying to build one" do
667 test "gets an existing user" do
669 {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
671 assert user == fetched_user
674 test "gets an existing user, case insensitive" do
675 user = insert(:user, nickname: "nick")
676 {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
678 assert user == fetched_user
681 test "gets an existing user by fully qualified nickname" do
684 {:ok, fetched_user} =
685 User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
687 assert user == fetched_user
690 test "gets an existing user by fully qualified nickname, case insensitive" do
691 user = insert(:user, nickname: "nick")
692 casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
694 {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
696 assert user == fetched_user
699 @tag capture_log: true
700 test "returns nil if no user could be fetched" do
701 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
702 assert fetched_user == "not found nonexistant@social.heldscal.la"
705 test "returns nil for nonexistant local user" do
706 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
707 assert fetched_user == "not found nonexistant"
710 test "updates an existing user, if stale" do
711 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
717 nickname: "admin@mastodon.example.org",
718 ap_id: "http://mastodon.example.org/users/admin",
719 last_refreshed_at: a_week_ago
722 assert orig_user.last_refreshed_at == a_week_ago
724 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
728 refute user.last_refreshed_at == orig_user.last_refreshed_at
731 test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
732 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
738 nickname: "admin@mastodon.example.org",
739 ap_id: "http://mastodon.example.org/users/harinezumigari",
740 last_refreshed_at: a_week_ago
743 assert orig_user.last_refreshed_at == a_week_ago
745 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
749 refute user.id == orig_user.id
751 orig_user = User.get_by_id(orig_user.id)
753 assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
756 @tag capture_log: true
757 test "it returns the old user if stale, but unfetchable" do
758 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
764 nickname: "admin@mastodon.example.org",
765 ap_id: "http://mastodon.example.org/users/raymoo",
766 last_refreshed_at: a_week_ago
769 assert orig_user.last_refreshed_at == a_week_ago
771 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/raymoo")
773 assert user.last_refreshed_at == orig_user.last_refreshed_at
777 test "returns an ap_id for a user" do
780 assert User.ap_id(user) ==
781 Pleroma.Web.Router.Helpers.user_feed_url(
782 Pleroma.Web.Endpoint,
788 test "returns an ap_followers link for a user" do
791 assert User.ap_followers(user) ==
792 Pleroma.Web.Router.Helpers.user_feed_url(
793 Pleroma.Web.Endpoint,
799 describe "remote user changeset" do
805 avatar: %{some: "avatar"}
807 setup do: clear_config([:instance, :user_bio_length])
808 setup do: clear_config([:instance, :user_name_length])
810 test "it confirms validity" do
811 cs = User.remote_user_changeset(@valid_remote)
815 test "it sets the follower_adress" do
816 cs = User.remote_user_changeset(@valid_remote)
817 # remote users get a fake local follower address
818 assert cs.changes.follower_address ==
819 User.ap_followers(%User{nickname: @valid_remote[:nickname]})
822 test "it enforces the fqn format for nicknames" do
823 cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})
824 assert Ecto.Changeset.get_field(cs, :local) == false
825 assert cs.changes.avatar
829 test "it has required fields" do
831 |> Enum.each(fn field ->
832 cs = User.remote_user_changeset(Map.delete(@valid_remote, field))
838 describe "followers and friends" do
839 test "gets all followers for a given user" do
841 follower_one = insert(:user)
842 follower_two = insert(:user)
843 not_follower = insert(:user)
845 {:ok, follower_one} = User.follow(follower_one, user)
846 {:ok, follower_two} = User.follow(follower_two, user)
848 res = User.get_followers(user)
850 assert Enum.member?(res, follower_one)
851 assert Enum.member?(res, follower_two)
852 refute Enum.member?(res, not_follower)
855 test "gets all friends (followed users) for a given user" do
857 followed_one = insert(:user)
858 followed_two = insert(:user)
859 not_followed = insert(:user)
861 {:ok, user} = User.follow(user, followed_one)
862 {:ok, user} = User.follow(user, followed_two)
864 res = User.get_friends(user)
866 followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
867 followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
868 assert Enum.member?(res, followed_one)
869 assert Enum.member?(res, followed_two)
870 refute Enum.member?(res, not_followed)
874 describe "updating note and follower count" do
875 test "it sets the note_count property" do
878 user = User.get_cached_by_ap_id(note.data["actor"])
880 assert user.note_count == 0
882 {:ok, user} = User.update_note_count(user)
884 assert user.note_count == 1
887 test "it increases the note_count property" do
889 user = User.get_cached_by_ap_id(note.data["actor"])
891 assert user.note_count == 0
893 {:ok, user} = User.increase_note_count(user)
895 assert user.note_count == 1
897 {:ok, user} = User.increase_note_count(user)
899 assert user.note_count == 2
902 test "it decreases the note_count property" do
904 user = User.get_cached_by_ap_id(note.data["actor"])
906 assert user.note_count == 0
908 {:ok, user} = User.increase_note_count(user)
910 assert user.note_count == 1
912 {:ok, user} = User.decrease_note_count(user)
914 assert user.note_count == 0
916 {:ok, user} = User.decrease_note_count(user)
918 assert user.note_count == 0
921 test "it sets the follower_count property" do
923 follower = insert(:user)
925 User.follow(follower, user)
927 assert user.follower_count == 0
929 {:ok, user} = User.update_follower_count(user)
931 assert user.follower_count == 1
935 describe "follow_import" do
936 test "it imports user followings from list" do
937 [user1, user2, user3] = insert_list(3, :user)
944 {:ok, job} = User.follow_import(user1, identifiers)
946 assert {:ok, result} = ObanHelpers.perform(job)
947 assert is_list(result)
948 assert result == [user2, user3]
953 test "it mutes people" do
955 muted_user = insert(:user)
957 refute User.mutes?(user, muted_user)
958 refute User.muted_notifications?(user, muted_user)
960 {:ok, _user_relationships} = User.mute(user, muted_user)
962 assert User.mutes?(user, muted_user)
963 assert User.muted_notifications?(user, muted_user)
966 test "it unmutes users" do
968 muted_user = insert(:user)
970 {:ok, _user_relationships} = User.mute(user, muted_user)
971 {:ok, _user_mute} = User.unmute(user, muted_user)
973 refute User.mutes?(user, muted_user)
974 refute User.muted_notifications?(user, muted_user)
977 test "it mutes user without notifications" do
979 muted_user = insert(:user)
981 refute User.mutes?(user, muted_user)
982 refute User.muted_notifications?(user, muted_user)
984 {:ok, _user_relationships} = User.mute(user, muted_user, false)
986 assert User.mutes?(user, muted_user)
987 refute User.muted_notifications?(user, muted_user)
992 test "it blocks people" do
994 blocked_user = insert(:user)
996 refute User.blocks?(user, blocked_user)
998 {:ok, _user_relationship} = User.block(user, blocked_user)
1000 assert User.blocks?(user, blocked_user)
1003 test "it unblocks users" do
1004 user = insert(:user)
1005 blocked_user = insert(:user)
1007 {:ok, _user_relationship} = User.block(user, blocked_user)
1008 {:ok, _user_block} = User.unblock(user, blocked_user)
1010 refute User.blocks?(user, blocked_user)
1013 test "blocks tear down cyclical follow relationships" do
1014 blocker = insert(:user)
1015 blocked = insert(:user)
1017 {:ok, blocker} = User.follow(blocker, blocked)
1018 {:ok, blocked} = User.follow(blocked, blocker)
1020 assert User.following?(blocker, blocked)
1021 assert User.following?(blocked, blocker)
1023 {:ok, _user_relationship} = User.block(blocker, blocked)
1024 blocked = User.get_cached_by_id(blocked.id)
1026 assert User.blocks?(blocker, blocked)
1028 refute User.following?(blocker, blocked)
1029 refute User.following?(blocked, blocker)
1032 test "blocks tear down blocker->blocked follow relationships" do
1033 blocker = insert(:user)
1034 blocked = insert(:user)
1036 {:ok, blocker} = User.follow(blocker, blocked)
1038 assert User.following?(blocker, blocked)
1039 refute User.following?(blocked, blocker)
1041 {:ok, _user_relationship} = User.block(blocker, blocked)
1042 blocked = User.get_cached_by_id(blocked.id)
1044 assert User.blocks?(blocker, blocked)
1046 refute User.following?(blocker, blocked)
1047 refute User.following?(blocked, blocker)
1050 test "blocks tear down blocked->blocker follow relationships" do
1051 blocker = insert(:user)
1052 blocked = insert(:user)
1054 {:ok, blocked} = User.follow(blocked, blocker)
1056 refute User.following?(blocker, blocked)
1057 assert User.following?(blocked, blocker)
1059 {:ok, _user_relationship} = User.block(blocker, blocked)
1060 blocked = User.get_cached_by_id(blocked.id)
1062 assert User.blocks?(blocker, blocked)
1064 refute User.following?(blocker, blocked)
1065 refute User.following?(blocked, blocker)
1068 test "blocks tear down blocked->blocker subscription relationships" do
1069 blocker = insert(:user)
1070 blocked = insert(:user)
1072 {:ok, _subscription} = User.subscribe(blocked, blocker)
1074 assert User.subscribed_to?(blocked, blocker)
1075 refute User.subscribed_to?(blocker, blocked)
1077 {:ok, _user_relationship} = User.block(blocker, blocked)
1079 assert User.blocks?(blocker, blocked)
1080 refute User.subscribed_to?(blocker, blocked)
1081 refute User.subscribed_to?(blocked, blocker)
1085 describe "domain blocking" do
1086 test "blocks domains" do
1087 user = insert(:user)
1088 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1090 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1092 assert User.blocks?(user, collateral_user)
1095 test "does not block domain with same end" do
1096 user = insert(:user)
1099 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1101 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1103 refute User.blocks?(user, collateral_user)
1106 test "does not block domain with same end if wildcard added" do
1107 user = insert(:user)
1110 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1112 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1114 refute User.blocks?(user, collateral_user)
1117 test "blocks domain with wildcard for subdomain" do
1118 user = insert(:user)
1120 user_from_subdomain =
1121 insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
1123 user_with_two_subdomains =
1125 ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
1128 user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1130 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1132 assert User.blocks?(user, user_from_subdomain)
1133 assert User.blocks?(user, user_with_two_subdomains)
1134 assert User.blocks?(user, user_domain)
1137 test "unblocks domains" do
1138 user = insert(:user)
1139 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1141 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1142 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
1144 refute User.blocks?(user, collateral_user)
1147 test "follows take precedence over domain blocks" do
1148 user = insert(:user)
1149 good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
1151 {:ok, user} = User.block_domain(user, "meanies.social")
1152 {:ok, user} = User.follow(user, good_eggo)
1154 refute User.blocks?(user, good_eggo)
1158 describe "blocks_import" do
1159 test "it imports user blocks from list" do
1160 [user1, user2, user3] = insert_list(3, :user)
1167 {:ok, job} = User.blocks_import(user1, identifiers)
1169 assert {:ok, result} = ObanHelpers.perform(job)
1170 assert is_list(result)
1171 assert result == [user2, user3]
1175 describe "get_recipients_from_activity" do
1176 test "works for announces" do
1177 actor = insert(:user)
1178 user = insert(:user, local: true)
1180 {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
1181 {:ok, announce} = CommonAPI.repeat(activity.id, user)
1183 recipients = User.get_recipients_from_activity(announce)
1185 assert user in recipients
1188 test "get recipients" do
1189 actor = insert(:user)
1190 user = insert(:user, local: true)
1191 user_two = insert(:user, local: false)
1192 addressed = insert(:user, local: true)
1193 addressed_remote = insert(:user, local: false)
1196 CommonAPI.post(actor, %{
1197 status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
1200 assert Enum.map([actor, addressed], & &1.ap_id) --
1201 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1203 {:ok, user} = User.follow(user, actor)
1204 {:ok, _user_two} = User.follow(user_two, actor)
1205 recipients = User.get_recipients_from_activity(activity)
1206 assert length(recipients) == 3
1207 assert user in recipients
1208 assert addressed in recipients
1211 test "has following" do
1212 actor = insert(:user)
1213 user = insert(:user)
1214 user_two = insert(:user)
1215 addressed = insert(:user, local: true)
1218 CommonAPI.post(actor, %{
1219 status: "hey @#{addressed.nickname}"
1222 assert Enum.map([actor, addressed], & &1.ap_id) --
1223 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1225 {:ok, _actor} = User.follow(actor, user)
1226 {:ok, _actor} = User.follow(actor, user_two)
1227 recipients = User.get_recipients_from_activity(activity)
1228 assert length(recipients) == 2
1229 assert addressed in recipients
1233 describe ".deactivate" do
1234 test "can de-activate then re-activate a user" do
1235 user = insert(:user)
1236 assert false == user.deactivated
1237 {:ok, user} = User.deactivate(user)
1238 assert true == user.deactivated
1239 {:ok, user} = User.deactivate(user, false)
1240 assert false == user.deactivated
1243 test "hide a user from followers" do
1244 user = insert(:user)
1245 user2 = insert(:user)
1247 {:ok, user} = User.follow(user, user2)
1248 {:ok, _user} = User.deactivate(user)
1250 user2 = User.get_cached_by_id(user2.id)
1252 assert user2.follower_count == 0
1253 assert [] = User.get_followers(user2)
1256 test "hide a user from friends" do
1257 user = insert(:user)
1258 user2 = insert(:user)
1260 {:ok, user2} = User.follow(user2, user)
1261 assert user2.following_count == 1
1262 assert User.following_count(user2) == 1
1264 {:ok, _user} = User.deactivate(user)
1266 user2 = User.get_cached_by_id(user2.id)
1268 assert refresh_record(user2).following_count == 0
1269 assert user2.following_count == 0
1270 assert User.following_count(user2) == 0
1271 assert [] = User.get_friends(user2)
1274 test "hide a user's statuses from timelines and notifications" do
1275 user = insert(:user)
1276 user2 = insert(:user)
1278 {:ok, user2} = User.follow(user2, user)
1280 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
1282 activity = Repo.preload(activity, :bookmark)
1284 [notification] = Pleroma.Notification.for_user(user2)
1285 assert notification.activity.id == activity.id
1287 assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
1289 assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
1290 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1294 {:ok, _user} = User.deactivate(user)
1296 assert [] == ActivityPub.fetch_public_activities(%{})
1297 assert [] == Pleroma.Notification.for_user(user2)
1300 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1306 describe "approve" do
1307 test "approves a user" do
1308 user = insert(:user, approval_pending: true)
1309 assert true == user.approval_pending
1310 {:ok, user} = User.approve(user)
1311 assert false == user.approval_pending
1314 test "approves a list of users" do
1315 unapproved_users = [
1316 insert(:user, approval_pending: true),
1317 insert(:user, approval_pending: true),
1318 insert(:user, approval_pending: true)
1321 {:ok, users} = User.approve(unapproved_users)
1323 assert Enum.count(users) == 3
1325 Enum.each(users, fn user ->
1326 assert false == user.approval_pending
1331 describe "delete" do
1333 {:ok, user} = insert(:user) |> User.set_cache()
1338 setup do: clear_config([:instance, :federating])
1340 test ".delete_user_activities deletes all create activities", %{user: user} do
1341 {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
1343 User.delete_user_activities(user)
1345 # TODO: Test removal favorites, repeats, delete activities.
1346 refute Activity.get_by_id(activity.id)
1349 test "it deactivates a user, all follow relationships and all activities", %{user: user} do
1350 follower = insert(:user)
1351 {:ok, follower} = User.follow(follower, user)
1353 locked_user = insert(:user, name: "locked", locked: true)
1354 {:ok, _} = User.follow(user, locked_user, :follow_pending)
1356 object = insert(:note, user: user)
1357 activity = insert(:note_activity, user: user, note: object)
1359 object_two = insert(:note, user: follower)
1360 activity_two = insert(:note_activity, user: follower, note: object_two)
1362 {:ok, like} = CommonAPI.favorite(user, activity_two.id)
1363 {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
1364 {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
1366 {:ok, job} = User.delete(user)
1367 {:ok, _user} = ObanHelpers.perform(job)
1369 follower = User.get_cached_by_id(follower.id)
1371 refute User.following?(follower, user)
1372 assert %{deactivated: true} = User.get_by_id(user.id)
1374 assert [] == User.get_follow_requests(locked_user)
1378 |> Activity.Queries.by_actor()
1380 |> Enum.map(fn act -> act.data["type"] end)
1382 assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
1384 refute Activity.get_by_id(activity.id)
1385 refute Activity.get_by_id(like.id)
1386 refute Activity.get_by_id(like_two.id)
1387 refute Activity.get_by_id(repeat.id)
1391 describe "delete/1 when confirmation is pending" do
1393 user = insert(:user, confirmation_pending: true)
1397 test "deletes user from database when activation required", %{user: user} do
1398 clear_config([:instance, :account_activation_required], true)
1400 {:ok, job} = User.delete(user)
1401 {:ok, _} = ObanHelpers.perform(job)
1403 refute User.get_cached_by_id(user.id)
1404 refute User.get_by_id(user.id)
1407 test "deactivates user when activation is not required", %{user: user} do
1408 clear_config([:instance, :account_activation_required], false)
1410 {:ok, job} = User.delete(user)
1411 {:ok, _} = ObanHelpers.perform(job)
1413 assert %{deactivated: true} = User.get_cached_by_id(user.id)
1414 assert %{deactivated: true} = User.get_by_id(user.id)
1418 test "delete/1 when approval is pending deletes the user" do
1419 user = insert(:user, approval_pending: true)
1422 {:ok, job} = User.delete(user)
1423 {:ok, _} = ObanHelpers.perform(job)
1425 refute User.get_cached_by_id(user.id)
1426 refute User.get_by_id(user.id)
1429 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1430 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1433 describe "per-user rich-text filtering" do
1434 test "html_filter_policy returns default policies, when rich-text is enabled" do
1435 user = insert(:user)
1437 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1440 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1441 user = insert(:user, no_rich_text: true)
1443 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1447 describe "caching" do
1448 test "invalidate_cache works" do
1449 user = insert(:user)
1451 User.set_cache(user)
1452 User.invalidate_cache(user)
1454 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1455 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1458 test "User.delete() plugs any possible zombie objects" do
1459 user = insert(:user)
1461 {:ok, job} = User.delete(user)
1462 {:ok, _} = ObanHelpers.perform(job)
1464 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1466 assert cached_user != user
1468 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1470 assert cached_user != user
1474 describe "account_status/1" do
1475 setup do: clear_config([:instance, :account_activation_required])
1477 test "return confirmation_pending for unconfirm user" do
1478 Pleroma.Config.put([:instance, :account_activation_required], true)
1479 user = insert(:user, confirmation_pending: true)
1480 assert User.account_status(user) == :confirmation_pending
1483 test "return active for confirmed user" do
1484 Pleroma.Config.put([:instance, :account_activation_required], true)
1485 user = insert(:user, confirmation_pending: false)
1486 assert User.account_status(user) == :active
1489 test "return active for remote user" do
1490 user = insert(:user, local: false)
1491 assert User.account_status(user) == :active
1494 test "returns :password_reset_pending for user with reset password" do
1495 user = insert(:user, password_reset_pending: true)
1496 assert User.account_status(user) == :password_reset_pending
1499 test "returns :deactivated for deactivated user" do
1500 user = insert(:user, local: true, confirmation_pending: false, deactivated: true)
1501 assert User.account_status(user) == :deactivated
1504 test "returns :approval_pending for unapproved user" do
1505 user = insert(:user, local: true, approval_pending: true)
1506 assert User.account_status(user) == :approval_pending
1508 user = insert(:user, local: true, confirmation_pending: true, approval_pending: true)
1509 assert User.account_status(user) == :approval_pending
1513 describe "superuser?/1" do
1514 test "returns false for unprivileged users" do
1515 user = insert(:user, local: true)
1517 refute User.superuser?(user)
1520 test "returns false for remote users" do
1521 user = insert(:user, local: false)
1522 remote_admin_user = insert(:user, local: false, is_admin: true)
1524 refute User.superuser?(user)
1525 refute User.superuser?(remote_admin_user)
1528 test "returns true for local moderators" do
1529 user = insert(:user, local: true, is_moderator: true)
1531 assert User.superuser?(user)
1534 test "returns true for local admins" do
1535 user = insert(:user, local: true, is_admin: true)
1537 assert User.superuser?(user)
1541 describe "invisible?/1" do
1542 test "returns true for an invisible user" do
1543 user = insert(:user, local: true, invisible: true)
1545 assert User.invisible?(user)
1548 test "returns false for a non-invisible user" do
1549 user = insert(:user, local: true)
1551 refute User.invisible?(user)
1555 describe "visible_for/2" do
1556 test "returns true when the account is itself" do
1557 user = insert(:user, local: true)
1559 assert User.visible_for(user, user) == :visible
1562 test "returns false when the account is unauthenticated and auth is required" do
1563 Pleroma.Config.put([:instance, :account_activation_required], true)
1565 user = insert(:user, local: true, confirmation_pending: true)
1566 other_user = insert(:user, local: true)
1568 refute User.visible_for(user, other_user) == :visible
1571 test "returns true when the account is unauthenticated and auth is not required" do
1572 user = insert(:user, local: true, confirmation_pending: true)
1573 other_user = insert(:user, local: true)
1575 assert User.visible_for(user, other_user) == :visible
1578 test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
1579 Pleroma.Config.put([:instance, :account_activation_required], true)
1581 user = insert(:user, local: true, confirmation_pending: true)
1582 other_user = insert(:user, local: true, is_admin: true)
1584 assert User.visible_for(user, other_user) == :visible
1588 describe "parse_bio/2" do
1589 test "preserves hosts in user links text" do
1590 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1591 user = insert(:user)
1592 bio = "A.k.a. @nick@domain.com"
1595 ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
1597 }" rel="ugc">@<span>nick@domain.com</span></a></span>)
1599 assert expected_text == User.parse_bio(bio, user)
1602 test "Adds rel=me on linkbacked urls" do
1603 user = insert(:user, ap_id: "https://social.example.org/users/lain")
1605 bio = "http://example.com/rel_me/null"
1606 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1607 assert expected_text == User.parse_bio(bio, user)
1609 bio = "http://example.com/rel_me/link"
1610 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1611 assert expected_text == User.parse_bio(bio, user)
1613 bio = "http://example.com/rel_me/anchor"
1614 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1615 assert expected_text == User.parse_bio(bio, user)
1619 test "follower count is updated when a follower is blocked" do
1620 user = insert(:user)
1621 follower = insert(:user)
1622 follower2 = insert(:user)
1623 follower3 = insert(:user)
1625 {:ok, follower} = User.follow(follower, user)
1626 {:ok, _follower2} = User.follow(follower2, user)
1627 {:ok, _follower3} = User.follow(follower3, user)
1629 {:ok, _user_relationship} = User.block(user, follower)
1630 user = refresh_record(user)
1632 assert user.follower_count == 2
1635 describe "list_inactive_users_query/1" do
1636 defp days_ago(days) do
1638 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
1639 -days * 60 * 60 * 24,
1644 test "Users are inactive by default" do
1648 Enum.map(1..total, fn _ ->
1649 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1652 inactive_users_ids =
1653 Pleroma.User.list_inactive_users_query()
1654 |> Pleroma.Repo.all()
1655 |> Enum.map(& &1.id)
1657 Enum.each(users, fn user ->
1658 assert user.id in inactive_users_ids
1662 test "Only includes users who has no recent activity" do
1666 Enum.map(1..total, fn _ ->
1667 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1670 {inactive, active} = Enum.split(users, trunc(total / 2))
1672 Enum.map(active, fn user ->
1673 to = Enum.random(users -- [user])
1676 CommonAPI.post(user, %{
1677 status: "hey @#{to.nickname}"
1681 inactive_users_ids =
1682 Pleroma.User.list_inactive_users_query()
1683 |> Pleroma.Repo.all()
1684 |> Enum.map(& &1.id)
1686 Enum.each(active, fn user ->
1687 refute user.id in inactive_users_ids
1690 Enum.each(inactive, fn user ->
1691 assert user.id in inactive_users_ids
1695 test "Only includes users with no read notifications" do
1699 Enum.map(1..total, fn _ ->
1700 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1703 [sender | recipients] = users
1704 {inactive, active} = Enum.split(recipients, trunc(total / 2))
1706 Enum.each(recipients, fn to ->
1708 CommonAPI.post(sender, %{
1709 status: "hey @#{to.nickname}"
1713 CommonAPI.post(sender, %{
1714 status: "hey again @#{to.nickname}"
1718 Enum.each(active, fn user ->
1719 [n1, _n2] = Pleroma.Notification.for_user(user)
1720 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
1723 inactive_users_ids =
1724 Pleroma.User.list_inactive_users_query()
1725 |> Pleroma.Repo.all()
1726 |> Enum.map(& &1.id)
1728 Enum.each(active, fn user ->
1729 refute user.id in inactive_users_ids
1732 Enum.each(inactive, fn user ->
1733 assert user.id in inactive_users_ids
1738 describe "toggle_confirmation/1" do
1739 test "if user is confirmed" do
1740 user = insert(:user, confirmation_pending: false)
1741 {:ok, user} = User.toggle_confirmation(user)
1743 assert user.confirmation_pending
1744 assert user.confirmation_token
1747 test "if user is unconfirmed" do
1748 user = insert(:user, confirmation_pending: true, confirmation_token: "some token")
1749 {:ok, user} = User.toggle_confirmation(user)
1751 refute user.confirmation_pending
1752 refute user.confirmation_token
1756 describe "ensure_keys_present" do
1757 test "it creates keys for a user and stores them in info" do
1758 user = insert(:user)
1759 refute is_binary(user.keys)
1760 {:ok, user} = User.ensure_keys_present(user)
1761 assert is_binary(user.keys)
1764 test "it doesn't create keys if there already are some" do
1765 user = insert(:user, keys: "xxx")
1766 {:ok, user} = User.ensure_keys_present(user)
1767 assert user.keys == "xxx"
1771 describe "get_ap_ids_by_nicknames" do
1772 test "it returns a list of AP ids for a given set of nicknames" do
1773 user = insert(:user)
1774 user_two = insert(:user)
1776 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
1777 assert length(ap_ids) == 2
1778 assert user.ap_id in ap_ids
1779 assert user_two.ap_id in ap_ids
1783 describe "sync followers count" do
1785 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
1786 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
1787 insert(:user, local: true)
1788 insert(:user, local: false, deactivated: true)
1789 {:ok, user1: user1, user2: user2}
1792 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
1793 [fdb_user1] = User.external_users(limit: 1)
1795 assert fdb_user1.ap_id
1796 assert fdb_user1.ap_id == user1.ap_id
1797 assert fdb_user1.id == user1.id
1799 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
1801 assert fdb_user2.ap_id
1802 assert fdb_user2.ap_id == user2.ap_id
1803 assert fdb_user2.id == user2.id
1805 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
1809 describe "is_internal_user?/1" do
1810 test "non-internal user returns false" do
1811 user = insert(:user)
1812 refute User.is_internal_user?(user)
1815 test "user with no nickname returns true" do
1816 user = insert(:user, %{nickname: nil})
1817 assert User.is_internal_user?(user)
1820 test "user with internal-prefixed nickname returns true" do
1821 user = insert(:user, %{nickname: "internal.test"})
1822 assert User.is_internal_user?(user)
1826 describe "update_and_set_cache/1" do
1827 test "returns error when user is stale instead Ecto.StaleEntryError" do
1828 user = insert(:user)
1830 changeset = Ecto.Changeset.change(user, bio: "test")
1834 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
1835 User.update_and_set_cache(changeset)
1838 test "performs update cache if user updated" do
1839 user = insert(:user)
1840 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1842 changeset = Ecto.Changeset.change(user, bio: "test-bio")
1844 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
1845 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1846 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
1850 describe "following/followers synchronization" do
1851 setup do: clear_config([:instance, :external_user_synchronization])
1853 test "updates the counters normally on following/getting a follow when disabled" do
1854 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 {:ok, user} = Pleroma.User.follow(user, other_user)
1869 other_user = Pleroma.User.get_by_id(other_user.id)
1871 assert user.following_count == 1
1872 assert other_user.follower_count == 1
1875 test "syncronizes the counters with the remote instance for the followed when enabled" do
1876 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1878 user = insert(:user)
1883 follower_address: "http://localhost:4001/users/masto_closed/followers",
1884 following_address: "http://localhost:4001/users/masto_closed/following",
1888 assert other_user.following_count == 0
1889 assert other_user.follower_count == 0
1891 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1892 {:ok, _user} = User.follow(user, other_user)
1893 other_user = User.get_by_id(other_user.id)
1895 assert other_user.follower_count == 437
1898 test "syncronizes the counters with the remote instance for the follower when enabled" do
1899 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1901 user = insert(:user)
1906 follower_address: "http://localhost:4001/users/masto_closed/followers",
1907 following_address: "http://localhost:4001/users/masto_closed/following",
1911 assert other_user.following_count == 0
1912 assert other_user.follower_count == 0
1914 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1915 {:ok, other_user} = User.follow(other_user, user)
1917 assert other_user.following_count == 152
1921 describe "change_email/2" do
1923 [user: insert(:user)]
1926 test "blank email returns error", %{user: user} do
1927 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
1928 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
1931 test "non unique email returns error", %{user: user} do
1932 %{email: email} = insert(:user)
1934 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
1935 User.change_email(user, email)
1938 test "invalid email returns error", %{user: user} do
1939 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
1940 User.change_email(user, "cofe")
1943 test "changes email", %{user: user} do
1944 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
1948 describe "get_cached_by_nickname_or_id" do
1950 local_user = insert(:user)
1951 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
1953 [local_user: local_user, remote_user: remote_user]
1956 setup do: clear_config([:instance, :limit_to_local_content])
1958 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
1959 remote_user: remote_user
1961 Pleroma.Config.put([:instance, :limit_to_local_content], false)
1962 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
1964 Pleroma.Config.put([:instance, :limit_to_local_content], true)
1965 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
1967 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1968 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
1971 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
1972 %{remote_user: remote_user} do
1973 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1974 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
1977 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
1978 %{remote_user: remote_user, local_user: local_user} do
1979 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1980 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
1983 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
1984 %{remote_user: remote_user} do
1985 Pleroma.Config.put([:instance, :limit_to_local_content], true)
1986 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
1989 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
1990 %{local_user: local_user} do
1991 Pleroma.Config.put([:instance, :limit_to_local_content], false)
1992 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
1994 Pleroma.Config.put([:instance, :limit_to_local_content], true)
1995 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
1997 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
1998 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2002 describe "update_email_notifications/2" do
2004 user = insert(:user, email_notifications: %{"digest" => true})
2009 test "Notifications are updated", %{user: user} do
2010 true = user.email_notifications["digest"]
2011 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
2012 assert result.email_notifications["digest"] == false
2016 test "avatar fallback" do
2017 user = insert(:user)
2018 assert User.avatar_url(user) =~ "/images/avi.png"
2020 clear_config([:assets, :default_user_avatar], "avatar.png")
2022 user = User.get_cached_by_nickname_or_id(user.nickname)
2023 assert User.avatar_url(user) =~ "avatar.png"
2025 assert User.avatar_url(user, no_default: true) == nil