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)
1421 {:ok, job} = User.delete(user)
1422 {:ok, _} = ObanHelpers.perform(job)
1424 refute User.get_cached_by_id(user.id)
1425 refute User.get_by_id(user.id)
1428 test "delete/1 purges a user when they wouldn't be fully deleted" do
1433 password_hash: "pdfk2$1b3n159001",
1434 keys: "RSA begin buplic key",
1435 public_key: "--PRIVATE KEYE--",
1436 avatar: %{"a" => "b"},
1438 banner: %{"a" => "b"},
1439 background: %{"a" => "b"},
1442 following_count: 9001,
1444 confirmation_pending: true,
1445 password_reset_pending: true,
1446 approval_pending: true,
1447 registration_reason: "ahhhhh",
1448 confirmation_token: "qqqq",
1449 domain_blocks: ["lain.com"],
1454 mastofe_settings: %{"a" => "b"},
1455 mascot: %{"a" => "b"},
1456 emoji: %{"a" => "b"},
1457 pleroma_settings_store: %{"q" => "x"},
1458 fields: [%{"gg" => "qq"}],
1459 raw_fields: [%{"gg" => "qq"}],
1461 also_known_as: ["https://lol.olo/users/loll"]
1464 {:ok, job} = User.delete(user)
1465 {:ok, _} = ObanHelpers.perform(job)
1466 user = User.get_by_id(user.id)
1478 last_refreshed_at: nil,
1479 last_digest_emailed_at: nil,
1486 confirmation_pending: false,
1487 password_reset_pending: false,
1488 approval_pending: false,
1489 registration_reason: nil,
1490 confirmation_token: nil,
1494 is_moderator: false,
1496 mastofe_settings: nil,
1499 pleroma_settings_store: %{},
1502 discoverable: false,
1507 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1508 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1511 describe "per-user rich-text filtering" do
1512 test "html_filter_policy returns default policies, when rich-text is enabled" do
1513 user = insert(:user)
1515 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1518 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1519 user = insert(:user, no_rich_text: true)
1521 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1525 describe "caching" do
1526 test "invalidate_cache works" do
1527 user = insert(:user)
1529 User.set_cache(user)
1530 User.invalidate_cache(user)
1532 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1533 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1536 test "User.delete() plugs any possible zombie objects" do
1537 user = insert(:user)
1539 {:ok, job} = User.delete(user)
1540 {:ok, _} = ObanHelpers.perform(job)
1542 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1544 assert cached_user != user
1546 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1548 assert cached_user != user
1552 describe "account_status/1" do
1553 setup do: clear_config([:instance, :account_activation_required])
1555 test "return confirmation_pending for unconfirm user" do
1556 Pleroma.Config.put([:instance, :account_activation_required], true)
1557 user = insert(:user, confirmation_pending: true)
1558 assert User.account_status(user) == :confirmation_pending
1561 test "return active for confirmed user" do
1562 Pleroma.Config.put([:instance, :account_activation_required], true)
1563 user = insert(:user, confirmation_pending: false)
1564 assert User.account_status(user) == :active
1567 test "return active for remote user" do
1568 user = insert(:user, local: false)
1569 assert User.account_status(user) == :active
1572 test "returns :password_reset_pending for user with reset password" do
1573 user = insert(:user, password_reset_pending: true)
1574 assert User.account_status(user) == :password_reset_pending
1577 test "returns :deactivated for deactivated user" do
1578 user = insert(:user, local: true, confirmation_pending: false, deactivated: true)
1579 assert User.account_status(user) == :deactivated
1582 test "returns :approval_pending for unapproved user" do
1583 user = insert(:user, local: true, approval_pending: true)
1584 assert User.account_status(user) == :approval_pending
1586 user = insert(:user, local: true, confirmation_pending: true, approval_pending: true)
1587 assert User.account_status(user) == :approval_pending
1591 describe "superuser?/1" do
1592 test "returns false for unprivileged users" do
1593 user = insert(:user, local: true)
1595 refute User.superuser?(user)
1598 test "returns false for remote users" do
1599 user = insert(:user, local: false)
1600 remote_admin_user = insert(:user, local: false, is_admin: true)
1602 refute User.superuser?(user)
1603 refute User.superuser?(remote_admin_user)
1606 test "returns true for local moderators" do
1607 user = insert(:user, local: true, is_moderator: true)
1609 assert User.superuser?(user)
1612 test "returns true for local admins" do
1613 user = insert(:user, local: true, is_admin: true)
1615 assert User.superuser?(user)
1619 describe "invisible?/1" do
1620 test "returns true for an invisible user" do
1621 user = insert(:user, local: true, invisible: true)
1623 assert User.invisible?(user)
1626 test "returns false for a non-invisible user" do
1627 user = insert(:user, local: true)
1629 refute User.invisible?(user)
1633 describe "visible_for/2" do
1634 test "returns true when the account is itself" do
1635 user = insert(:user, local: true)
1637 assert User.visible_for(user, user) == :visible
1640 test "returns false when the account is unauthenticated and auth is required" do
1641 Pleroma.Config.put([:instance, :account_activation_required], true)
1643 user = insert(:user, local: true, confirmation_pending: true)
1644 other_user = insert(:user, local: true)
1646 refute User.visible_for(user, other_user) == :visible
1649 test "returns true when the account is unauthenticated and auth is not required" do
1650 user = insert(:user, local: true, confirmation_pending: true)
1651 other_user = insert(:user, local: true)
1653 assert User.visible_for(user, other_user) == :visible
1656 test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
1657 Pleroma.Config.put([:instance, :account_activation_required], true)
1659 user = insert(:user, local: true, confirmation_pending: true)
1660 other_user = insert(:user, local: true, is_admin: true)
1662 assert User.visible_for(user, other_user) == :visible
1666 describe "parse_bio/2" do
1667 test "preserves hosts in user links text" do
1668 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1669 user = insert(:user)
1670 bio = "A.k.a. @nick@domain.com"
1673 ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
1675 }" rel="ugc">@<span>nick@domain.com</span></a></span>)
1677 assert expected_text == User.parse_bio(bio, user)
1680 test "Adds rel=me on linkbacked urls" do
1681 user = insert(:user, ap_id: "https://social.example.org/users/lain")
1683 bio = "http://example.com/rel_me/null"
1684 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1685 assert expected_text == User.parse_bio(bio, user)
1687 bio = "http://example.com/rel_me/link"
1688 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1689 assert expected_text == User.parse_bio(bio, user)
1691 bio = "http://example.com/rel_me/anchor"
1692 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1693 assert expected_text == User.parse_bio(bio, user)
1697 test "follower count is updated when a follower is blocked" do
1698 user = insert(:user)
1699 follower = insert(:user)
1700 follower2 = insert(:user)
1701 follower3 = insert(:user)
1703 {:ok, follower} = User.follow(follower, user)
1704 {:ok, _follower2} = User.follow(follower2, user)
1705 {:ok, _follower3} = User.follow(follower3, user)
1707 {:ok, _user_relationship} = User.block(user, follower)
1708 user = refresh_record(user)
1710 assert user.follower_count == 2
1713 describe "list_inactive_users_query/1" do
1714 defp days_ago(days) do
1716 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
1717 -days * 60 * 60 * 24,
1722 test "Users are inactive by default" do
1726 Enum.map(1..total, fn _ ->
1727 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1730 inactive_users_ids =
1731 Pleroma.User.list_inactive_users_query()
1732 |> Pleroma.Repo.all()
1733 |> Enum.map(& &1.id)
1735 Enum.each(users, fn user ->
1736 assert user.id in inactive_users_ids
1740 test "Only includes users who has no recent activity" do
1744 Enum.map(1..total, fn _ ->
1745 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1748 {inactive, active} = Enum.split(users, trunc(total / 2))
1750 Enum.map(active, fn user ->
1751 to = Enum.random(users -- [user])
1754 CommonAPI.post(user, %{
1755 status: "hey @#{to.nickname}"
1759 inactive_users_ids =
1760 Pleroma.User.list_inactive_users_query()
1761 |> Pleroma.Repo.all()
1762 |> Enum.map(& &1.id)
1764 Enum.each(active, fn user ->
1765 refute user.id in inactive_users_ids
1768 Enum.each(inactive, fn user ->
1769 assert user.id in inactive_users_ids
1773 test "Only includes users with no read notifications" do
1777 Enum.map(1..total, fn _ ->
1778 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1781 [sender | recipients] = users
1782 {inactive, active} = Enum.split(recipients, trunc(total / 2))
1784 Enum.each(recipients, fn to ->
1786 CommonAPI.post(sender, %{
1787 status: "hey @#{to.nickname}"
1791 CommonAPI.post(sender, %{
1792 status: "hey again @#{to.nickname}"
1796 Enum.each(active, fn user ->
1797 [n1, _n2] = Pleroma.Notification.for_user(user)
1798 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
1801 inactive_users_ids =
1802 Pleroma.User.list_inactive_users_query()
1803 |> Pleroma.Repo.all()
1804 |> Enum.map(& &1.id)
1806 Enum.each(active, fn user ->
1807 refute user.id in inactive_users_ids
1810 Enum.each(inactive, fn user ->
1811 assert user.id in inactive_users_ids
1816 describe "toggle_confirmation/1" do
1817 test "if user is confirmed" do
1818 user = insert(:user, confirmation_pending: false)
1819 {:ok, user} = User.toggle_confirmation(user)
1821 assert user.confirmation_pending
1822 assert user.confirmation_token
1825 test "if user is unconfirmed" do
1826 user = insert(:user, confirmation_pending: true, confirmation_token: "some token")
1827 {:ok, user} = User.toggle_confirmation(user)
1829 refute user.confirmation_pending
1830 refute user.confirmation_token
1834 describe "ensure_keys_present" do
1835 test "it creates keys for a user and stores them in info" do
1836 user = insert(:user)
1837 refute is_binary(user.keys)
1838 {:ok, user} = User.ensure_keys_present(user)
1839 assert is_binary(user.keys)
1842 test "it doesn't create keys if there already are some" do
1843 user = insert(:user, keys: "xxx")
1844 {:ok, user} = User.ensure_keys_present(user)
1845 assert user.keys == "xxx"
1849 describe "get_ap_ids_by_nicknames" do
1850 test "it returns a list of AP ids for a given set of nicknames" do
1851 user = insert(:user)
1852 user_two = insert(:user)
1854 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
1855 assert length(ap_ids) == 2
1856 assert user.ap_id in ap_ids
1857 assert user_two.ap_id in ap_ids
1861 describe "sync followers count" do
1863 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
1864 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
1865 insert(:user, local: true)
1866 insert(:user, local: false, deactivated: true)
1867 {:ok, user1: user1, user2: user2}
1870 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
1871 [fdb_user1] = User.external_users(limit: 1)
1873 assert fdb_user1.ap_id
1874 assert fdb_user1.ap_id == user1.ap_id
1875 assert fdb_user1.id == user1.id
1877 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
1879 assert fdb_user2.ap_id
1880 assert fdb_user2.ap_id == user2.ap_id
1881 assert fdb_user2.id == user2.id
1883 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
1887 describe "is_internal_user?/1" do
1888 test "non-internal user returns false" do
1889 user = insert(:user)
1890 refute User.is_internal_user?(user)
1893 test "user with no nickname returns true" do
1894 user = insert(:user, %{nickname: nil})
1895 assert User.is_internal_user?(user)
1898 test "user with internal-prefixed nickname returns true" do
1899 user = insert(:user, %{nickname: "internal.test"})
1900 assert User.is_internal_user?(user)
1904 describe "update_and_set_cache/1" do
1905 test "returns error when user is stale instead Ecto.StaleEntryError" do
1906 user = insert(:user)
1908 changeset = Ecto.Changeset.change(user, bio: "test")
1912 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
1913 User.update_and_set_cache(changeset)
1916 test "performs update cache if user updated" do
1917 user = insert(:user)
1918 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1920 changeset = Ecto.Changeset.change(user, bio: "test-bio")
1922 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
1923 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1924 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
1928 describe "following/followers synchronization" do
1929 setup do: clear_config([:instance, :external_user_synchronization])
1931 test "updates the counters normally on following/getting a follow when disabled" do
1932 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1933 user = insert(:user)
1938 follower_address: "http://localhost:4001/users/masto_closed/followers",
1939 following_address: "http://localhost:4001/users/masto_closed/following",
1943 assert other_user.following_count == 0
1944 assert other_user.follower_count == 0
1946 {:ok, user} = Pleroma.User.follow(user, other_user)
1947 other_user = Pleroma.User.get_by_id(other_user.id)
1949 assert user.following_count == 1
1950 assert other_user.follower_count == 1
1953 test "syncronizes the counters with the remote instance for the followed when enabled" do
1954 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1956 user = insert(:user)
1961 follower_address: "http://localhost:4001/users/masto_closed/followers",
1962 following_address: "http://localhost:4001/users/masto_closed/following",
1966 assert other_user.following_count == 0
1967 assert other_user.follower_count == 0
1969 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1970 {:ok, _user} = User.follow(user, other_user)
1971 other_user = User.get_by_id(other_user.id)
1973 assert other_user.follower_count == 437
1976 test "syncronizes the counters with the remote instance for the follower when enabled" do
1977 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1979 user = insert(:user)
1984 follower_address: "http://localhost:4001/users/masto_closed/followers",
1985 following_address: "http://localhost:4001/users/masto_closed/following",
1989 assert other_user.following_count == 0
1990 assert other_user.follower_count == 0
1992 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1993 {:ok, other_user} = User.follow(other_user, user)
1995 assert other_user.following_count == 152
1999 describe "change_email/2" do
2001 [user: insert(:user)]
2004 test "blank email returns error", %{user: user} do
2005 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
2006 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
2009 test "non unique email returns error", %{user: user} do
2010 %{email: email} = insert(:user)
2012 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
2013 User.change_email(user, email)
2016 test "invalid email returns error", %{user: user} do
2017 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
2018 User.change_email(user, "cofe")
2021 test "changes email", %{user: user} do
2022 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
2026 describe "get_cached_by_nickname_or_id" do
2028 local_user = insert(:user)
2029 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
2031 [local_user: local_user, remote_user: remote_user]
2034 setup do: clear_config([:instance, :limit_to_local_content])
2036 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
2037 remote_user: remote_user
2039 Pleroma.Config.put([:instance, :limit_to_local_content], false)
2040 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2042 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2043 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2045 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2046 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2049 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
2050 %{remote_user: remote_user} do
2051 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2052 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2055 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
2056 %{remote_user: remote_user, local_user: local_user} do
2057 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2058 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
2061 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
2062 %{remote_user: remote_user} do
2063 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2064 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2067 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
2068 %{local_user: local_user} do
2069 Pleroma.Config.put([:instance, :limit_to_local_content], false)
2070 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2072 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2073 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2075 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2076 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2080 describe "update_email_notifications/2" do
2082 user = insert(:user, email_notifications: %{"digest" => true})
2087 test "Notifications are updated", %{user: user} do
2088 true = user.email_notifications["digest"]
2089 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
2090 assert result.email_notifications["digest"] == false
2094 test "avatar fallback" do
2095 user = insert(:user)
2096 assert User.avatar_url(user) =~ "/images/avi.png"
2098 clear_config([:assets, :default_user_avatar], "avatar.png")
2100 user = User.get_cached_by_nickname_or_id(user.nickname)
2101 assert User.avatar_url(user) =~ "avatar.png"
2103 assert User.avatar_url(user, no_default: true) == nil