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
936 test "it mutes people" do
938 muted_user = insert(:user)
940 refute User.mutes?(user, muted_user)
941 refute User.muted_notifications?(user, muted_user)
943 {:ok, _user_relationships} = User.mute(user, muted_user)
945 assert User.mutes?(user, muted_user)
946 assert User.muted_notifications?(user, muted_user)
949 test "it unmutes users" do
951 muted_user = insert(:user)
953 {:ok, _user_relationships} = User.mute(user, muted_user)
954 {:ok, _user_mute} = User.unmute(user, muted_user)
956 refute User.mutes?(user, muted_user)
957 refute User.muted_notifications?(user, muted_user)
960 test "it mutes user without notifications" do
962 muted_user = insert(:user)
964 refute User.mutes?(user, muted_user)
965 refute User.muted_notifications?(user, muted_user)
967 {:ok, _user_relationships} = User.mute(user, muted_user, false)
969 assert User.mutes?(user, muted_user)
970 refute User.muted_notifications?(user, muted_user)
975 test "it blocks people" do
977 blocked_user = insert(:user)
979 refute User.blocks?(user, blocked_user)
981 {:ok, _user_relationship} = User.block(user, blocked_user)
983 assert User.blocks?(user, blocked_user)
986 test "it unblocks users" do
988 blocked_user = insert(:user)
990 {:ok, _user_relationship} = User.block(user, blocked_user)
991 {:ok, _user_block} = User.unblock(user, blocked_user)
993 refute User.blocks?(user, blocked_user)
996 test "blocks tear down cyclical follow relationships" do
997 blocker = insert(:user)
998 blocked = insert(:user)
1000 {:ok, blocker} = User.follow(blocker, blocked)
1001 {:ok, blocked} = User.follow(blocked, blocker)
1003 assert User.following?(blocker, blocked)
1004 assert User.following?(blocked, blocker)
1006 {:ok, _user_relationship} = User.block(blocker, blocked)
1007 blocked = User.get_cached_by_id(blocked.id)
1009 assert User.blocks?(blocker, blocked)
1011 refute User.following?(blocker, blocked)
1012 refute User.following?(blocked, blocker)
1015 test "blocks tear down blocker->blocked follow relationships" do
1016 blocker = insert(:user)
1017 blocked = insert(:user)
1019 {:ok, blocker} = User.follow(blocker, blocked)
1021 assert User.following?(blocker, blocked)
1022 refute User.following?(blocked, blocker)
1024 {:ok, _user_relationship} = User.block(blocker, blocked)
1025 blocked = User.get_cached_by_id(blocked.id)
1027 assert User.blocks?(blocker, blocked)
1029 refute User.following?(blocker, blocked)
1030 refute User.following?(blocked, blocker)
1033 test "blocks tear down blocked->blocker follow relationships" do
1034 blocker = insert(:user)
1035 blocked = insert(:user)
1037 {:ok, blocked} = User.follow(blocked, blocker)
1039 refute User.following?(blocker, blocked)
1040 assert User.following?(blocked, blocker)
1042 {:ok, _user_relationship} = User.block(blocker, blocked)
1043 blocked = User.get_cached_by_id(blocked.id)
1045 assert User.blocks?(blocker, blocked)
1047 refute User.following?(blocker, blocked)
1048 refute User.following?(blocked, blocker)
1051 test "blocks tear down blocked->blocker subscription relationships" do
1052 blocker = insert(:user)
1053 blocked = insert(:user)
1055 {:ok, _subscription} = User.subscribe(blocked, blocker)
1057 assert User.subscribed_to?(blocked, blocker)
1058 refute User.subscribed_to?(blocker, blocked)
1060 {:ok, _user_relationship} = User.block(blocker, blocked)
1062 assert User.blocks?(blocker, blocked)
1063 refute User.subscribed_to?(blocker, blocked)
1064 refute User.subscribed_to?(blocked, blocker)
1068 describe "domain blocking" do
1069 test "blocks domains" do
1070 user = insert(:user)
1071 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1073 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1075 assert User.blocks?(user, collateral_user)
1078 test "does not block domain with same end" do
1079 user = insert(:user)
1082 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1084 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1086 refute User.blocks?(user, collateral_user)
1089 test "does not block domain with same end if wildcard added" do
1090 user = insert(:user)
1093 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1095 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1097 refute User.blocks?(user, collateral_user)
1100 test "blocks domain with wildcard for subdomain" do
1101 user = insert(:user)
1103 user_from_subdomain =
1104 insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
1106 user_with_two_subdomains =
1108 ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
1111 user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1113 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1115 assert User.blocks?(user, user_from_subdomain)
1116 assert User.blocks?(user, user_with_two_subdomains)
1117 assert User.blocks?(user, user_domain)
1120 test "unblocks domains" do
1121 user = insert(:user)
1122 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1124 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1125 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
1127 refute User.blocks?(user, collateral_user)
1130 test "follows take precedence over domain blocks" do
1131 user = insert(:user)
1132 good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
1134 {:ok, user} = User.block_domain(user, "meanies.social")
1135 {:ok, user} = User.follow(user, good_eggo)
1137 refute User.blocks?(user, good_eggo)
1141 describe "get_recipients_from_activity" do
1142 test "works for announces" do
1143 actor = insert(:user)
1144 user = insert(:user, local: true)
1146 {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
1147 {:ok, announce} = CommonAPI.repeat(activity.id, user)
1149 recipients = User.get_recipients_from_activity(announce)
1151 assert user in recipients
1154 test "get recipients" do
1155 actor = insert(:user)
1156 user = insert(:user, local: true)
1157 user_two = insert(:user, local: false)
1158 addressed = insert(:user, local: true)
1159 addressed_remote = insert(:user, local: false)
1162 CommonAPI.post(actor, %{
1163 status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
1166 assert Enum.map([actor, addressed], & &1.ap_id) --
1167 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1169 {:ok, user} = User.follow(user, actor)
1170 {:ok, _user_two} = User.follow(user_two, actor)
1171 recipients = User.get_recipients_from_activity(activity)
1172 assert length(recipients) == 3
1173 assert user in recipients
1174 assert addressed in recipients
1177 test "has following" do
1178 actor = insert(:user)
1179 user = insert(:user)
1180 user_two = insert(:user)
1181 addressed = insert(:user, local: true)
1184 CommonAPI.post(actor, %{
1185 status: "hey @#{addressed.nickname}"
1188 assert Enum.map([actor, addressed], & &1.ap_id) --
1189 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1191 {:ok, _actor} = User.follow(actor, user)
1192 {:ok, _actor} = User.follow(actor, user_two)
1193 recipients = User.get_recipients_from_activity(activity)
1194 assert length(recipients) == 2
1195 assert addressed in recipients
1199 describe ".deactivate" do
1200 test "can de-activate then re-activate a user" do
1201 user = insert(:user)
1202 assert false == user.deactivated
1203 {:ok, user} = User.deactivate(user)
1204 assert true == user.deactivated
1205 {:ok, user} = User.deactivate(user, false)
1206 assert false == user.deactivated
1209 test "hide a user from followers" do
1210 user = insert(:user)
1211 user2 = insert(:user)
1213 {:ok, user} = User.follow(user, user2)
1214 {:ok, _user} = User.deactivate(user)
1216 user2 = User.get_cached_by_id(user2.id)
1218 assert user2.follower_count == 0
1219 assert [] = User.get_followers(user2)
1222 test "hide a user from friends" do
1223 user = insert(:user)
1224 user2 = insert(:user)
1226 {:ok, user2} = User.follow(user2, user)
1227 assert user2.following_count == 1
1228 assert User.following_count(user2) == 1
1230 {:ok, _user} = User.deactivate(user)
1232 user2 = User.get_cached_by_id(user2.id)
1234 assert refresh_record(user2).following_count == 0
1235 assert user2.following_count == 0
1236 assert User.following_count(user2) == 0
1237 assert [] = User.get_friends(user2)
1240 test "hide a user's statuses from timelines and notifications" do
1241 user = insert(:user)
1242 user2 = insert(:user)
1244 {:ok, user2} = User.follow(user2, user)
1246 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
1248 activity = Repo.preload(activity, :bookmark)
1250 [notification] = Pleroma.Notification.for_user(user2)
1251 assert notification.activity.id == activity.id
1253 assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
1255 assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
1256 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1260 {:ok, _user} = User.deactivate(user)
1262 assert [] == ActivityPub.fetch_public_activities(%{})
1263 assert [] == Pleroma.Notification.for_user(user2)
1266 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1272 describe "approve" do
1273 test "approves a user" do
1274 user = insert(:user, approval_pending: true)
1275 assert true == user.approval_pending
1276 {:ok, user} = User.approve(user)
1277 assert false == user.approval_pending
1280 test "approves a list of users" do
1281 unapproved_users = [
1282 insert(:user, approval_pending: true),
1283 insert(:user, approval_pending: true),
1284 insert(:user, approval_pending: true)
1287 {:ok, users} = User.approve(unapproved_users)
1289 assert Enum.count(users) == 3
1291 Enum.each(users, fn user ->
1292 assert false == user.approval_pending
1297 describe "delete" do
1299 {:ok, user} = insert(:user) |> User.set_cache()
1304 setup do: clear_config([:instance, :federating])
1306 test ".delete_user_activities deletes all create activities", %{user: user} do
1307 {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
1309 User.delete_user_activities(user)
1311 # TODO: Test removal favorites, repeats, delete activities.
1312 refute Activity.get_by_id(activity.id)
1315 test "it deactivates a user, all follow relationships and all activities", %{user: user} do
1316 follower = insert(:user)
1317 {:ok, follower} = User.follow(follower, user)
1319 locked_user = insert(:user, name: "locked", locked: true)
1320 {:ok, _} = User.follow(user, locked_user, :follow_pending)
1322 object = insert(:note, user: user)
1323 activity = insert(:note_activity, user: user, note: object)
1325 object_two = insert(:note, user: follower)
1326 activity_two = insert(:note_activity, user: follower, note: object_two)
1328 {:ok, like} = CommonAPI.favorite(user, activity_two.id)
1329 {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
1330 {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
1332 {:ok, job} = User.delete(user)
1333 {:ok, _user} = ObanHelpers.perform(job)
1335 follower = User.get_cached_by_id(follower.id)
1337 refute User.following?(follower, user)
1338 assert %{deactivated: true} = User.get_by_id(user.id)
1340 assert [] == User.get_follow_requests(locked_user)
1344 |> Activity.Queries.by_actor()
1346 |> Enum.map(fn act -> act.data["type"] end)
1348 assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
1350 refute Activity.get_by_id(activity.id)
1351 refute Activity.get_by_id(like.id)
1352 refute Activity.get_by_id(like_two.id)
1353 refute Activity.get_by_id(repeat.id)
1357 describe "delete/1 when confirmation is pending" do
1359 user = insert(:user, confirmation_pending: true)
1363 test "deletes user from database when activation required", %{user: user} do
1364 clear_config([:instance, :account_activation_required], true)
1366 {:ok, job} = User.delete(user)
1367 {:ok, _} = ObanHelpers.perform(job)
1369 refute User.get_cached_by_id(user.id)
1370 refute User.get_by_id(user.id)
1373 test "deactivates user when activation is not required", %{user: user} do
1374 clear_config([:instance, :account_activation_required], false)
1376 {:ok, job} = User.delete(user)
1377 {:ok, _} = ObanHelpers.perform(job)
1379 assert %{deactivated: true} = User.get_cached_by_id(user.id)
1380 assert %{deactivated: true} = User.get_by_id(user.id)
1384 test "delete/1 when approval is pending deletes the user" do
1385 user = insert(:user, approval_pending: true)
1387 {:ok, job} = User.delete(user)
1388 {:ok, _} = ObanHelpers.perform(job)
1390 refute User.get_cached_by_id(user.id)
1391 refute User.get_by_id(user.id)
1394 test "delete/1 purges a user when they wouldn't be fully deleted" do
1399 password_hash: "pdfk2$1b3n159001",
1400 keys: "RSA begin buplic key",
1401 public_key: "--PRIVATE KEYE--",
1402 avatar: %{"a" => "b"},
1404 banner: %{"a" => "b"},
1405 background: %{"a" => "b"},
1408 following_count: 9001,
1410 confirmation_pending: true,
1411 password_reset_pending: true,
1412 approval_pending: true,
1413 registration_reason: "ahhhhh",
1414 confirmation_token: "qqqq",
1415 domain_blocks: ["lain.com"],
1420 mastofe_settings: %{"a" => "b"},
1421 mascot: %{"a" => "b"},
1422 emoji: %{"a" => "b"},
1423 pleroma_settings_store: %{"q" => "x"},
1424 fields: [%{"gg" => "qq"}],
1425 raw_fields: [%{"gg" => "qq"}],
1427 also_known_as: ["https://lol.olo/users/loll"]
1430 {:ok, job} = User.delete(user)
1431 {:ok, _} = ObanHelpers.perform(job)
1432 user = User.get_by_id(user.id)
1444 last_refreshed_at: nil,
1445 last_digest_emailed_at: nil,
1452 confirmation_pending: false,
1453 password_reset_pending: false,
1454 approval_pending: false,
1455 registration_reason: nil,
1456 confirmation_token: nil,
1460 is_moderator: false,
1462 mastofe_settings: nil,
1465 pleroma_settings_store: %{},
1468 discoverable: false,
1473 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1474 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1477 describe "per-user rich-text filtering" do
1478 test "html_filter_policy returns default policies, when rich-text is enabled" do
1479 user = insert(:user)
1481 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1484 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1485 user = insert(:user, no_rich_text: true)
1487 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1491 describe "caching" do
1492 test "invalidate_cache works" do
1493 user = insert(:user)
1495 User.set_cache(user)
1496 User.invalidate_cache(user)
1498 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1499 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1502 test "User.delete() plugs any possible zombie objects" do
1503 user = insert(:user)
1505 {:ok, job} = User.delete(user)
1506 {:ok, _} = ObanHelpers.perform(job)
1508 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1510 assert cached_user != user
1512 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1514 assert cached_user != user
1518 describe "account_status/1" do
1519 setup do: clear_config([:instance, :account_activation_required])
1521 test "return confirmation_pending for unconfirm user" do
1522 Pleroma.Config.put([:instance, :account_activation_required], true)
1523 user = insert(:user, confirmation_pending: true)
1524 assert User.account_status(user) == :confirmation_pending
1527 test "return active for confirmed user" do
1528 Pleroma.Config.put([:instance, :account_activation_required], true)
1529 user = insert(:user, confirmation_pending: false)
1530 assert User.account_status(user) == :active
1533 test "return active for remote user" do
1534 user = insert(:user, local: false)
1535 assert User.account_status(user) == :active
1538 test "returns :password_reset_pending for user with reset password" do
1539 user = insert(:user, password_reset_pending: true)
1540 assert User.account_status(user) == :password_reset_pending
1543 test "returns :deactivated for deactivated user" do
1544 user = insert(:user, local: true, confirmation_pending: false, deactivated: true)
1545 assert User.account_status(user) == :deactivated
1548 test "returns :approval_pending for unapproved user" do
1549 user = insert(:user, local: true, approval_pending: true)
1550 assert User.account_status(user) == :approval_pending
1552 user = insert(:user, local: true, confirmation_pending: true, approval_pending: true)
1553 assert User.account_status(user) == :approval_pending
1557 describe "superuser?/1" do
1558 test "returns false for unprivileged users" do
1559 user = insert(:user, local: true)
1561 refute User.superuser?(user)
1564 test "returns false for remote users" do
1565 user = insert(:user, local: false)
1566 remote_admin_user = insert(:user, local: false, is_admin: true)
1568 refute User.superuser?(user)
1569 refute User.superuser?(remote_admin_user)
1572 test "returns true for local moderators" do
1573 user = insert(:user, local: true, is_moderator: true)
1575 assert User.superuser?(user)
1578 test "returns true for local admins" do
1579 user = insert(:user, local: true, is_admin: true)
1581 assert User.superuser?(user)
1585 describe "invisible?/1" do
1586 test "returns true for an invisible user" do
1587 user = insert(:user, local: true, invisible: true)
1589 assert User.invisible?(user)
1592 test "returns false for a non-invisible user" do
1593 user = insert(:user, local: true)
1595 refute User.invisible?(user)
1599 describe "visible_for/2" do
1600 test "returns true when the account is itself" do
1601 user = insert(:user, local: true)
1603 assert User.visible_for(user, user) == :visible
1606 test "returns false when the account is unauthenticated and auth is required" do
1607 Pleroma.Config.put([:instance, :account_activation_required], true)
1609 user = insert(:user, local: true, confirmation_pending: true)
1610 other_user = insert(:user, local: true)
1612 refute User.visible_for(user, other_user) == :visible
1615 test "returns true when the account is unauthenticated and auth is not required" do
1616 user = insert(:user, local: true, confirmation_pending: true)
1617 other_user = insert(:user, local: true)
1619 assert User.visible_for(user, other_user) == :visible
1622 test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
1623 Pleroma.Config.put([:instance, :account_activation_required], true)
1625 user = insert(:user, local: true, confirmation_pending: true)
1626 other_user = insert(:user, local: true, is_admin: true)
1628 assert User.visible_for(user, other_user) == :visible
1632 describe "parse_bio/2" do
1633 test "preserves hosts in user links text" do
1634 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1635 user = insert(:user)
1636 bio = "A.k.a. @nick@domain.com"
1639 ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
1641 }" rel="ugc">@<span>nick@domain.com</span></a></span>)
1643 assert expected_text == User.parse_bio(bio, user)
1646 test "Adds rel=me on linkbacked urls" do
1647 user = insert(:user, ap_id: "https://social.example.org/users/lain")
1649 bio = "http://example.com/rel_me/null"
1650 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1651 assert expected_text == User.parse_bio(bio, user)
1653 bio = "http://example.com/rel_me/link"
1654 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1655 assert expected_text == User.parse_bio(bio, user)
1657 bio = "http://example.com/rel_me/anchor"
1658 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1659 assert expected_text == User.parse_bio(bio, user)
1663 test "follower count is updated when a follower is blocked" do
1664 user = insert(:user)
1665 follower = insert(:user)
1666 follower2 = insert(:user)
1667 follower3 = insert(:user)
1669 {:ok, follower} = User.follow(follower, user)
1670 {:ok, _follower2} = User.follow(follower2, user)
1671 {:ok, _follower3} = User.follow(follower3, user)
1673 {:ok, _user_relationship} = User.block(user, follower)
1674 user = refresh_record(user)
1676 assert user.follower_count == 2
1679 describe "list_inactive_users_query/1" do
1680 defp days_ago(days) do
1682 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
1683 -days * 60 * 60 * 24,
1688 test "Users are inactive by default" do
1692 Enum.map(1..total, fn _ ->
1693 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1696 inactive_users_ids =
1697 Pleroma.User.list_inactive_users_query()
1698 |> Pleroma.Repo.all()
1699 |> Enum.map(& &1.id)
1701 Enum.each(users, fn user ->
1702 assert user.id in inactive_users_ids
1706 test "Only includes users who has no recent activity" do
1710 Enum.map(1..total, fn _ ->
1711 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1714 {inactive, active} = Enum.split(users, trunc(total / 2))
1716 Enum.map(active, fn user ->
1717 to = Enum.random(users -- [user])
1720 CommonAPI.post(user, %{
1721 status: "hey @#{to.nickname}"
1725 inactive_users_ids =
1726 Pleroma.User.list_inactive_users_query()
1727 |> Pleroma.Repo.all()
1728 |> Enum.map(& &1.id)
1730 Enum.each(active, fn user ->
1731 refute user.id in inactive_users_ids
1734 Enum.each(inactive, fn user ->
1735 assert user.id in inactive_users_ids
1739 test "Only includes users with no read notifications" do
1743 Enum.map(1..total, fn _ ->
1744 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1747 [sender | recipients] = users
1748 {inactive, active} = Enum.split(recipients, trunc(total / 2))
1750 Enum.each(recipients, fn to ->
1752 CommonAPI.post(sender, %{
1753 status: "hey @#{to.nickname}"
1757 CommonAPI.post(sender, %{
1758 status: "hey again @#{to.nickname}"
1762 Enum.each(active, fn user ->
1763 [n1, _n2] = Pleroma.Notification.for_user(user)
1764 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
1767 inactive_users_ids =
1768 Pleroma.User.list_inactive_users_query()
1769 |> Pleroma.Repo.all()
1770 |> Enum.map(& &1.id)
1772 Enum.each(active, fn user ->
1773 refute user.id in inactive_users_ids
1776 Enum.each(inactive, fn user ->
1777 assert user.id in inactive_users_ids
1782 describe "toggle_confirmation/1" do
1783 test "if user is confirmed" do
1784 user = insert(:user, confirmation_pending: false)
1785 {:ok, user} = User.toggle_confirmation(user)
1787 assert user.confirmation_pending
1788 assert user.confirmation_token
1791 test "if user is unconfirmed" do
1792 user = insert(:user, confirmation_pending: true, confirmation_token: "some token")
1793 {:ok, user} = User.toggle_confirmation(user)
1795 refute user.confirmation_pending
1796 refute user.confirmation_token
1800 describe "ensure_keys_present" do
1801 test "it creates keys for a user and stores them in info" do
1802 user = insert(:user)
1803 refute is_binary(user.keys)
1804 {:ok, user} = User.ensure_keys_present(user)
1805 assert is_binary(user.keys)
1808 test "it doesn't create keys if there already are some" do
1809 user = insert(:user, keys: "xxx")
1810 {:ok, user} = User.ensure_keys_present(user)
1811 assert user.keys == "xxx"
1815 describe "get_ap_ids_by_nicknames" do
1816 test "it returns a list of AP ids for a given set of nicknames" do
1817 user = insert(:user)
1818 user_two = insert(:user)
1820 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
1821 assert length(ap_ids) == 2
1822 assert user.ap_id in ap_ids
1823 assert user_two.ap_id in ap_ids
1827 describe "sync followers count" do
1829 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
1830 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
1831 insert(:user, local: true)
1832 insert(:user, local: false, deactivated: true)
1833 {:ok, user1: user1, user2: user2}
1836 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
1837 [fdb_user1] = User.external_users(limit: 1)
1839 assert fdb_user1.ap_id
1840 assert fdb_user1.ap_id == user1.ap_id
1841 assert fdb_user1.id == user1.id
1843 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
1845 assert fdb_user2.ap_id
1846 assert fdb_user2.ap_id == user2.ap_id
1847 assert fdb_user2.id == user2.id
1849 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
1853 describe "is_internal_user?/1" do
1854 test "non-internal user returns false" do
1855 user = insert(:user)
1856 refute User.is_internal_user?(user)
1859 test "user with no nickname returns true" do
1860 user = insert(:user, %{nickname: nil})
1861 assert User.is_internal_user?(user)
1864 test "user with internal-prefixed nickname returns true" do
1865 user = insert(:user, %{nickname: "internal.test"})
1866 assert User.is_internal_user?(user)
1870 describe "update_and_set_cache/1" do
1871 test "returns error when user is stale instead Ecto.StaleEntryError" do
1872 user = insert(:user)
1874 changeset = Ecto.Changeset.change(user, bio: "test")
1878 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
1879 User.update_and_set_cache(changeset)
1882 test "performs update cache if user updated" do
1883 user = insert(:user)
1884 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1886 changeset = Ecto.Changeset.change(user, bio: "test-bio")
1888 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
1889 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1890 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
1894 describe "following/followers synchronization" do
1895 setup do: clear_config([:instance, :external_user_synchronization])
1897 test "updates the counters normally on following/getting a follow when disabled" do
1898 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1899 user = insert(:user)
1904 follower_address: "http://localhost:4001/users/masto_closed/followers",
1905 following_address: "http://localhost:4001/users/masto_closed/following",
1909 assert other_user.following_count == 0
1910 assert other_user.follower_count == 0
1912 {:ok, user} = Pleroma.User.follow(user, other_user)
1913 other_user = Pleroma.User.get_by_id(other_user.id)
1915 assert user.following_count == 1
1916 assert other_user.follower_count == 1
1919 test "syncronizes the counters with the remote instance for the followed when enabled" do
1920 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1922 user = insert(:user)
1927 follower_address: "http://localhost:4001/users/masto_closed/followers",
1928 following_address: "http://localhost:4001/users/masto_closed/following",
1932 assert other_user.following_count == 0
1933 assert other_user.follower_count == 0
1935 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1936 {:ok, _user} = User.follow(user, other_user)
1937 other_user = User.get_by_id(other_user.id)
1939 assert other_user.follower_count == 437
1942 test "syncronizes the counters with the remote instance for the follower when enabled" do
1943 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1945 user = insert(:user)
1950 follower_address: "http://localhost:4001/users/masto_closed/followers",
1951 following_address: "http://localhost:4001/users/masto_closed/following",
1955 assert other_user.following_count == 0
1956 assert other_user.follower_count == 0
1958 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1959 {:ok, other_user} = User.follow(other_user, user)
1961 assert other_user.following_count == 152
1965 describe "change_email/2" do
1967 [user: insert(:user)]
1970 test "blank email returns error", %{user: user} do
1971 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
1972 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
1975 test "non unique email returns error", %{user: user} do
1976 %{email: email} = insert(:user)
1978 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
1979 User.change_email(user, email)
1982 test "invalid email returns error", %{user: user} do
1983 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
1984 User.change_email(user, "cofe")
1987 test "changes email", %{user: user} do
1988 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
1992 describe "get_cached_by_nickname_or_id" do
1994 local_user = insert(:user)
1995 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
1997 [local_user: local_user, remote_user: remote_user]
2000 setup do: clear_config([:instance, :limit_to_local_content])
2002 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
2003 remote_user: remote_user
2005 Pleroma.Config.put([:instance, :limit_to_local_content], false)
2006 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2008 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2009 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2011 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2012 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2015 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
2016 %{remote_user: remote_user} do
2017 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2018 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2021 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
2022 %{remote_user: remote_user, local_user: local_user} do
2023 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2024 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
2027 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
2028 %{remote_user: remote_user} do
2029 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2030 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2033 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
2034 %{local_user: local_user} do
2035 Pleroma.Config.put([:instance, :limit_to_local_content], false)
2036 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2038 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2039 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2041 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2042 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2046 describe "update_email_notifications/2" do
2048 user = insert(:user, email_notifications: %{"digest" => true})
2053 test "Notifications are updated", %{user: user} do
2054 true = user.email_notifications["digest"]
2055 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
2056 assert result.email_notifications["digest"] == false
2060 test "avatar fallback" do
2061 user = insert(:user)
2062 assert User.avatar_url(user) =~ "/images/avi.png"
2064 clear_config([:assets, :default_user_avatar], "avatar.png")
2066 user = User.get_cached_by_nickname_or_id(user.nickname)
2067 assert User.avatar_url(user) =~ "avatar.png"
2069 assert User.avatar_url(user, no_default: true) == nil