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
444 clear_config(:mrf_simple,
447 federated_timeline_removal: [],
460 Pleroma.Web.ActivityPub.MRF.SimplePolicy
464 test "it sends a welcome chat message when Simple policy applied to local instance" do
465 Pleroma.Config.put([:mrf_simple, :media_nsfw], ["localhost"])
467 welcome_user = insert(:user)
468 Pleroma.Config.put([:welcome, :chat_message, :enabled], true)
469 Pleroma.Config.put([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
470 Pleroma.Config.put([:welcome, :chat_message, :message], "Hello, this is a chat message")
472 cng = User.register_changeset(%User{}, @full_user_data)
473 {:ok, registered_user} = User.register(cng)
474 ObanHelpers.perform_all()
476 activity = Repo.one(Pleroma.Activity)
477 assert registered_user.ap_id in activity.recipients
478 assert Object.normalize(activity).data["content"] =~ "chat message"
479 assert activity.actor == welcome_user.ap_id
482 test "it sends a welcome email message if it is set" do
483 welcome_user = insert(:user)
484 Pleroma.Config.put([:welcome, :email, :enabled], true)
485 Pleroma.Config.put([:welcome, :email, :sender], welcome_user.email)
488 [:welcome, :email, :subject],
489 "Hello, welcome to cool site: <%= instance_name %>"
492 instance_name = Pleroma.Config.get([:instance, :name])
494 cng = User.register_changeset(%User{}, @full_user_data)
495 {:ok, registered_user} = User.register(cng)
496 ObanHelpers.perform_all()
499 from: {instance_name, welcome_user.email},
500 to: {registered_user.name, registered_user.email},
501 subject: "Hello, welcome to cool site: #{instance_name}",
502 html_body: "Welcome to #{instance_name}"
506 test "it sends a confirm email" do
507 Pleroma.Config.put([:instance, :account_activation_required], true)
509 cng = User.register_changeset(%User{}, @full_user_data)
510 {:ok, registered_user} = User.register(cng)
511 ObanHelpers.perform_all()
512 assert_email_sent(Pleroma.Emails.UserEmail.account_confirmation_email(registered_user))
515 test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do
516 Pleroma.Config.put([:instance, :account_activation_required], true)
520 |> Enum.each(fn key ->
521 params = Map.delete(@full_user_data, key)
522 changeset = User.register_changeset(%User{}, params)
524 assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
528 test "it requires an name, nickname and password, bio and email are optional when account_activation_required is disabled" do
529 Pleroma.Config.put([:instance, :account_activation_required], false)
533 |> Enum.each(fn key ->
534 params = Map.delete(@full_user_data, key)
535 changeset = User.register_changeset(%User{}, params)
537 assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid?
541 test "it restricts certain nicknames" do
542 [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
544 assert is_bitstring(restricted_name)
548 |> Map.put(:nickname, restricted_name)
550 changeset = User.register_changeset(%User{}, params)
552 refute changeset.valid?
555 test "it blocks blacklisted email domains" do
556 clear_config([User, :email_blacklist], ["trolling.world"])
559 params = Map.put(@full_user_data, :email, "troll@trolling.world")
560 changeset = User.register_changeset(%User{}, params)
561 refute changeset.valid?
563 # Block with subdomain match
564 params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world")
565 changeset = User.register_changeset(%User{}, params)
566 refute changeset.valid?
568 # Pass with different domains that are similar
569 params = Map.put(@full_user_data, :email, "troll@gnomestrolling.world")
570 changeset = User.register_changeset(%User{}, params)
571 assert changeset.valid?
573 params = Map.put(@full_user_data, :email, "troll@trolling.world.us")
574 changeset = User.register_changeset(%User{}, params)
575 assert changeset.valid?
578 test "it sets the password_hash and ap_id" do
579 changeset = User.register_changeset(%User{}, @full_user_data)
581 assert changeset.valid?
583 assert is_binary(changeset.changes[:password_hash])
584 assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
586 assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
589 test "it sets the 'accepts_chat_messages' set to true" do
590 changeset = User.register_changeset(%User{}, @full_user_data)
591 assert changeset.valid?
593 {:ok, user} = Repo.insert(changeset)
595 assert user.accepts_chat_messages
598 test "it creates a confirmed user" do
599 changeset = User.register_changeset(%User{}, @full_user_data)
600 assert changeset.valid?
602 {:ok, user} = Repo.insert(changeset)
604 refute user.confirmation_pending
608 describe "user registration, with :account_activation_required" do
614 password_confirmation: "test",
615 email: "email@example.com"
617 setup do: clear_config([:instance, :account_activation_required], true)
619 test "it creates unconfirmed user" do
620 changeset = User.register_changeset(%User{}, @full_user_data)
621 assert changeset.valid?
623 {:ok, user} = Repo.insert(changeset)
625 assert user.confirmation_pending
626 assert user.confirmation_token
629 test "it creates confirmed user if :confirmed option is given" do
630 changeset = User.register_changeset(%User{}, @full_user_data, need_confirmation: false)
631 assert changeset.valid?
633 {:ok, user} = Repo.insert(changeset)
635 refute user.confirmation_pending
636 refute user.confirmation_token
640 describe "user registration, with :account_approval_required" do
646 password_confirmation: "test",
647 email: "email@example.com",
648 registration_reason: "I'm a cool guy :)"
650 setup do: clear_config([:instance, :account_approval_required], true)
652 test "it creates unapproved user" do
653 changeset = User.register_changeset(%User{}, @full_user_data)
654 assert changeset.valid?
656 {:ok, user} = Repo.insert(changeset)
658 assert user.approval_pending
659 assert user.registration_reason == "I'm a cool guy :)"
662 test "it restricts length of registration reason" do
663 reason_limit = Pleroma.Config.get([:instance, :registration_reason_length])
665 assert is_integer(reason_limit)
670 :registration_reason,
671 "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."
674 changeset = User.register_changeset(%User{}, params)
676 refute changeset.valid?
680 describe "get_or_fetch/1" do
681 test "gets an existing user by nickname" do
683 {:ok, fetched_user} = User.get_or_fetch(user.nickname)
685 assert user == fetched_user
688 test "gets an existing user by ap_id" do
689 ap_id = "http://mastodon.example.org/users/admin"
695 nickname: "admin@mastodon.example.org",
699 {:ok, fetched_user} = User.get_or_fetch(ap_id)
700 freshed_user = refresh_record(user)
701 assert freshed_user == fetched_user
705 describe "fetching a user from nickname or trying to build one" do
706 test "gets an existing user" do
708 {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
710 assert user == fetched_user
713 test "gets an existing user, case insensitive" do
714 user = insert(:user, nickname: "nick")
715 {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
717 assert user == fetched_user
720 test "gets an existing user by fully qualified nickname" do
723 {:ok, fetched_user} =
724 User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
726 assert user == fetched_user
729 test "gets an existing user by fully qualified nickname, case insensitive" do
730 user = insert(:user, nickname: "nick")
731 casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
733 {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
735 assert user == fetched_user
738 @tag capture_log: true
739 test "returns nil if no user could be fetched" do
740 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
741 assert fetched_user == "not found nonexistant@social.heldscal.la"
744 test "returns nil for nonexistant local user" do
745 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
746 assert fetched_user == "not found nonexistant"
749 test "updates an existing user, if stale" do
750 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
756 nickname: "admin@mastodon.example.org",
757 ap_id: "http://mastodon.example.org/users/admin",
758 last_refreshed_at: a_week_ago
761 assert orig_user.last_refreshed_at == a_week_ago
763 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
767 refute user.last_refreshed_at == orig_user.last_refreshed_at
770 test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
771 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
777 nickname: "admin@mastodon.example.org",
778 ap_id: "http://mastodon.example.org/users/harinezumigari",
779 last_refreshed_at: a_week_ago
782 assert orig_user.last_refreshed_at == a_week_ago
784 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
788 refute user.id == orig_user.id
790 orig_user = User.get_by_id(orig_user.id)
792 assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
795 @tag capture_log: true
796 test "it returns the old user if stale, but unfetchable" do
797 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
803 nickname: "admin@mastodon.example.org",
804 ap_id: "http://mastodon.example.org/users/raymoo",
805 last_refreshed_at: a_week_ago
808 assert orig_user.last_refreshed_at == a_week_ago
810 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/raymoo")
812 assert user.last_refreshed_at == orig_user.last_refreshed_at
816 test "returns an ap_id for a user" do
819 assert User.ap_id(user) ==
820 Pleroma.Web.Router.Helpers.user_feed_url(
821 Pleroma.Web.Endpoint,
827 test "returns an ap_followers link for a user" do
830 assert User.ap_followers(user) ==
831 Pleroma.Web.Router.Helpers.user_feed_url(
832 Pleroma.Web.Endpoint,
838 describe "remote user changeset" do
844 avatar: %{some: "avatar"}
846 setup do: clear_config([:instance, :user_bio_length])
847 setup do: clear_config([:instance, :user_name_length])
849 test "it confirms validity" do
850 cs = User.remote_user_changeset(@valid_remote)
854 test "it sets the follower_adress" do
855 cs = User.remote_user_changeset(@valid_remote)
856 # remote users get a fake local follower address
857 assert cs.changes.follower_address ==
858 User.ap_followers(%User{nickname: @valid_remote[:nickname]})
861 test "it enforces the fqn format for nicknames" do
862 cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})
863 assert Ecto.Changeset.get_field(cs, :local) == false
864 assert cs.changes.avatar
868 test "it has required fields" do
870 |> Enum.each(fn field ->
871 cs = User.remote_user_changeset(Map.delete(@valid_remote, field))
877 describe "followers and friends" do
878 test "gets all followers for a given user" do
880 follower_one = insert(:user)
881 follower_two = insert(:user)
882 not_follower = insert(:user)
884 {:ok, follower_one} = User.follow(follower_one, user)
885 {:ok, follower_two} = User.follow(follower_two, user)
887 res = User.get_followers(user)
889 assert Enum.member?(res, follower_one)
890 assert Enum.member?(res, follower_two)
891 refute Enum.member?(res, not_follower)
894 test "gets all friends (followed users) for a given user" do
896 followed_one = insert(:user)
897 followed_two = insert(:user)
898 not_followed = insert(:user)
900 {:ok, user} = User.follow(user, followed_one)
901 {:ok, user} = User.follow(user, followed_two)
903 res = User.get_friends(user)
905 followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
906 followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
907 assert Enum.member?(res, followed_one)
908 assert Enum.member?(res, followed_two)
909 refute Enum.member?(res, not_followed)
913 describe "updating note and follower count" do
914 test "it sets the note_count property" do
917 user = User.get_cached_by_ap_id(note.data["actor"])
919 assert user.note_count == 0
921 {:ok, user} = User.update_note_count(user)
923 assert user.note_count == 1
926 test "it increases the note_count property" do
928 user = User.get_cached_by_ap_id(note.data["actor"])
930 assert user.note_count == 0
932 {:ok, user} = User.increase_note_count(user)
934 assert user.note_count == 1
936 {:ok, user} = User.increase_note_count(user)
938 assert user.note_count == 2
941 test "it decreases the note_count property" do
943 user = User.get_cached_by_ap_id(note.data["actor"])
945 assert user.note_count == 0
947 {:ok, user} = User.increase_note_count(user)
949 assert user.note_count == 1
951 {:ok, user} = User.decrease_note_count(user)
953 assert user.note_count == 0
955 {:ok, user} = User.decrease_note_count(user)
957 assert user.note_count == 0
960 test "it sets the follower_count property" do
962 follower = insert(:user)
964 User.follow(follower, user)
966 assert user.follower_count == 0
968 {:ok, user} = User.update_follower_count(user)
970 assert user.follower_count == 1
975 test "it mutes people" do
977 muted_user = insert(:user)
979 refute User.mutes?(user, muted_user)
980 refute User.muted_notifications?(user, muted_user)
982 {:ok, _user_relationships} = User.mute(user, muted_user)
984 assert User.mutes?(user, muted_user)
985 assert User.muted_notifications?(user, muted_user)
988 test "it unmutes users" do
990 muted_user = insert(:user)
992 {:ok, _user_relationships} = User.mute(user, muted_user)
993 {:ok, _user_mute} = User.unmute(user, muted_user)
995 refute User.mutes?(user, muted_user)
996 refute User.muted_notifications?(user, muted_user)
999 test "it mutes user without notifications" do
1000 user = insert(:user)
1001 muted_user = insert(:user)
1003 refute User.mutes?(user, muted_user)
1004 refute User.muted_notifications?(user, muted_user)
1006 {:ok, _user_relationships} = User.mute(user, muted_user, false)
1008 assert User.mutes?(user, muted_user)
1009 refute User.muted_notifications?(user, muted_user)
1013 describe "blocks" do
1014 test "it blocks people" do
1015 user = insert(:user)
1016 blocked_user = insert(:user)
1018 refute User.blocks?(user, blocked_user)
1020 {:ok, _user_relationship} = User.block(user, blocked_user)
1022 assert User.blocks?(user, blocked_user)
1025 test "it unblocks users" do
1026 user = insert(:user)
1027 blocked_user = insert(:user)
1029 {:ok, _user_relationship} = User.block(user, blocked_user)
1030 {:ok, _user_block} = User.unblock(user, blocked_user)
1032 refute User.blocks?(user, blocked_user)
1035 test "blocks tear down cyclical follow relationships" do
1036 blocker = insert(:user)
1037 blocked = insert(:user)
1039 {:ok, blocker} = User.follow(blocker, blocked)
1040 {:ok, blocked} = User.follow(blocked, blocker)
1042 assert User.following?(blocker, blocked)
1043 assert User.following?(blocked, blocker)
1045 {:ok, _user_relationship} = User.block(blocker, blocked)
1046 blocked = User.get_cached_by_id(blocked.id)
1048 assert User.blocks?(blocker, blocked)
1050 refute User.following?(blocker, blocked)
1051 refute User.following?(blocked, blocker)
1054 test "blocks tear down blocker->blocked follow relationships" do
1055 blocker = insert(:user)
1056 blocked = insert(:user)
1058 {:ok, blocker} = User.follow(blocker, blocked)
1060 assert User.following?(blocker, blocked)
1061 refute User.following?(blocked, blocker)
1063 {:ok, _user_relationship} = User.block(blocker, blocked)
1064 blocked = User.get_cached_by_id(blocked.id)
1066 assert User.blocks?(blocker, blocked)
1068 refute User.following?(blocker, blocked)
1069 refute User.following?(blocked, blocker)
1072 test "blocks tear down blocked->blocker follow relationships" do
1073 blocker = insert(:user)
1074 blocked = insert(:user)
1076 {:ok, blocked} = User.follow(blocked, blocker)
1078 refute User.following?(blocker, blocked)
1079 assert User.following?(blocked, blocker)
1081 {:ok, _user_relationship} = User.block(blocker, blocked)
1082 blocked = User.get_cached_by_id(blocked.id)
1084 assert User.blocks?(blocker, blocked)
1086 refute User.following?(blocker, blocked)
1087 refute User.following?(blocked, blocker)
1090 test "blocks tear down blocked->blocker subscription relationships" do
1091 blocker = insert(:user)
1092 blocked = insert(:user)
1094 {:ok, _subscription} = User.subscribe(blocked, blocker)
1096 assert User.subscribed_to?(blocked, blocker)
1097 refute User.subscribed_to?(blocker, blocked)
1099 {:ok, _user_relationship} = User.block(blocker, blocked)
1101 assert User.blocks?(blocker, blocked)
1102 refute User.subscribed_to?(blocker, blocked)
1103 refute User.subscribed_to?(blocked, blocker)
1107 describe "domain blocking" do
1108 test "blocks domains" do
1109 user = insert(:user)
1110 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1112 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1114 assert User.blocks?(user, collateral_user)
1117 test "does not block domain with same end" do
1118 user = insert(:user)
1121 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1123 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1125 refute User.blocks?(user, collateral_user)
1128 test "does not block domain with same end if wildcard added" do
1129 user = insert(:user)
1132 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1134 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1136 refute User.blocks?(user, collateral_user)
1139 test "blocks domain with wildcard for subdomain" do
1140 user = insert(:user)
1142 user_from_subdomain =
1143 insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
1145 user_with_two_subdomains =
1147 ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
1150 user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1152 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1154 assert User.blocks?(user, user_from_subdomain)
1155 assert User.blocks?(user, user_with_two_subdomains)
1156 assert User.blocks?(user, user_domain)
1159 test "unblocks domains" do
1160 user = insert(:user)
1161 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1163 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1164 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
1166 refute User.blocks?(user, collateral_user)
1169 test "follows take precedence over domain blocks" do
1170 user = insert(:user)
1171 good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
1173 {:ok, user} = User.block_domain(user, "meanies.social")
1174 {:ok, user} = User.follow(user, good_eggo)
1176 refute User.blocks?(user, good_eggo)
1180 describe "get_recipients_from_activity" do
1181 test "works for announces" do
1182 actor = insert(:user)
1183 user = insert(:user, local: true)
1185 {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
1186 {:ok, announce} = CommonAPI.repeat(activity.id, user)
1188 recipients = User.get_recipients_from_activity(announce)
1190 assert user in recipients
1193 test "get recipients" do
1194 actor = insert(:user)
1195 user = insert(:user, local: true)
1196 user_two = insert(:user, local: false)
1197 addressed = insert(:user, local: true)
1198 addressed_remote = insert(:user, local: false)
1201 CommonAPI.post(actor, %{
1202 status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
1205 assert Enum.map([actor, addressed], & &1.ap_id) --
1206 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1208 {:ok, user} = User.follow(user, actor)
1209 {:ok, _user_two} = User.follow(user_two, actor)
1210 recipients = User.get_recipients_from_activity(activity)
1211 assert length(recipients) == 3
1212 assert user in recipients
1213 assert addressed in recipients
1216 test "has following" do
1217 actor = insert(:user)
1218 user = insert(:user)
1219 user_two = insert(:user)
1220 addressed = insert(:user, local: true)
1223 CommonAPI.post(actor, %{
1224 status: "hey @#{addressed.nickname}"
1227 assert Enum.map([actor, addressed], & &1.ap_id) --
1228 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1230 {:ok, _actor} = User.follow(actor, user)
1231 {:ok, _actor} = User.follow(actor, user_two)
1232 recipients = User.get_recipients_from_activity(activity)
1233 assert length(recipients) == 2
1234 assert addressed in recipients
1238 describe ".deactivate" do
1239 test "can de-activate then re-activate a user" do
1240 user = insert(:user)
1241 assert false == user.deactivated
1242 {:ok, user} = User.deactivate(user)
1243 assert true == user.deactivated
1244 {:ok, user} = User.deactivate(user, false)
1245 assert false == user.deactivated
1248 test "hide a user from followers" do
1249 user = insert(:user)
1250 user2 = insert(:user)
1252 {:ok, user} = User.follow(user, user2)
1253 {:ok, _user} = User.deactivate(user)
1255 user2 = User.get_cached_by_id(user2.id)
1257 assert user2.follower_count == 0
1258 assert [] = User.get_followers(user2)
1261 test "hide a user from friends" do
1262 user = insert(:user)
1263 user2 = insert(:user)
1265 {:ok, user2} = User.follow(user2, user)
1266 assert user2.following_count == 1
1267 assert User.following_count(user2) == 1
1269 {:ok, _user} = User.deactivate(user)
1271 user2 = User.get_cached_by_id(user2.id)
1273 assert refresh_record(user2).following_count == 0
1274 assert user2.following_count == 0
1275 assert User.following_count(user2) == 0
1276 assert [] = User.get_friends(user2)
1279 test "hide a user's statuses from timelines and notifications" do
1280 user = insert(:user)
1281 user2 = insert(:user)
1283 {:ok, user2} = User.follow(user2, user)
1285 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
1287 activity = Repo.preload(activity, :bookmark)
1289 [notification] = Pleroma.Notification.for_user(user2)
1290 assert notification.activity.id == activity.id
1292 assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
1294 assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
1295 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1299 {:ok, _user} = User.deactivate(user)
1301 assert [] == ActivityPub.fetch_public_activities(%{})
1302 assert [] == Pleroma.Notification.for_user(user2)
1305 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1311 describe "approve" do
1312 test "approves a user" do
1313 user = insert(:user, approval_pending: true)
1314 assert true == user.approval_pending
1315 {:ok, user} = User.approve(user)
1316 assert false == user.approval_pending
1319 test "approves a list of users" do
1320 unapproved_users = [
1321 insert(:user, approval_pending: true),
1322 insert(:user, approval_pending: true),
1323 insert(:user, approval_pending: true)
1326 {:ok, users} = User.approve(unapproved_users)
1328 assert Enum.count(users) == 3
1330 Enum.each(users, fn user ->
1331 assert false == user.approval_pending
1336 describe "delete" do
1338 {:ok, user} = insert(:user) |> User.set_cache()
1343 setup do: clear_config([:instance, :federating])
1345 test ".delete_user_activities deletes all create activities", %{user: user} do
1346 {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
1348 User.delete_user_activities(user)
1350 # TODO: Test removal favorites, repeats, delete activities.
1351 refute Activity.get_by_id(activity.id)
1354 test "it deactivates a user, all follow relationships and all activities", %{user: user} do
1355 follower = insert(:user)
1356 {:ok, follower} = User.follow(follower, user)
1358 locked_user = insert(:user, name: "locked", locked: true)
1359 {:ok, _} = User.follow(user, locked_user, :follow_pending)
1361 object = insert(:note, user: user)
1362 activity = insert(:note_activity, user: user, note: object)
1364 object_two = insert(:note, user: follower)
1365 activity_two = insert(:note_activity, user: follower, note: object_two)
1367 {:ok, like} = CommonAPI.favorite(user, activity_two.id)
1368 {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
1369 {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
1371 {:ok, job} = User.delete(user)
1372 {:ok, _user} = ObanHelpers.perform(job)
1374 follower = User.get_cached_by_id(follower.id)
1376 refute User.following?(follower, user)
1377 assert %{deactivated: true} = User.get_by_id(user.id)
1379 assert [] == User.get_follow_requests(locked_user)
1383 |> Activity.Queries.by_actor()
1385 |> Enum.map(fn act -> act.data["type"] end)
1387 assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
1389 refute Activity.get_by_id(activity.id)
1390 refute Activity.get_by_id(like.id)
1391 refute Activity.get_by_id(like_two.id)
1392 refute Activity.get_by_id(repeat.id)
1396 describe "delete/1 when confirmation is pending" do
1398 user = insert(:user, confirmation_pending: true)
1402 test "deletes user from database when activation required", %{user: user} do
1403 clear_config([:instance, :account_activation_required], true)
1405 {:ok, job} = User.delete(user)
1406 {:ok, _} = ObanHelpers.perform(job)
1408 refute User.get_cached_by_id(user.id)
1409 refute User.get_by_id(user.id)
1412 test "deactivates user when activation is not required", %{user: user} do
1413 clear_config([:instance, :account_activation_required], false)
1415 {:ok, job} = User.delete(user)
1416 {:ok, _} = ObanHelpers.perform(job)
1418 assert %{deactivated: true} = User.get_cached_by_id(user.id)
1419 assert %{deactivated: true} = User.get_by_id(user.id)
1423 test "delete/1 when approval is pending deletes the user" do
1424 user = insert(:user, approval_pending: true)
1426 {:ok, job} = User.delete(user)
1427 {:ok, _} = ObanHelpers.perform(job)
1429 refute User.get_cached_by_id(user.id)
1430 refute User.get_by_id(user.id)
1433 test "delete/1 purges a user when they wouldn't be fully deleted" do
1438 password_hash: "pdfk2$1b3n159001",
1439 keys: "RSA begin buplic key",
1440 public_key: "--PRIVATE KEYE--",
1441 avatar: %{"a" => "b"},
1443 banner: %{"a" => "b"},
1444 background: %{"a" => "b"},
1447 following_count: 9001,
1449 confirmation_pending: true,
1450 password_reset_pending: true,
1451 approval_pending: true,
1452 registration_reason: "ahhhhh",
1453 confirmation_token: "qqqq",
1454 domain_blocks: ["lain.com"],
1459 mastofe_settings: %{"a" => "b"},
1460 mascot: %{"a" => "b"},
1461 emoji: %{"a" => "b"},
1462 pleroma_settings_store: %{"q" => "x"},
1463 fields: [%{"gg" => "qq"}],
1464 raw_fields: [%{"gg" => "qq"}],
1466 also_known_as: ["https://lol.olo/users/loll"]
1469 {:ok, job} = User.delete(user)
1470 {:ok, _} = ObanHelpers.perform(job)
1471 user = User.get_by_id(user.id)
1483 last_refreshed_at: nil,
1484 last_digest_emailed_at: nil,
1491 confirmation_pending: false,
1492 password_reset_pending: false,
1493 approval_pending: false,
1494 registration_reason: nil,
1495 confirmation_token: nil,
1499 is_moderator: false,
1501 mastofe_settings: nil,
1504 pleroma_settings_store: %{},
1507 discoverable: false,
1512 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1513 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1516 describe "per-user rich-text filtering" do
1517 test "html_filter_policy returns default policies, when rich-text is enabled" do
1518 user = insert(:user)
1520 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1523 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1524 user = insert(:user, no_rich_text: true)
1526 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1530 describe "caching" do
1531 test "invalidate_cache works" do
1532 user = insert(:user)
1534 User.set_cache(user)
1535 User.invalidate_cache(user)
1537 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1538 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1541 test "User.delete() plugs any possible zombie objects" do
1542 user = insert(:user)
1544 {:ok, job} = User.delete(user)
1545 {:ok, _} = ObanHelpers.perform(job)
1547 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1549 assert cached_user != user
1551 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1553 assert cached_user != user
1557 describe "account_status/1" do
1558 setup do: clear_config([:instance, :account_activation_required])
1560 test "return confirmation_pending for unconfirm user" do
1561 Pleroma.Config.put([:instance, :account_activation_required], true)
1562 user = insert(:user, confirmation_pending: true)
1563 assert User.account_status(user) == :confirmation_pending
1566 test "return active for confirmed user" do
1567 Pleroma.Config.put([:instance, :account_activation_required], true)
1568 user = insert(:user, confirmation_pending: false)
1569 assert User.account_status(user) == :active
1572 test "return active for remote user" do
1573 user = insert(:user, local: false)
1574 assert User.account_status(user) == :active
1577 test "returns :password_reset_pending for user with reset password" do
1578 user = insert(:user, password_reset_pending: true)
1579 assert User.account_status(user) == :password_reset_pending
1582 test "returns :deactivated for deactivated user" do
1583 user = insert(:user, local: true, confirmation_pending: false, deactivated: true)
1584 assert User.account_status(user) == :deactivated
1587 test "returns :approval_pending for unapproved user" do
1588 user = insert(:user, local: true, approval_pending: true)
1589 assert User.account_status(user) == :approval_pending
1591 user = insert(:user, local: true, confirmation_pending: true, approval_pending: true)
1592 assert User.account_status(user) == :approval_pending
1596 describe "superuser?/1" do
1597 test "returns false for unprivileged users" do
1598 user = insert(:user, local: true)
1600 refute User.superuser?(user)
1603 test "returns false for remote users" do
1604 user = insert(:user, local: false)
1605 remote_admin_user = insert(:user, local: false, is_admin: true)
1607 refute User.superuser?(user)
1608 refute User.superuser?(remote_admin_user)
1611 test "returns true for local moderators" do
1612 user = insert(:user, local: true, is_moderator: true)
1614 assert User.superuser?(user)
1617 test "returns true for local admins" do
1618 user = insert(:user, local: true, is_admin: true)
1620 assert User.superuser?(user)
1624 describe "invisible?/1" do
1625 test "returns true for an invisible user" do
1626 user = insert(:user, local: true, invisible: true)
1628 assert User.invisible?(user)
1631 test "returns false for a non-invisible user" do
1632 user = insert(:user, local: true)
1634 refute User.invisible?(user)
1638 describe "visible_for/2" do
1639 test "returns true when the account is itself" do
1640 user = insert(:user, local: true)
1642 assert User.visible_for(user, user) == :visible
1645 test "returns false when the account is unconfirmed and confirmation is required" do
1646 Pleroma.Config.put([:instance, :account_activation_required], true)
1648 user = insert(:user, local: true, confirmation_pending: true)
1649 other_user = insert(:user, local: true)
1651 refute User.visible_for(user, other_user) == :visible
1654 test "returns true when the account is unconfirmed and confirmation is required but the account is remote" do
1655 Pleroma.Config.put([:instance, :account_activation_required], true)
1657 user = insert(:user, local: false, confirmation_pending: true)
1658 other_user = insert(:user, local: true)
1660 assert User.visible_for(user, other_user) == :visible
1663 test "returns true when the account is unconfirmed and confirmation is not required" do
1664 user = insert(:user, local: true, confirmation_pending: true)
1665 other_user = insert(:user, local: true)
1667 assert User.visible_for(user, other_user) == :visible
1670 test "returns true when the account is unconfirmed and being viewed by a privileged account (confirmation required)" do
1671 Pleroma.Config.put([:instance, :account_activation_required], true)
1673 user = insert(:user, local: true, confirmation_pending: true)
1674 other_user = insert(:user, local: true, is_admin: true)
1676 assert User.visible_for(user, other_user) == :visible
1680 describe "parse_bio/2" do
1681 test "preserves hosts in user links text" do
1682 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1683 user = insert(:user)
1684 bio = "A.k.a. @nick@domain.com"
1687 ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
1689 }" rel="ugc">@<span>nick@domain.com</span></a></span>)
1691 assert expected_text == User.parse_bio(bio, user)
1694 test "Adds rel=me on linkbacked urls" do
1695 user = insert(:user, ap_id: "https://social.example.org/users/lain")
1697 bio = "http://example.com/rel_me/null"
1698 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1699 assert expected_text == User.parse_bio(bio, user)
1701 bio = "http://example.com/rel_me/link"
1702 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1703 assert expected_text == User.parse_bio(bio, user)
1705 bio = "http://example.com/rel_me/anchor"
1706 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1707 assert expected_text == User.parse_bio(bio, user)
1711 test "follower count is updated when a follower is blocked" do
1712 user = insert(:user)
1713 follower = insert(:user)
1714 follower2 = insert(:user)
1715 follower3 = insert(:user)
1717 {:ok, follower} = User.follow(follower, user)
1718 {:ok, _follower2} = User.follow(follower2, user)
1719 {:ok, _follower3} = User.follow(follower3, user)
1721 {:ok, _user_relationship} = User.block(user, follower)
1722 user = refresh_record(user)
1724 assert user.follower_count == 2
1727 describe "list_inactive_users_query/1" do
1728 defp days_ago(days) do
1730 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
1731 -days * 60 * 60 * 24,
1736 test "Users are inactive by default" do
1740 Enum.map(1..total, fn _ ->
1741 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1744 inactive_users_ids =
1745 Pleroma.User.list_inactive_users_query()
1746 |> Pleroma.Repo.all()
1747 |> Enum.map(& &1.id)
1749 Enum.each(users, fn user ->
1750 assert user.id in inactive_users_ids
1754 test "Only includes users who has no recent activity" do
1758 Enum.map(1..total, fn _ ->
1759 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1762 {inactive, active} = Enum.split(users, trunc(total / 2))
1764 Enum.map(active, fn user ->
1765 to = Enum.random(users -- [user])
1768 CommonAPI.post(user, %{
1769 status: "hey @#{to.nickname}"
1773 inactive_users_ids =
1774 Pleroma.User.list_inactive_users_query()
1775 |> Pleroma.Repo.all()
1776 |> Enum.map(& &1.id)
1778 Enum.each(active, fn user ->
1779 refute user.id in inactive_users_ids
1782 Enum.each(inactive, fn user ->
1783 assert user.id in inactive_users_ids
1787 test "Only includes users with no read notifications" do
1791 Enum.map(1..total, fn _ ->
1792 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1795 [sender | recipients] = users
1796 {inactive, active} = Enum.split(recipients, trunc(total / 2))
1798 Enum.each(recipients, fn to ->
1800 CommonAPI.post(sender, %{
1801 status: "hey @#{to.nickname}"
1805 CommonAPI.post(sender, %{
1806 status: "hey again @#{to.nickname}"
1810 Enum.each(active, fn user ->
1811 [n1, _n2] = Pleroma.Notification.for_user(user)
1812 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
1815 inactive_users_ids =
1816 Pleroma.User.list_inactive_users_query()
1817 |> Pleroma.Repo.all()
1818 |> Enum.map(& &1.id)
1820 Enum.each(active, fn user ->
1821 refute user.id in inactive_users_ids
1824 Enum.each(inactive, fn user ->
1825 assert user.id in inactive_users_ids
1830 describe "toggle_confirmation/1" do
1831 test "if user is confirmed" do
1832 user = insert(:user, confirmation_pending: false)
1833 {:ok, user} = User.toggle_confirmation(user)
1835 assert user.confirmation_pending
1836 assert user.confirmation_token
1839 test "if user is unconfirmed" do
1840 user = insert(:user, confirmation_pending: true, confirmation_token: "some token")
1841 {:ok, user} = User.toggle_confirmation(user)
1843 refute user.confirmation_pending
1844 refute user.confirmation_token
1848 describe "ensure_keys_present" do
1849 test "it creates keys for a user and stores them in info" do
1850 user = insert(:user)
1851 refute is_binary(user.keys)
1852 {:ok, user} = User.ensure_keys_present(user)
1853 assert is_binary(user.keys)
1856 test "it doesn't create keys if there already are some" do
1857 user = insert(:user, keys: "xxx")
1858 {:ok, user} = User.ensure_keys_present(user)
1859 assert user.keys == "xxx"
1863 describe "get_ap_ids_by_nicknames" do
1864 test "it returns a list of AP ids for a given set of nicknames" do
1865 user = insert(:user)
1866 user_two = insert(:user)
1868 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
1869 assert length(ap_ids) == 2
1870 assert user.ap_id in ap_ids
1871 assert user_two.ap_id in ap_ids
1875 describe "sync followers count" do
1877 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
1878 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
1879 insert(:user, local: true)
1880 insert(:user, local: false, deactivated: true)
1881 {:ok, user1: user1, user2: user2}
1884 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
1885 [fdb_user1] = User.external_users(limit: 1)
1887 assert fdb_user1.ap_id
1888 assert fdb_user1.ap_id == user1.ap_id
1889 assert fdb_user1.id == user1.id
1891 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
1893 assert fdb_user2.ap_id
1894 assert fdb_user2.ap_id == user2.ap_id
1895 assert fdb_user2.id == user2.id
1897 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
1901 describe "is_internal_user?/1" do
1902 test "non-internal user returns false" do
1903 user = insert(:user)
1904 refute User.is_internal_user?(user)
1907 test "user with no nickname returns true" do
1908 user = insert(:user, %{nickname: nil})
1909 assert User.is_internal_user?(user)
1912 test "user with internal-prefixed nickname returns true" do
1913 user = insert(:user, %{nickname: "internal.test"})
1914 assert User.is_internal_user?(user)
1918 describe "update_and_set_cache/1" do
1919 test "returns error when user is stale instead Ecto.StaleEntryError" do
1920 user = insert(:user)
1922 changeset = Ecto.Changeset.change(user, bio: "test")
1926 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
1927 User.update_and_set_cache(changeset)
1930 test "performs update cache if user updated" do
1931 user = insert(:user)
1932 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1934 changeset = Ecto.Changeset.change(user, bio: "test-bio")
1936 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
1937 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1938 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
1942 describe "following/followers synchronization" do
1943 setup do: clear_config([:instance, :external_user_synchronization])
1945 test "updates the counters normally on following/getting a follow when disabled" do
1946 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1947 user = insert(:user)
1952 follower_address: "http://localhost:4001/users/masto_closed/followers",
1953 following_address: "http://localhost:4001/users/masto_closed/following",
1957 assert other_user.following_count == 0
1958 assert other_user.follower_count == 0
1960 {:ok, user} = Pleroma.User.follow(user, other_user)
1961 other_user = Pleroma.User.get_by_id(other_user.id)
1963 assert user.following_count == 1
1964 assert other_user.follower_count == 1
1967 test "syncronizes the counters with the remote instance for the followed when enabled" do
1968 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1970 user = insert(:user)
1975 follower_address: "http://localhost:4001/users/masto_closed/followers",
1976 following_address: "http://localhost:4001/users/masto_closed/following",
1980 assert other_user.following_count == 0
1981 assert other_user.follower_count == 0
1983 Pleroma.Config.put([:instance, :external_user_synchronization], true)
1984 {:ok, _user} = User.follow(user, other_user)
1985 other_user = User.get_by_id(other_user.id)
1987 assert other_user.follower_count == 437
1990 test "syncronizes the counters with the remote instance for the follower when enabled" do
1991 Pleroma.Config.put([:instance, :external_user_synchronization], false)
1993 user = insert(:user)
1998 follower_address: "http://localhost:4001/users/masto_closed/followers",
1999 following_address: "http://localhost:4001/users/masto_closed/following",
2003 assert other_user.following_count == 0
2004 assert other_user.follower_count == 0
2006 Pleroma.Config.put([:instance, :external_user_synchronization], true)
2007 {:ok, other_user} = User.follow(other_user, user)
2009 assert other_user.following_count == 152
2013 describe "change_email/2" do
2015 [user: insert(:user)]
2018 test "blank email returns error", %{user: user} do
2019 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
2020 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
2023 test "non unique email returns error", %{user: user} do
2024 %{email: email} = insert(:user)
2026 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
2027 User.change_email(user, email)
2030 test "invalid email returns error", %{user: user} do
2031 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
2032 User.change_email(user, "cofe")
2035 test "changes email", %{user: user} do
2036 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
2040 describe "get_cached_by_nickname_or_id" do
2042 local_user = insert(:user)
2043 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
2045 [local_user: local_user, remote_user: remote_user]
2048 setup do: clear_config([:instance, :limit_to_local_content])
2050 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
2051 remote_user: remote_user
2053 Pleroma.Config.put([:instance, :limit_to_local_content], false)
2054 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2056 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2057 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2059 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2060 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2063 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
2064 %{remote_user: remote_user} do
2065 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2066 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2069 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
2070 %{remote_user: remote_user, local_user: local_user} do
2071 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2072 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
2075 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
2076 %{remote_user: remote_user} do
2077 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2078 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2081 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
2082 %{local_user: local_user} do
2083 Pleroma.Config.put([:instance, :limit_to_local_content], false)
2084 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2086 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2087 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2089 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2090 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2094 describe "update_email_notifications/2" do
2096 user = insert(:user, email_notifications: %{"digest" => true})
2101 test "Notifications are updated", %{user: user} do
2102 true = user.email_notifications["digest"]
2103 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
2104 assert result.email_notifications["digest"] == false
2108 test "avatar fallback" do
2109 user = insert(:user)
2110 assert User.avatar_url(user) =~ "/images/avi.png"
2112 clear_config([:assets, :default_user_avatar], "avatar.png")
2114 user = User.get_cached_by_nickname_or_id(user.nickname)
2115 assert User.avatar_url(user) =~ "avatar.png"
2117 assert User.avatar_url(user, no_default: true) == nil