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)
968 muted_user = insert(:user)
970 {:ok, _user_relationships} = User.mute(user, muted_user, %{expires_in: 60})
971 assert User.mutes?(user, muted_user)
973 worker = Pleroma.Workers.MuteExpireWorker
974 args = %{"op" => "unmute_user", "muter_id" => user.id, "mutee_id" => muted_user.id}
981 assert :ok = perform_job(worker, args)
983 refute User.mutes?(user, muted_user)
984 refute User.muted_notifications?(user, muted_user)
987 test "it unmutes users" do
989 muted_user = insert(:user)
991 {:ok, _user_relationships} = User.mute(user, muted_user)
992 {:ok, _user_mute} = User.unmute(user, muted_user)
994 refute User.mutes?(user, muted_user)
995 refute User.muted_notifications?(user, muted_user)
998 test "it mutes user without notifications" do
1000 muted_user = insert(:user)
1002 refute User.mutes?(user, muted_user)
1003 refute User.muted_notifications?(user, muted_user)
1005 {:ok, _user_relationships} = User.mute(user, muted_user, %{notifications: false})
1007 assert User.mutes?(user, muted_user)
1008 refute User.muted_notifications?(user, muted_user)
1012 describe "blocks" do
1013 test "it blocks people" do
1014 user = insert(:user)
1015 blocked_user = insert(:user)
1017 refute User.blocks?(user, blocked_user)
1019 {:ok, _user_relationship} = User.block(user, blocked_user)
1021 assert User.blocks?(user, blocked_user)
1024 test "it unblocks users" do
1025 user = insert(:user)
1026 blocked_user = insert(:user)
1028 {:ok, _user_relationship} = User.block(user, blocked_user)
1029 {:ok, _user_block} = User.unblock(user, blocked_user)
1031 refute User.blocks?(user, blocked_user)
1034 test "blocks tear down cyclical follow relationships" do
1035 blocker = insert(:user)
1036 blocked = insert(:user)
1038 {:ok, blocker} = User.follow(blocker, blocked)
1039 {:ok, blocked} = User.follow(blocked, blocker)
1041 assert User.following?(blocker, blocked)
1042 assert User.following?(blocked, blocker)
1044 {:ok, _user_relationship} = User.block(blocker, blocked)
1045 blocked = User.get_cached_by_id(blocked.id)
1047 assert User.blocks?(blocker, blocked)
1049 refute User.following?(blocker, blocked)
1050 refute User.following?(blocked, blocker)
1053 test "blocks tear down blocker->blocked follow relationships" do
1054 blocker = insert(:user)
1055 blocked = insert(:user)
1057 {:ok, blocker} = User.follow(blocker, blocked)
1059 assert User.following?(blocker, blocked)
1060 refute User.following?(blocked, blocker)
1062 {:ok, _user_relationship} = User.block(blocker, blocked)
1063 blocked = User.get_cached_by_id(blocked.id)
1065 assert User.blocks?(blocker, blocked)
1067 refute User.following?(blocker, blocked)
1068 refute User.following?(blocked, blocker)
1071 test "blocks tear down blocked->blocker follow relationships" do
1072 blocker = insert(:user)
1073 blocked = insert(:user)
1075 {:ok, blocked} = User.follow(blocked, blocker)
1077 refute User.following?(blocker, blocked)
1078 assert User.following?(blocked, blocker)
1080 {:ok, _user_relationship} = User.block(blocker, blocked)
1081 blocked = User.get_cached_by_id(blocked.id)
1083 assert User.blocks?(blocker, blocked)
1085 refute User.following?(blocker, blocked)
1086 refute User.following?(blocked, blocker)
1089 test "blocks tear down blocked->blocker subscription relationships" do
1090 blocker = insert(:user)
1091 blocked = insert(:user)
1093 {:ok, _subscription} = User.subscribe(blocked, blocker)
1095 assert User.subscribed_to?(blocked, blocker)
1096 refute User.subscribed_to?(blocker, blocked)
1098 {:ok, _user_relationship} = User.block(blocker, blocked)
1100 assert User.blocks?(blocker, blocked)
1101 refute User.subscribed_to?(blocker, blocked)
1102 refute User.subscribed_to?(blocked, blocker)
1106 describe "domain blocking" do
1107 test "blocks domains" do
1108 user = insert(:user)
1109 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1111 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1113 assert User.blocks?(user, collateral_user)
1116 test "does not block domain with same end" do
1117 user = insert(:user)
1120 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1122 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1124 refute User.blocks?(user, collateral_user)
1127 test "does not block domain with same end if wildcard added" do
1128 user = insert(:user)
1131 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1133 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1135 refute User.blocks?(user, collateral_user)
1138 test "blocks domain with wildcard for subdomain" do
1139 user = insert(:user)
1141 user_from_subdomain =
1142 insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
1144 user_with_two_subdomains =
1146 ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
1149 user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1151 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1153 assert User.blocks?(user, user_from_subdomain)
1154 assert User.blocks?(user, user_with_two_subdomains)
1155 assert User.blocks?(user, user_domain)
1158 test "unblocks domains" do
1159 user = insert(:user)
1160 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1162 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1163 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
1165 refute User.blocks?(user, collateral_user)
1168 test "follows take precedence over domain blocks" do
1169 user = insert(:user)
1170 good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
1172 {:ok, user} = User.block_domain(user, "meanies.social")
1173 {:ok, user} = User.follow(user, good_eggo)
1175 refute User.blocks?(user, good_eggo)
1179 describe "blocks_import" do
1180 test "it imports user blocks from list" do
1181 [user1, user2, user3] = insert_list(3, :user)
1188 {:ok, job} = User.blocks_import(user1, identifiers)
1190 assert {:ok, result} = ObanHelpers.perform(job)
1191 assert is_list(result)
1192 assert result == [user2, user3]
1196 describe "get_recipients_from_activity" do
1197 test "works for announces" do
1198 actor = insert(:user)
1199 user = insert(:user, local: true)
1201 {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
1202 {:ok, announce} = CommonAPI.repeat(activity.id, user)
1204 recipients = User.get_recipients_from_activity(announce)
1206 assert user in recipients
1209 test "get recipients" do
1210 actor = insert(:user)
1211 user = insert(:user, local: true)
1212 user_two = insert(:user, local: false)
1213 addressed = insert(:user, local: true)
1214 addressed_remote = insert(:user, local: false)
1217 CommonAPI.post(actor, %{
1218 status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
1221 assert Enum.map([actor, addressed], & &1.ap_id) --
1222 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1224 {:ok, user} = User.follow(user, actor)
1225 {:ok, _user_two} = User.follow(user_two, actor)
1226 recipients = User.get_recipients_from_activity(activity)
1227 assert length(recipients) == 3
1228 assert user in recipients
1229 assert addressed in recipients
1232 test "has following" do
1233 actor = insert(:user)
1234 user = insert(:user)
1235 user_two = insert(:user)
1236 addressed = insert(:user, local: true)
1239 CommonAPI.post(actor, %{
1240 status: "hey @#{addressed.nickname}"
1243 assert Enum.map([actor, addressed], & &1.ap_id) --
1244 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1246 {:ok, _actor} = User.follow(actor, user)
1247 {:ok, _actor} = User.follow(actor, user_two)
1248 recipients = User.get_recipients_from_activity(activity)
1249 assert length(recipients) == 2
1250 assert addressed in recipients
1254 describe ".deactivate" do
1255 test "can de-activate then re-activate a user" do
1256 user = insert(:user)
1257 assert false == user.deactivated
1258 {:ok, user} = User.deactivate(user)
1259 assert true == user.deactivated
1260 {:ok, user} = User.deactivate(user, false)
1261 assert false == user.deactivated
1264 test "hide a user from followers" do
1265 user = insert(:user)
1266 user2 = insert(:user)
1268 {:ok, user} = User.follow(user, user2)
1269 {:ok, _user} = User.deactivate(user)
1271 user2 = User.get_cached_by_id(user2.id)
1273 assert user2.follower_count == 0
1274 assert [] = User.get_followers(user2)
1277 test "hide a user from friends" do
1278 user = insert(:user)
1279 user2 = insert(:user)
1281 {:ok, user2} = User.follow(user2, user)
1282 assert user2.following_count == 1
1283 assert User.following_count(user2) == 1
1285 {:ok, _user} = User.deactivate(user)
1287 user2 = User.get_cached_by_id(user2.id)
1289 assert refresh_record(user2).following_count == 0
1290 assert user2.following_count == 0
1291 assert User.following_count(user2) == 0
1292 assert [] = User.get_friends(user2)
1295 test "hide a user's statuses from timelines and notifications" do
1296 user = insert(:user)
1297 user2 = insert(:user)
1299 {:ok, user2} = User.follow(user2, user)
1301 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
1303 activity = Repo.preload(activity, :bookmark)
1305 [notification] = Pleroma.Notification.for_user(user2)
1306 assert notification.activity.id == activity.id
1308 assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
1310 assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
1311 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1315 {:ok, _user} = User.deactivate(user)
1317 assert [] == ActivityPub.fetch_public_activities(%{})
1318 assert [] == Pleroma.Notification.for_user(user2)
1321 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1327 describe "approve" do
1328 test "approves a user" do
1329 user = insert(:user, approval_pending: true)
1330 assert true == user.approval_pending
1331 {:ok, user} = User.approve(user)
1332 assert false == user.approval_pending
1335 test "approves a list of users" do
1336 unapproved_users = [
1337 insert(:user, approval_pending: true),
1338 insert(:user, approval_pending: true),
1339 insert(:user, approval_pending: true)
1342 {:ok, users} = User.approve(unapproved_users)
1344 assert Enum.count(users) == 3
1346 Enum.each(users, fn user ->
1347 assert false == user.approval_pending
1352 describe "delete" do
1354 {:ok, user} = insert(:user) |> User.set_cache()
1359 setup do: clear_config([:instance, :federating])
1361 test ".delete_user_activities deletes all create activities", %{user: user} do
1362 {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
1364 User.delete_user_activities(user)
1366 # TODO: Test removal favorites, repeats, delete activities.
1367 refute Activity.get_by_id(activity.id)
1370 test "it deactivates a user, all follow relationships and all activities", %{user: user} do
1371 follower = insert(:user)
1372 {:ok, follower} = User.follow(follower, user)
1374 locked_user = insert(:user, name: "locked", locked: true)
1375 {:ok, _} = User.follow(user, locked_user, :follow_pending)
1377 object = insert(:note, user: user)
1378 activity = insert(:note_activity, user: user, note: object)
1380 object_two = insert(:note, user: follower)
1381 activity_two = insert(:note_activity, user: follower, note: object_two)
1383 {:ok, like} = CommonAPI.favorite(user, activity_two.id)
1384 {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
1385 {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
1387 {:ok, job} = User.delete(user)
1388 {:ok, _user} = ObanHelpers.perform(job)
1390 follower = User.get_cached_by_id(follower.id)
1392 refute User.following?(follower, user)
1393 assert %{deactivated: true} = User.get_by_id(user.id)
1395 assert [] == User.get_follow_requests(locked_user)
1399 |> Activity.Queries.by_actor()
1401 |> Enum.map(fn act -> act.data["type"] end)
1403 assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
1405 refute Activity.get_by_id(activity.id)
1406 refute Activity.get_by_id(like.id)
1407 refute Activity.get_by_id(like_two.id)
1408 refute Activity.get_by_id(repeat.id)
1412 describe "delete/1 when confirmation is pending" do
1414 user = insert(:user, confirmation_pending: true)
1418 test "deletes user from database when activation required", %{user: user} do
1419 clear_config([:instance, :account_activation_required], 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 "deactivates user when activation is not required", %{user: user} do
1429 clear_config([:instance, :account_activation_required], false)
1431 {:ok, job} = User.delete(user)
1432 {:ok, _} = ObanHelpers.perform(job)
1434 assert %{deactivated: true} = User.get_cached_by_id(user.id)
1435 assert %{deactivated: true} = User.get_by_id(user.id)
1439 test "delete/1 when approval is pending deletes the user" do
1440 user = insert(:user, approval_pending: true)
1442 {:ok, job} = User.delete(user)
1443 {:ok, _} = ObanHelpers.perform(job)
1445 refute User.get_cached_by_id(user.id)
1446 refute User.get_by_id(user.id)
1449 test "delete/1 purges a user when they wouldn't be fully deleted" do
1454 password_hash: "pdfk2$1b3n159001",
1455 keys: "RSA begin buplic key",
1456 public_key: "--PRIVATE KEYE--",
1457 avatar: %{"a" => "b"},
1459 banner: %{"a" => "b"},
1460 background: %{"a" => "b"},
1463 following_count: 9001,
1465 confirmation_pending: true,
1466 password_reset_pending: true,
1467 approval_pending: true,
1468 registration_reason: "ahhhhh",
1469 confirmation_token: "qqqq",
1470 domain_blocks: ["lain.com"],
1475 mastofe_settings: %{"a" => "b"},
1476 mascot: %{"a" => "b"},
1477 emoji: %{"a" => "b"},
1478 pleroma_settings_store: %{"q" => "x"},
1479 fields: [%{"gg" => "qq"}],
1480 raw_fields: [%{"gg" => "qq"}],
1482 also_known_as: ["https://lol.olo/users/loll"]
1485 {:ok, job} = User.delete(user)
1486 {:ok, _} = ObanHelpers.perform(job)
1487 user = User.get_by_id(user.id)
1499 last_refreshed_at: nil,
1500 last_digest_emailed_at: nil,
1507 confirmation_pending: false,
1508 password_reset_pending: false,
1509 approval_pending: false,
1510 registration_reason: nil,
1511 confirmation_token: nil,
1515 is_moderator: false,
1517 mastofe_settings: nil,
1520 pleroma_settings_store: %{},
1523 discoverable: false,
1528 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1529 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1532 describe "per-user rich-text filtering" do
1533 test "html_filter_policy returns default policies, when rich-text is enabled" do
1534 user = insert(:user)
1536 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1539 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1540 user = insert(:user, no_rich_text: true)
1542 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1546 describe "caching" do
1547 test "invalidate_cache works" do
1548 user = insert(:user)
1550 User.set_cache(user)
1551 User.invalidate_cache(user)
1553 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1554 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1557 test "User.delete() plugs any possible zombie objects" do
1558 user = insert(:user)
1560 {:ok, job} = User.delete(user)
1561 {:ok, _} = ObanHelpers.perform(job)
1563 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1565 assert cached_user != user
1567 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1569 assert cached_user != user
1573 describe "account_status/1" do
1574 setup do: clear_config([:instance, :account_activation_required])
1576 test "return confirmation_pending for unconfirm user" do
1577 Pleroma.Config.put([:instance, :account_activation_required], true)
1578 user = insert(:user, confirmation_pending: true)
1579 assert User.account_status(user) == :confirmation_pending
1582 test "return active for confirmed user" do
1583 Pleroma.Config.put([:instance, :account_activation_required], true)
1584 user = insert(:user, confirmation_pending: false)
1585 assert User.account_status(user) == :active
1588 test "return active for remote user" do
1589 user = insert(:user, local: false)
1590 assert User.account_status(user) == :active
1593 test "returns :password_reset_pending for user with reset password" do
1594 user = insert(:user, password_reset_pending: true)
1595 assert User.account_status(user) == :password_reset_pending
1598 test "returns :deactivated for deactivated user" do
1599 user = insert(:user, local: true, confirmation_pending: false, deactivated: true)
1600 assert User.account_status(user) == :deactivated
1603 test "returns :approval_pending for unapproved user" do
1604 user = insert(:user, local: true, approval_pending: true)
1605 assert User.account_status(user) == :approval_pending
1607 user = insert(:user, local: true, confirmation_pending: true, approval_pending: true)
1608 assert User.account_status(user) == :approval_pending
1612 describe "superuser?/1" do
1613 test "returns false for unprivileged users" do
1614 user = insert(:user, local: true)
1616 refute User.superuser?(user)
1619 test "returns false for remote users" do
1620 user = insert(:user, local: false)
1621 remote_admin_user = insert(:user, local: false, is_admin: true)
1623 refute User.superuser?(user)
1624 refute User.superuser?(remote_admin_user)
1627 test "returns true for local moderators" do
1628 user = insert(:user, local: true, is_moderator: true)
1630 assert User.superuser?(user)
1633 test "returns true for local admins" do
1634 user = insert(:user, local: true, is_admin: true)
1636 assert User.superuser?(user)
1640 describe "invisible?/1" do
1641 test "returns true for an invisible user" do
1642 user = insert(:user, local: true, invisible: true)
1644 assert User.invisible?(user)
1647 test "returns false for a non-invisible user" do
1648 user = insert(:user, local: true)
1650 refute User.invisible?(user)
1654 describe "visible_for/2" do
1655 test "returns true when the account is itself" do
1656 user = insert(:user, local: true)
1658 assert User.visible_for(user, user) == :visible
1661 test "returns false when the account is unauthenticated and auth is required" do
1662 Pleroma.Config.put([:instance, :account_activation_required], true)
1664 user = insert(:user, local: true, confirmation_pending: true)
1665 other_user = insert(:user, local: true)
1667 refute User.visible_for(user, other_user) == :visible
1670 test "returns true when the account is unauthenticated and auth is not required" do
1671 user = insert(:user, local: true, confirmation_pending: true)
1672 other_user = insert(:user, local: true)
1674 assert User.visible_for(user, other_user) == :visible
1677 test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
1678 Pleroma.Config.put([:instance, :account_activation_required], true)
1680 user = insert(:user, local: true, confirmation_pending: true)
1681 other_user = insert(:user, local: true, is_admin: true)
1683 assert User.visible_for(user, other_user) == :visible
1687 describe "parse_bio/2" do
1688 test "preserves hosts in user links text" do
1689 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1690 user = insert(:user)
1691 bio = "A.k.a. @nick@domain.com"
1694 ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
1696 }" rel="ugc">@<span>nick@domain.com</span></a></span>)
1698 assert expected_text == User.parse_bio(bio, user)
1701 test "Adds rel=me on linkbacked urls" do
1702 user = insert(:user, ap_id: "https://social.example.org/users/lain")
1704 bio = "http://example.com/rel_me/null"
1705 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1706 assert expected_text == User.parse_bio(bio, user)
1708 bio = "http://example.com/rel_me/link"
1709 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1710 assert expected_text == User.parse_bio(bio, user)
1712 bio = "http://example.com/rel_me/anchor"
1713 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1714 assert expected_text == User.parse_bio(bio, user)
1718 test "follower count is updated when a follower is blocked" do
1719 user = insert(:user)
1720 follower = insert(:user)
1721 follower2 = insert(:user)
1722 follower3 = insert(:user)
1724 {:ok, follower} = User.follow(follower, user)
1725 {:ok, _follower2} = User.follow(follower2, user)
1726 {:ok, _follower3} = User.follow(follower3, user)
1728 {:ok, _user_relationship} = User.block(user, follower)
1729 user = refresh_record(user)
1731 assert user.follower_count == 2
1734 describe "list_inactive_users_query/1" do
1735 defp days_ago(days) do
1737 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
1738 -days * 60 * 60 * 24,
1743 test "Users are inactive by default" do
1747 Enum.map(1..total, fn _ ->
1748 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1751 inactive_users_ids =
1752 Pleroma.User.list_inactive_users_query()
1753 |> Pleroma.Repo.all()
1754 |> Enum.map(& &1.id)
1756 Enum.each(users, fn user ->
1757 assert user.id in inactive_users_ids
1761 test "Only includes users who has no recent activity" do
1765 Enum.map(1..total, fn _ ->
1766 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1769 {inactive, active} = Enum.split(users, trunc(total / 2))
1771 Enum.map(active, fn user ->
1772 to = Enum.random(users -- [user])
1775 CommonAPI.post(user, %{
1776 status: "hey @#{to.nickname}"
1780 inactive_users_ids =
1781 Pleroma.User.list_inactive_users_query()
1782 |> Pleroma.Repo.all()
1783 |> Enum.map(& &1.id)
1785 Enum.each(active, fn user ->
1786 refute user.id in inactive_users_ids
1789 Enum.each(inactive, fn user ->
1790 assert user.id in inactive_users_ids
1794 test "Only includes users with no read notifications" do
1798 Enum.map(1..total, fn _ ->
1799 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1802 [sender | recipients] = users
1803 {inactive, active} = Enum.split(recipients, trunc(total / 2))
1805 Enum.each(recipients, fn to ->
1807 CommonAPI.post(sender, %{
1808 status: "hey @#{to.nickname}"
1812 CommonAPI.post(sender, %{
1813 status: "hey again @#{to.nickname}"
1817 Enum.each(active, fn user ->
1818 [n1, _n2] = Pleroma.Notification.for_user(user)
1819 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
1822 inactive_users_ids =
1823 Pleroma.User.list_inactive_users_query()
1824 |> Pleroma.Repo.all()
1825 |> Enum.map(& &1.id)
1827 Enum.each(active, fn user ->
1828 refute user.id in inactive_users_ids
1831 Enum.each(inactive, fn user ->
1832 assert user.id in inactive_users_ids
1837 describe "toggle_confirmation/1" do
1838 test "if user is confirmed" do
1839 user = insert(:user, confirmation_pending: false)
1840 {:ok, user} = User.toggle_confirmation(user)
1842 assert user.confirmation_pending
1843 assert user.confirmation_token
1846 test "if user is unconfirmed" do
1847 user = insert(:user, confirmation_pending: true, confirmation_token: "some token")
1848 {:ok, user} = User.toggle_confirmation(user)
1850 refute user.confirmation_pending
1851 refute user.confirmation_token
1855 describe "ensure_keys_present" do
1856 test "it creates keys for a user and stores them in info" do
1857 user = insert(:user)
1858 refute is_binary(user.keys)
1859 {:ok, user} = User.ensure_keys_present(user)
1860 assert is_binary(user.keys)
1863 test "it doesn't create keys if there already are some" do
1864 user = insert(:user, keys: "xxx")
1865 {:ok, user} = User.ensure_keys_present(user)
1866 assert user.keys == "xxx"
1870 describe "get_ap_ids_by_nicknames" do
1871 test "it returns a list of AP ids for a given set of nicknames" do
1872 user = insert(:user)
1873 user_two = insert(:user)
1875 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
1876 assert length(ap_ids) == 2
1877 assert user.ap_id in ap_ids
1878 assert user_two.ap_id in ap_ids
1882 describe "sync followers count" do
1884 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
1885 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
1886 insert(:user, local: true)
1887 insert(:user, local: false, deactivated: true)
1888 {:ok, user1: user1, user2: user2}
1891 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
1892 [fdb_user1] = User.external_users(limit: 1)
1894 assert fdb_user1.ap_id
1895 assert fdb_user1.ap_id == user1.ap_id
1896 assert fdb_user1.id == user1.id
1898 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
1900 assert fdb_user2.ap_id
1901 assert fdb_user2.ap_id == user2.ap_id
1902 assert fdb_user2.id == user2.id
1904 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
1908 describe "is_internal_user?/1" do
1909 test "non-internal user returns false" do
1910 user = insert(:user)
1911 refute User.is_internal_user?(user)
1914 test "user with no nickname returns true" do
1915 user = insert(:user, %{nickname: nil})
1916 assert User.is_internal_user?(user)
1919 test "user with internal-prefixed nickname returns true" do
1920 user = insert(:user, %{nickname: "internal.test"})
1921 assert User.is_internal_user?(user)
1925 describe "update_and_set_cache/1" do
1926 test "returns error when user is stale instead Ecto.StaleEntryError" do
1927 user = insert(:user)
1929 changeset = Ecto.Changeset.change(user, bio: "test")
1933 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
1934 User.update_and_set_cache(changeset)
1937 test "performs update cache if user updated" do
1938 user = insert(:user)
1939 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1941 changeset = Ecto.Changeset.change(user, bio: "test-bio")
1943 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
1944 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1945 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
1949 describe "following/followers synchronization" do
1950 setup do: clear_config([:instance, :external_user_synchronization])
1952 test "updates the counters normally on following/getting a follow when disabled" do
1953 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1954 user = insert(:user)
1959 follower_address: "http://localhost:4001/users/masto_closed/followers",
1960 following_address: "http://localhost:4001/users/masto_closed/following",
1964 assert other_user.following_count == 0
1965 assert other_user.follower_count == 0
1967 {:ok, user} = Pleroma.User.follow(user, other_user)
1968 other_user = Pleroma.User.get_by_id(other_user.id)
1970 assert user.following_count == 1
1971 assert other_user.follower_count == 1
1974 test "syncronizes the counters with the remote instance for the followed when enabled" do
1975 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1977 user = insert(:user)
1982 follower_address: "http://localhost:4001/users/masto_closed/followers",
1983 following_address: "http://localhost:4001/users/masto_closed/following",
1987 assert other_user.following_count == 0
1988 assert other_user.follower_count == 0
1990 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1991 {:ok, _user} = User.follow(user, other_user)
1992 other_user = User.get_by_id(other_user.id)
1994 assert other_user.follower_count == 437
1997 test "syncronizes the counters with the remote instance for the follower when enabled" do
1998 Pleroma.Config.put([:instance, :external_user_synchronization], false)
2000 user = insert(:user)
2005 follower_address: "http://localhost:4001/users/masto_closed/followers",
2006 following_address: "http://localhost:4001/users/masto_closed/following",
2010 assert other_user.following_count == 0
2011 assert other_user.follower_count == 0
2013 Pleroma.Config.put([:instance, :external_user_synchronization], true)
2014 {:ok, other_user} = User.follow(other_user, user)
2016 assert other_user.following_count == 152
2020 describe "change_email/2" do
2022 [user: insert(:user)]
2025 test "blank email returns error", %{user: user} do
2026 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
2027 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
2030 test "non unique email returns error", %{user: user} do
2031 %{email: email} = insert(:user)
2033 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
2034 User.change_email(user, email)
2037 test "invalid email returns error", %{user: user} do
2038 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
2039 User.change_email(user, "cofe")
2042 test "changes email", %{user: user} do
2043 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
2047 describe "get_cached_by_nickname_or_id" do
2049 local_user = insert(:user)
2050 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
2052 [local_user: local_user, remote_user: remote_user]
2055 setup do: clear_config([:instance, :limit_to_local_content])
2057 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
2058 remote_user: remote_user
2060 Pleroma.Config.put([:instance, :limit_to_local_content], false)
2061 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2063 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2064 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2066 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2067 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2070 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
2071 %{remote_user: remote_user} do
2072 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2073 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2076 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
2077 %{remote_user: remote_user, local_user: local_user} do
2078 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2079 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
2082 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
2083 %{remote_user: remote_user} do
2084 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2085 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2088 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
2089 %{local_user: local_user} do
2090 Pleroma.Config.put([:instance, :limit_to_local_content], false)
2091 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2093 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2094 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2096 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2097 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2101 describe "update_email_notifications/2" do
2103 user = insert(:user, email_notifications: %{"digest" => true})
2108 test "Notifications are updated", %{user: user} do
2109 true = user.email_notifications["digest"]
2110 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
2111 assert result.email_notifications["digest"] == false
2115 test "avatar fallback" do
2116 user = insert(:user)
2117 assert User.avatar_url(user) =~ "/images/avi.png"
2119 clear_config([:assets, :default_user_avatar], "avatar.png")
2121 user = User.get_cached_by_nickname_or_id(user.nickname)
2122 assert User.avatar_url(user) =~ "avatar.png"
2124 assert User.avatar_url(user, no_default: true) == nil