1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.UserTest do
7 alias Pleroma.Builders.UserBuilder
8 alias Pleroma.Notification
11 alias Pleroma.Tests.ObanHelpers
13 alias Pleroma.Web.ActivityPub.ActivityPub
14 alias Pleroma.Web.CommonAPI
17 use Oban.Testing, repo: Pleroma.Repo
19 import Pleroma.Factory
20 import ExUnit.CaptureLog
21 import Swoosh.TestAssertions
24 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
28 setup do: clear_config([:instance, :account_activation_required])
30 describe "service actors" do
31 test "returns updated invisible actor" do
32 uri = "#{Pleroma.Web.Endpoint.url()}/relay"
33 followers_uri = "#{uri}/followers"
42 follower_address: followers_uri
46 actor = User.get_or_create_service_actor_by_ap_id(uri, "relay")
47 assert actor.invisible
50 test "returns relay user" do
51 uri = "#{Pleroma.Web.Endpoint.url()}/relay"
52 followers_uri = "#{uri}/followers"
59 follower_address: ^followers_uri
60 } = User.get_or_create_service_actor_by_ap_id(uri, "relay")
62 assert capture_log(fn ->
63 refute User.get_or_create_service_actor_by_ap_id("/relay", "relay")
64 end) =~ "Cannot create service actor:"
67 test "returns invisible actor" do
68 uri = "#{Pleroma.Web.Endpoint.url()}/internal/fetch-test"
69 followers_uri = "#{uri}/followers"
70 user = User.get_or_create_service_actor_by_ap_id(uri, "internal.fetch-test")
73 nickname: "internal.fetch-test",
77 follower_address: ^followers_uri
80 user2 = User.get_or_create_service_actor_by_ap_id(uri, "internal.fetch-test")
81 assert user.id == user2.id
85 describe "AP ID user relationships" do
87 {:ok, user: insert(:user)}
90 test "outgoing_relationships_ap_ids/1", %{user: user} do
91 rel_types = [:block, :mute, :notification_mute, :reblog_mute, :inverse_subscription]
99 insert_list(2, :user_relationship, %{source: user, relationship_type: rel_type})
101 ap_ids = Enum.map(rel_records, fn rr -> Repo.preload(rr, :target).target.ap_id end)
102 {rel_type, Enum.sort(ap_ids)}
106 assert ap_ids_by_rel[:block] == Enum.sort(User.blocked_users_ap_ids(user))
107 assert ap_ids_by_rel[:block] == Enum.sort(Enum.map(User.blocked_users(user), & &1.ap_id))
109 assert ap_ids_by_rel[:mute] == Enum.sort(User.muted_users_ap_ids(user))
110 assert ap_ids_by_rel[:mute] == Enum.sort(Enum.map(User.muted_users(user), & &1.ap_id))
112 assert ap_ids_by_rel[:notification_mute] ==
113 Enum.sort(User.notification_muted_users_ap_ids(user))
115 assert ap_ids_by_rel[:notification_mute] ==
116 Enum.sort(Enum.map(User.notification_muted_users(user), & &1.ap_id))
118 assert ap_ids_by_rel[:reblog_mute] == Enum.sort(User.reblog_muted_users_ap_ids(user))
120 assert ap_ids_by_rel[:reblog_mute] ==
121 Enum.sort(Enum.map(User.reblog_muted_users(user), & &1.ap_id))
123 assert ap_ids_by_rel[:inverse_subscription] == Enum.sort(User.subscriber_users_ap_ids(user))
125 assert ap_ids_by_rel[:inverse_subscription] ==
126 Enum.sort(Enum.map(User.subscriber_users(user), & &1.ap_id))
128 outgoing_relationships_ap_ids = User.outgoing_relationships_ap_ids(user, rel_types)
130 assert ap_ids_by_rel ==
131 Enum.into(outgoing_relationships_ap_ids, %{}, fn {k, v} -> {k, Enum.sort(v)} end)
135 describe "when tags are nil" do
136 test "tagging a user" do
137 user = insert(:user, %{tags: nil})
138 user = User.tag(user, ["cool", "dude"])
140 assert "cool" in user.tags
141 assert "dude" in user.tags
144 test "untagging a user" do
145 user = insert(:user, %{tags: nil})
146 user = User.untag(user, ["cool", "dude"])
148 assert user.tags == []
152 test "ap_id returns the activity pub id for the user" do
153 user = UserBuilder.build()
155 expected_ap_id = "#{Pleroma.Web.Endpoint.url()}/users/#{user.nickname}"
157 assert expected_ap_id == User.ap_id(user)
160 test "ap_followers returns the followers collection for the user" do
161 user = UserBuilder.build()
163 expected_followers_collection = "#{User.ap_id(user)}/followers"
165 assert expected_followers_collection == User.ap_followers(user)
168 test "ap_following returns the following collection for the user" do
169 user = UserBuilder.build()
171 expected_followers_collection = "#{User.ap_id(user)}/following"
173 assert expected_followers_collection == User.ap_following(user)
176 test "returns all pending follow requests" do
177 unlocked = insert(:user)
178 locked = insert(:user, is_locked: true)
179 follower = insert(:user)
181 CommonAPI.follow(follower, unlocked)
182 CommonAPI.follow(follower, locked)
184 assert [] = User.get_follow_requests(unlocked)
185 assert [activity] = User.get_follow_requests(locked)
190 test "doesn't return already accepted or duplicate follow requests" do
191 locked = insert(:user, is_locked: true)
192 pending_follower = insert(:user)
193 accepted_follower = insert(:user)
195 CommonAPI.follow(pending_follower, locked)
196 CommonAPI.follow(pending_follower, locked)
197 CommonAPI.follow(accepted_follower, locked)
199 Pleroma.FollowingRelationship.update(accepted_follower, locked, :follow_accept)
201 assert [^pending_follower] = User.get_follow_requests(locked)
204 test "doesn't return follow requests for deactivated accounts" do
205 locked = insert(:user, is_locked: true)
206 pending_follower = insert(:user, %{is_active: false})
208 CommonAPI.follow(pending_follower, locked)
210 refute pending_follower.is_active
211 assert [] = User.get_follow_requests(locked)
214 test "clears follow requests when requester is blocked" do
215 followed = insert(:user, is_locked: true)
216 follower = insert(:user)
218 CommonAPI.follow(follower, followed)
219 assert [_activity] = User.get_follow_requests(followed)
221 {:ok, _user_relationship} = User.block(followed, follower)
222 assert [] = User.get_follow_requests(followed)
225 test "follow_all follows mutliple users" do
227 followed_zero = insert(:user)
228 followed_one = insert(:user)
229 followed_two = insert(:user)
230 blocked = insert(:user)
231 not_followed = insert(:user)
232 reverse_blocked = insert(:user)
234 {:ok, _user_relationship} = User.block(user, blocked)
235 {:ok, _user_relationship} = User.block(reverse_blocked, user)
237 {:ok, user, followed_zero} = User.follow(user, followed_zero)
239 {:ok, user} = User.follow_all(user, [followed_one, followed_two, blocked, reverse_blocked])
241 assert User.following?(user, followed_one)
242 assert User.following?(user, followed_two)
243 assert User.following?(user, followed_zero)
244 refute User.following?(user, not_followed)
245 refute User.following?(user, blocked)
246 refute User.following?(user, reverse_blocked)
249 test "follow_all follows mutliple users without duplicating" do
251 followed_zero = insert(:user)
252 followed_one = insert(:user)
253 followed_two = insert(:user)
255 {:ok, user} = User.follow_all(user, [followed_zero, followed_one])
256 assert length(User.following(user)) == 3
258 {:ok, user} = User.follow_all(user, [followed_one, followed_two])
259 assert length(User.following(user)) == 4
262 test "follow takes a user and another user" do
264 followed = insert(:user)
266 {:ok, user, followed} = User.follow(user, followed)
268 user = User.get_cached_by_id(user.id)
269 followed = User.get_cached_by_ap_id(followed.ap_id)
271 assert followed.follower_count == 1
272 assert user.following_count == 1
274 assert User.ap_followers(followed) in User.following(user)
277 test "can't follow a deactivated users" do
279 followed = insert(:user, %{is_active: false})
281 {:error, _} = User.follow(user, followed)
284 test "can't follow a user who blocked us" do
285 blocker = insert(:user)
286 blockee = insert(:user)
288 {:ok, _user_relationship} = User.block(blocker, blockee)
290 {:error, _} = User.follow(blockee, blocker)
293 test "can't subscribe to a user who blocked us" do
294 blocker = insert(:user)
295 blocked = insert(:user)
297 {:ok, _user_relationship} = User.block(blocker, blocked)
299 {:error, _} = User.subscribe(blocked, blocker)
302 test "local users do not automatically follow local locked accounts" do
303 follower = insert(:user, is_locked: true)
304 followed = insert(:user, is_locked: true)
306 {:ok, follower, followed} = User.maybe_direct_follow(follower, followed)
308 refute User.following?(follower, followed)
311 describe "unfollow/2" do
312 setup do: clear_config([:instance, :external_user_synchronization])
314 test "unfollow with syncronizes external user" do
315 clear_config([:instance, :external_user_synchronization], true)
320 follower_address: "http://localhost:4001/users/fuser1/followers",
321 following_address: "http://localhost:4001/users/fuser1/following",
322 ap_id: "http://localhost:4001/users/fuser1"
329 ap_id: "http://localhost:4001/users/fuser2",
330 follower_address: "http://localhost:4001/users/fuser2/followers",
331 following_address: "http://localhost:4001/users/fuser2/following"
334 {:ok, user, followed} = User.follow(user, followed, :follow_accept)
336 {:ok, user, _activity} = User.unfollow(user, followed)
338 user = User.get_cached_by_id(user.id)
340 assert User.following(user) == []
343 test "unfollow takes a user and another user" do
344 followed = insert(:user)
347 {:ok, user, followed} = User.follow(user, followed, :follow_accept)
349 assert User.following(user) == [user.follower_address, followed.follower_address]
351 {:ok, user, _activity} = User.unfollow(user, followed)
353 assert User.following(user) == [user.follower_address]
356 test "unfollow doesn't unfollow yourself" do
359 {:error, _} = User.unfollow(user, user)
361 assert User.following(user) == [user.follower_address]
365 test "test if a user is following another user" do
366 followed = insert(:user)
368 User.follow(user, followed, :follow_accept)
370 assert User.following?(user, followed)
371 refute User.following?(followed, user)
374 test "fetches correct profile for nickname beginning with number" do
375 # Use old-style integer ID to try to reproduce the problem
376 user = insert(:user, %{id: 1080})
377 user_with_numbers = insert(:user, %{nickname: "#{user.id}garbage"})
378 assert user_with_numbers == User.get_cached_by_nickname_or_id(user_with_numbers.nickname)
381 describe "user registration" do
387 password_confirmation: "test",
388 email: "email@example.com"
391 setup do: clear_config([:instance, :autofollowed_nicknames])
392 setup do: clear_config([:instance, :autofollowing_nicknames])
393 setup do: clear_config([:welcome])
394 setup do: clear_config([:instance, :account_activation_required])
396 test "it autofollows accounts that are set for it" do
398 remote_user = insert(:user, %{local: false})
400 clear_config([:instance, :autofollowed_nicknames], [
405 cng = User.register_changeset(%User{}, @full_user_data)
407 {:ok, registered_user} = User.register(cng)
409 assert User.following?(registered_user, user)
410 refute User.following?(registered_user, remote_user)
413 test "it adds automatic followers for new registered accounts" do
414 user1 = insert(:user)
415 user2 = insert(:user)
417 clear_config([:instance, :autofollowing_nicknames], [
422 cng = User.register_changeset(%User{}, @full_user_data)
424 {:ok, registered_user} = User.register(cng)
426 assert User.following?(user1, registered_user)
427 assert User.following?(user2, registered_user)
430 test "it sends a welcome message if it is set" do
431 welcome_user = insert(:user)
432 clear_config([:welcome, :direct_message, :enabled], true)
433 clear_config([:welcome, :direct_message, :sender_nickname], welcome_user.nickname)
434 clear_config([:welcome, :direct_message, :message], "Hello, this is a direct message")
436 cng = User.register_changeset(%User{}, @full_user_data)
437 {:ok, registered_user} = User.register(cng)
438 ObanHelpers.perform_all()
440 activity = Repo.one(Pleroma.Activity)
441 assert registered_user.ap_id in activity.recipients
442 assert Object.normalize(activity, fetch: false).data["content"] =~ "direct message"
443 assert activity.actor == welcome_user.ap_id
447 clear_config(:mrf_simple,
450 federated_timeline_removal: [],
463 Pleroma.Web.ActivityPub.MRF.SimplePolicy
467 test "it sends a welcome email message if it is set" do
468 welcome_user = insert(:user)
469 clear_config([:welcome, :email, :enabled], true)
470 clear_config([:welcome, :email, :sender], welcome_user.email)
473 [:welcome, :email, :subject],
474 "Hello, welcome to cool site: <%= instance_name %>"
477 instance_name = Pleroma.Config.get([:instance, :name])
479 cng = User.register_changeset(%User{}, @full_user_data)
480 {:ok, registered_user} = User.register(cng)
481 ObanHelpers.perform_all()
484 from: {instance_name, welcome_user.email},
485 to: {registered_user.name, registered_user.email},
486 subject: "Hello, welcome to cool site: #{instance_name}",
487 html_body: "Welcome to #{instance_name}"
491 test "it sends a confirm email" do
492 clear_config([:instance, :account_activation_required], true)
494 cng = User.register_changeset(%User{}, @full_user_data)
495 {:ok, registered_user} = User.register(cng)
496 ObanHelpers.perform_all()
498 Pleroma.Emails.UserEmail.account_confirmation_email(registered_user)
499 # temporary hackney fix until hackney max_connections bug is fixed
500 # https://git.pleroma.social/pleroma/pleroma/-/issues/2101
501 |> Swoosh.Email.put_private(:hackney_options, ssl_options: [versions: [:"tlsv1.2"]])
502 |> assert_email_sent()
505 test "sends a pending approval email" do
506 clear_config([:instance, :account_approval_required], true)
509 User.register_changeset(%User{}, @full_user_data)
512 ObanHelpers.perform_all()
515 from: Pleroma.Config.Helpers.sender(),
516 to: {user.name, user.email},
517 subject: "Your account is awaiting approval"
521 test "it sends a registration confirmed email if no others will be sent" do
522 clear_config([:welcome, :email, :enabled], false)
523 clear_config([:instance, :account_activation_required], false)
524 clear_config([:instance, :account_approval_required], false)
527 User.register_changeset(%User{}, @full_user_data)
530 ObanHelpers.perform_all()
532 instance_name = Pleroma.Config.get([:instance, :name])
533 sender = Pleroma.Config.get([:instance, :notify_email])
536 from: {instance_name, sender},
537 to: {user.name, user.email},
538 subject: "Account registered on #{instance_name}"
542 test "it fails gracefully with invalid email config" do
543 cng = User.register_changeset(%User{}, @full_user_data)
545 # Disable the mailer but enable all the things that want to send emails
546 clear_config([Pleroma.Emails.Mailer, :enabled], false)
547 clear_config([:instance, :account_activation_required], true)
548 clear_config([:instance, :account_approval_required], true)
549 clear_config([:welcome, :email, :enabled], true)
550 clear_config([:welcome, :email, :sender], "lain@lain.com")
552 # The user is still created
553 assert {:ok, %User{nickname: "nick"}} = User.register(cng)
556 ObanHelpers.perform_all()
560 test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do
561 clear_config([:instance, :account_activation_required], true)
565 |> Enum.each(fn key ->
566 params = Map.delete(@full_user_data, key)
567 changeset = User.register_changeset(%User{}, params)
569 assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
573 test "it requires an name, nickname and password, bio and email are optional when account_activation_required is disabled" do
574 clear_config([:instance, :account_activation_required], false)
578 |> Enum.each(fn key ->
579 params = Map.delete(@full_user_data, key)
580 changeset = User.register_changeset(%User{}, params)
582 assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid?
586 test "it restricts certain nicknames" do
587 [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
589 assert is_bitstring(restricted_name)
593 |> Map.put(:nickname, restricted_name)
595 changeset = User.register_changeset(%User{}, params)
597 refute changeset.valid?
600 test "it blocks blacklisted email domains" do
601 clear_config([User, :email_blacklist], ["trolling.world"])
604 params = Map.put(@full_user_data, :email, "troll@trolling.world")
605 changeset = User.register_changeset(%User{}, params)
606 refute changeset.valid?
608 # Block with subdomain match
609 params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world")
610 changeset = User.register_changeset(%User{}, params)
611 refute changeset.valid?
613 # Pass with different domains that are similar
614 params = Map.put(@full_user_data, :email, "troll@gnomestrolling.world")
615 changeset = User.register_changeset(%User{}, params)
616 assert changeset.valid?
618 params = Map.put(@full_user_data, :email, "troll@trolling.world.us")
619 changeset = User.register_changeset(%User{}, params)
620 assert changeset.valid?
623 test "it sets the password_hash, ap_id, private key and followers collection address" do
624 changeset = User.register_changeset(%User{}, @full_user_data)
626 assert changeset.valid?
628 assert is_binary(changeset.changes[:password_hash])
629 assert is_binary(changeset.changes[:keys])
630 assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
631 assert is_binary(changeset.changes[:keys])
632 assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
635 test "it creates a confirmed user" do
636 changeset = User.register_changeset(%User{}, @full_user_data)
637 assert changeset.valid?
639 {:ok, user} = Repo.insert(changeset)
641 assert user.is_confirmed
645 describe "user registration, with :account_activation_required" do
651 password_confirmation: "test",
652 email: "email@example.com"
654 setup do: clear_config([:instance, :account_activation_required], true)
656 test "it creates unconfirmed user" do
657 changeset = User.register_changeset(%User{}, @full_user_data)
658 assert changeset.valid?
660 {:ok, user} = Repo.insert(changeset)
662 refute user.is_confirmed
663 assert user.confirmation_token
666 test "it creates confirmed user if :confirmed option is given" do
667 changeset = User.register_changeset(%User{}, @full_user_data, confirmed: true)
668 assert changeset.valid?
670 {:ok, user} = Repo.insert(changeset)
672 assert user.is_confirmed
673 refute user.confirmation_token
677 describe "user registration, with :account_approval_required" do
683 password_confirmation: "test",
684 email: "email@example.com",
685 registration_reason: "I'm a cool guy :)"
687 setup do: clear_config([:instance, :account_approval_required], true)
689 test "it creates unapproved user" do
690 changeset = User.register_changeset(%User{}, @full_user_data)
691 assert changeset.valid?
693 {:ok, user} = Repo.insert(changeset)
695 refute user.is_approved
696 assert user.registration_reason == "I'm a cool guy :)"
699 test "it restricts length of registration reason" do
700 reason_limit = Pleroma.Config.get([:instance, :registration_reason_length])
702 assert is_integer(reason_limit)
707 :registration_reason,
708 "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."
711 changeset = User.register_changeset(%User{}, params)
713 refute changeset.valid?
717 describe "get_or_fetch/1" do
718 test "gets an existing user by nickname" do
720 {:ok, fetched_user} = User.get_or_fetch(user.nickname)
722 assert user == fetched_user
725 test "gets an existing user by ap_id" do
726 ap_id = "http://mastodon.example.org/users/admin"
732 nickname: "admin@mastodon.example.org",
736 {:ok, fetched_user} = User.get_or_fetch(ap_id)
737 freshed_user = refresh_record(user)
738 assert freshed_user == fetched_user
741 test "gets an existing user by nickname starting with http" do
742 user = insert(:user, nickname: "httpssome")
743 {:ok, fetched_user} = User.get_or_fetch("httpssome")
745 assert user == fetched_user
749 describe "get_or_fetch/1 remote users with tld, while BE is runned on subdomain" do
750 setup do: clear_config([Pleroma.Web.WebFinger, :update_nickname_on_user_fetch], true)
752 test "for mastodon" do
754 %{url: "https://example.com/.well-known/host-meta"} ->
757 headers: [{"location", "https://sub.example.com/.well-known/host-meta"}]
760 %{url: "https://sub.example.com/.well-known/host-meta"} ->
764 "test/fixtures/webfinger/masto-host-meta.xml"
766 |> String.replace("{{domain}}", "sub.example.com")
769 %{url: "https://sub.example.com/.well-known/webfinger?resource=acct:a@example.com"} ->
773 "test/fixtures/webfinger/masto-webfinger.json"
775 |> String.replace("{{nickname}}", "a")
776 |> String.replace("{{domain}}", "example.com")
777 |> String.replace("{{subdomain}}", "sub.example.com"),
778 headers: [{"content-type", "application/jrd+json"}]
781 %{url: "https://sub.example.com/users/a"} ->
785 "test/fixtures/webfinger/masto-user.json"
787 |> String.replace("{{nickname}}", "a")
788 |> String.replace("{{domain}}", "sub.example.com"),
789 headers: [{"content-type", "application/activity+json"}]
792 %{url: "https://sub.example.com/users/a/collections/featured"} ->
796 File.read!("test/fixtures/users_mock/masto_featured.json")
797 |> String.replace("{{domain}}", "sub.example.com")
798 |> String.replace("{{nickname}}", "a"),
799 headers: [{"content-type", "application/activity+json"}]
803 ap_id = "a@example.com"
804 {:ok, fetched_user} = User.get_or_fetch(ap_id)
806 assert fetched_user.ap_id == "https://sub.example.com/users/a"
807 assert fetched_user.nickname == "a@example.com"
810 test "for pleroma" do
812 %{url: "https://example.com/.well-known/host-meta"} ->
815 headers: [{"location", "https://sub.example.com/.well-known/host-meta"}]
818 %{url: "https://sub.example.com/.well-known/host-meta"} ->
822 "test/fixtures/webfinger/pleroma-host-meta.xml"
824 |> String.replace("{{domain}}", "sub.example.com")
827 %{url: "https://sub.example.com/.well-known/webfinger?resource=acct:a@example.com"} ->
831 "test/fixtures/webfinger/pleroma-webfinger.json"
833 |> String.replace("{{nickname}}", "a")
834 |> String.replace("{{domain}}", "example.com")
835 |> String.replace("{{subdomain}}", "sub.example.com"),
836 headers: [{"content-type", "application/jrd+json"}]
839 %{url: "https://sub.example.com/users/a"} ->
843 "test/fixtures/webfinger/pleroma-user.json"
845 |> String.replace("{{nickname}}", "a")
846 |> String.replace("{{domain}}", "sub.example.com"),
847 headers: [{"content-type", "application/activity+json"}]
851 ap_id = "a@example.com"
852 {:ok, fetched_user} = User.get_or_fetch(ap_id)
854 assert fetched_user.ap_id == "https://sub.example.com/users/a"
855 assert fetched_user.nickname == "a@example.com"
859 describe "fetching a user from nickname or trying to build one" do
860 test "gets an existing user" do
862 {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
864 assert user == fetched_user
867 test "gets an existing user, case insensitive" do
868 user = insert(:user, nickname: "nick")
869 {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
871 assert user == fetched_user
874 test "gets an existing user by fully qualified nickname" do
877 {:ok, fetched_user} =
878 User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
880 assert user == fetched_user
883 test "gets an existing user by fully qualified nickname, case insensitive" do
884 user = insert(:user, nickname: "nick")
885 casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
887 {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
889 assert user == fetched_user
892 @tag capture_log: true
893 test "returns nil if no user could be fetched" do
894 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
895 assert fetched_user == "not found nonexistant@social.heldscal.la"
898 test "returns nil for nonexistant local user" do
899 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
900 assert fetched_user == "not found nonexistant"
903 test "updates an existing user, if stale" do
904 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
910 nickname: "admin@mastodon.example.org",
911 ap_id: "http://mastodon.example.org/users/admin",
912 last_refreshed_at: a_week_ago
915 assert orig_user.last_refreshed_at == a_week_ago
917 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
921 refute user.last_refreshed_at == orig_user.last_refreshed_at
924 test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
925 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
931 nickname: "admin@mastodon.example.org",
932 ap_id: "http://mastodon.example.org/users/harinezumigari",
933 last_refreshed_at: a_week_ago
936 assert orig_user.last_refreshed_at == a_week_ago
938 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
942 refute user.id == orig_user.id
944 orig_user = User.get_by_id(orig_user.id)
946 assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
949 @tag capture_log: true
950 test "it returns the old user if stale, but unfetchable" do
951 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
957 nickname: "admin@mastodon.example.org",
958 ap_id: "http://mastodon.example.org/users/raymoo",
959 last_refreshed_at: a_week_ago
962 assert orig_user.last_refreshed_at == a_week_ago
964 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/raymoo")
966 assert user.last_refreshed_at == orig_user.last_refreshed_at
970 test "returns an ap_id for a user" do
973 assert User.ap_id(user) ==
974 Pleroma.Web.Router.Helpers.user_feed_url(
975 Pleroma.Web.Endpoint,
981 test "returns an ap_followers link for a user" do
984 assert User.ap_followers(user) ==
985 Pleroma.Web.Router.Helpers.user_feed_url(
986 Pleroma.Web.Endpoint,
992 describe "remote user changeset" do
998 avatar: %{some: "avatar"}
1000 setup do: clear_config([:instance, :user_bio_length])
1001 setup do: clear_config([:instance, :user_name_length])
1003 test "it confirms validity" do
1004 cs = User.remote_user_changeset(@valid_remote)
1008 test "it sets the follower_adress" do
1009 cs = User.remote_user_changeset(@valid_remote)
1010 # remote users get a fake local follower address
1011 assert cs.changes.follower_address ==
1012 User.ap_followers(%User{nickname: @valid_remote[:nickname]})
1015 test "it enforces the fqn format for nicknames" do
1016 cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})
1017 assert Ecto.Changeset.get_field(cs, :local) == false
1018 assert cs.changes.avatar
1022 test "it has required fields" do
1024 |> Enum.each(fn field ->
1025 cs = User.remote_user_changeset(Map.delete(@valid_remote, field))
1030 test "it is invalid given a local user" do
1031 user = insert(:user)
1032 cs = User.remote_user_changeset(user, %{name: "tom from myspace"})
1038 describe "followers and friends" do
1039 test "gets all followers for a given user" do
1040 user = insert(:user)
1041 follower_one = insert(:user)
1042 follower_two = insert(:user)
1043 not_follower = insert(:user)
1045 {:ok, follower_one, user} = User.follow(follower_one, user)
1046 {:ok, follower_two, user} = User.follow(follower_two, user)
1048 res = User.get_followers(user)
1050 assert Enum.member?(res, follower_one)
1051 assert Enum.member?(res, follower_two)
1052 refute Enum.member?(res, not_follower)
1055 test "gets all friends (followed users) for a given user" do
1056 user = insert(:user)
1057 followed_one = insert(:user)
1058 followed_two = insert(:user)
1059 not_followed = insert(:user)
1061 {:ok, user, followed_one} = User.follow(user, followed_one)
1062 {:ok, user, followed_two} = User.follow(user, followed_two)
1064 res = User.get_friends(user)
1066 followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
1067 followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
1068 assert Enum.member?(res, followed_one)
1069 assert Enum.member?(res, followed_two)
1070 refute Enum.member?(res, not_followed)
1074 describe "updating note and follower count" do
1075 test "it sets the note_count property" do
1076 note = insert(:note)
1078 user = User.get_cached_by_ap_id(note.data["actor"])
1080 assert user.note_count == 0
1082 {:ok, user} = User.update_note_count(user)
1084 assert user.note_count == 1
1087 test "it increases the note_count property" do
1088 note = insert(:note)
1089 user = User.get_cached_by_ap_id(note.data["actor"])
1091 assert user.note_count == 0
1093 {:ok, user} = User.increase_note_count(user)
1095 assert user.note_count == 1
1097 {:ok, user} = User.increase_note_count(user)
1099 assert user.note_count == 2
1102 test "it decreases the note_count property" do
1103 note = insert(:note)
1104 user = User.get_cached_by_ap_id(note.data["actor"])
1106 assert user.note_count == 0
1108 {:ok, user} = User.increase_note_count(user)
1110 assert user.note_count == 1
1112 {:ok, user} = User.decrease_note_count(user)
1114 assert user.note_count == 0
1116 {:ok, user} = User.decrease_note_count(user)
1118 assert user.note_count == 0
1121 test "it sets the follower_count property" do
1122 user = insert(:user)
1123 follower = insert(:user)
1125 User.follow(follower, user)
1127 assert user.follower_count == 0
1129 {:ok, user} = User.update_follower_count(user)
1131 assert user.follower_count == 1
1136 test "it mutes people" do
1137 user = insert(:user)
1138 muted_user = insert(:user)
1140 refute User.mutes?(user, muted_user)
1141 refute User.muted_notifications?(user, muted_user)
1143 {:ok, _user_relationships} = User.mute(user, muted_user)
1145 assert User.mutes?(user, muted_user)
1146 assert User.muted_notifications?(user, muted_user)
1150 user = insert(:user)
1151 muted_user = insert(:user)
1153 {:ok, _user_relationships} = User.mute(user, muted_user, %{expires_in: 60})
1154 assert User.mutes?(user, muted_user)
1156 worker = Pleroma.Workers.MuteExpireWorker
1157 args = %{"op" => "unmute_user", "muter_id" => user.id, "mutee_id" => muted_user.id}
1164 assert :ok = perform_job(worker, args)
1166 refute User.mutes?(user, muted_user)
1167 refute User.muted_notifications?(user, muted_user)
1170 test "it unmutes users" do
1171 user = insert(:user)
1172 muted_user = insert(:user)
1174 {:ok, _user_relationships} = User.mute(user, muted_user)
1175 {:ok, _user_mute} = User.unmute(user, muted_user)
1177 refute User.mutes?(user, muted_user)
1178 refute User.muted_notifications?(user, muted_user)
1181 test "it unmutes users by id" do
1182 user = insert(:user)
1183 muted_user = insert(:user)
1185 {:ok, _user_relationships} = User.mute(user, muted_user)
1186 {:ok, _user_mute} = User.unmute(user.id, muted_user.id)
1188 refute User.mutes?(user, muted_user)
1189 refute User.muted_notifications?(user, muted_user)
1192 test "it mutes user without notifications" do
1193 user = insert(:user)
1194 muted_user = insert(:user)
1196 refute User.mutes?(user, muted_user)
1197 refute User.muted_notifications?(user, muted_user)
1199 {:ok, _user_relationships} = User.mute(user, muted_user, %{notifications: false})
1201 assert User.mutes?(user, muted_user)
1202 refute User.muted_notifications?(user, muted_user)
1206 describe "blocks" do
1207 test "it blocks people" do
1208 user = insert(:user)
1209 blocked_user = insert(:user)
1211 refute User.blocks?(user, blocked_user)
1213 {:ok, _user_relationship} = User.block(user, blocked_user)
1215 assert User.blocks?(user, blocked_user)
1218 test "it unblocks users" do
1219 user = insert(:user)
1220 blocked_user = insert(:user)
1222 {:ok, _user_relationship} = User.block(user, blocked_user)
1223 {:ok, _user_block} = User.unblock(user, blocked_user)
1225 refute User.blocks?(user, blocked_user)
1228 test "blocks tear down cyclical follow relationships" do
1229 blocker = insert(:user)
1230 blocked = insert(:user)
1232 {:ok, blocker, blocked} = User.follow(blocker, blocked)
1233 {:ok, blocked, blocker} = User.follow(blocked, blocker)
1235 assert User.following?(blocker, blocked)
1236 assert User.following?(blocked, blocker)
1238 {:ok, _user_relationship} = User.block(blocker, blocked)
1239 blocked = User.get_cached_by_id(blocked.id)
1241 assert User.blocks?(blocker, blocked)
1243 refute User.following?(blocker, blocked)
1244 refute User.following?(blocked, blocker)
1247 test "blocks tear down blocker->blocked follow relationships" do
1248 blocker = insert(:user)
1249 blocked = insert(:user)
1251 {:ok, blocker, blocked} = User.follow(blocker, blocked)
1253 assert User.following?(blocker, blocked)
1254 refute User.following?(blocked, blocker)
1256 {:ok, _user_relationship} = User.block(blocker, blocked)
1257 blocked = User.get_cached_by_id(blocked.id)
1259 assert User.blocks?(blocker, blocked)
1261 refute User.following?(blocker, blocked)
1262 refute User.following?(blocked, blocker)
1265 test "blocks tear down blocked->blocker follow relationships" do
1266 blocker = insert(:user)
1267 blocked = insert(:user)
1269 {:ok, blocked, blocker} = User.follow(blocked, blocker)
1271 refute User.following?(blocker, blocked)
1272 assert User.following?(blocked, blocker)
1274 {:ok, _user_relationship} = User.block(blocker, blocked)
1275 blocked = User.get_cached_by_id(blocked.id)
1277 assert User.blocks?(blocker, blocked)
1279 refute User.following?(blocker, blocked)
1280 refute User.following?(blocked, blocker)
1283 test "blocks tear down blocked->blocker subscription relationships" do
1284 blocker = insert(:user)
1285 blocked = insert(:user)
1287 {:ok, _subscription} = User.subscribe(blocked, blocker)
1289 assert User.subscribed_to?(blocked, blocker)
1290 refute User.subscribed_to?(blocker, blocked)
1292 {:ok, _user_relationship} = User.block(blocker, blocked)
1294 assert User.blocks?(blocker, blocked)
1295 refute User.subscribed_to?(blocker, blocked)
1296 refute User.subscribed_to?(blocked, blocker)
1300 describe "domain blocking" do
1301 test "blocks domains" do
1302 user = insert(:user)
1303 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1305 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1307 assert User.blocks?(user, collateral_user)
1310 test "does not block domain with same end" do
1311 user = insert(:user)
1314 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1316 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1318 refute User.blocks?(user, collateral_user)
1321 test "does not block domain with same end if wildcard added" do
1322 user = insert(:user)
1325 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1327 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1329 refute User.blocks?(user, collateral_user)
1332 test "blocks domain with wildcard for subdomain" do
1333 user = insert(:user)
1335 user_from_subdomain =
1336 insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
1338 user_with_two_subdomains =
1340 ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
1343 user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1345 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1347 assert User.blocks?(user, user_from_subdomain)
1348 assert User.blocks?(user, user_with_two_subdomains)
1349 assert User.blocks?(user, user_domain)
1352 test "unblocks domains" do
1353 user = insert(:user)
1354 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1356 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1357 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
1359 refute User.blocks?(user, collateral_user)
1362 test "follows take precedence over domain blocks" do
1363 user = insert(:user)
1364 good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
1366 {:ok, user} = User.block_domain(user, "meanies.social")
1367 {:ok, user, good_eggo} = User.follow(user, good_eggo)
1369 refute User.blocks?(user, good_eggo)
1373 describe "get_recipients_from_activity" do
1374 test "works for announces" do
1375 actor = insert(:user)
1376 user = insert(:user, local: true)
1378 {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
1379 {:ok, announce} = CommonAPI.repeat(activity.id, user)
1381 recipients = User.get_recipients_from_activity(announce)
1383 assert user in recipients
1386 test "get recipients" do
1387 actor = insert(:user)
1388 user = insert(:user, local: true)
1389 user_two = insert(:user, local: false)
1390 addressed = insert(:user, local: true)
1391 addressed_remote = insert(:user, local: false)
1394 CommonAPI.post(actor, %{
1395 status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
1398 assert Enum.map([actor, addressed], & &1.ap_id) --
1399 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1401 {:ok, user, actor} = User.follow(user, actor)
1402 {:ok, _user_two, _actor} = User.follow(user_two, actor)
1403 recipients = User.get_recipients_from_activity(activity)
1404 assert length(recipients) == 3
1405 assert user in recipients
1406 assert addressed in recipients
1409 test "has following" do
1410 actor = insert(:user)
1411 user = insert(:user)
1412 user_two = insert(:user)
1413 addressed = insert(:user, local: true)
1416 CommonAPI.post(actor, %{
1417 status: "hey @#{addressed.nickname}"
1420 assert Enum.map([actor, addressed], & &1.ap_id) --
1421 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1423 {:ok, _actor, _user} = User.follow(actor, user)
1424 {:ok, _actor, _user_two} = User.follow(actor, user_two)
1425 recipients = User.get_recipients_from_activity(activity)
1426 assert length(recipients) == 2
1427 assert addressed in recipients
1431 describe ".set_activation" do
1432 test "can de-activate then re-activate a user" do
1433 user = insert(:user)
1434 assert user.is_active
1435 {:ok, user} = User.set_activation(user, false)
1436 refute user.is_active
1437 {:ok, user} = User.set_activation(user, true)
1438 assert user.is_active
1441 test "hide a user from followers" do
1442 user = insert(:user)
1443 user2 = insert(:user)
1445 {:ok, user, user2} = User.follow(user, user2)
1446 {:ok, _user} = User.set_activation(user, false)
1448 user2 = User.get_cached_by_id(user2.id)
1450 assert user2.follower_count == 0
1451 assert [] = User.get_followers(user2)
1454 test "hide a user from friends" do
1455 user = insert(:user)
1456 user2 = insert(:user)
1458 {:ok, user2, user} = User.follow(user2, user)
1459 assert user2.following_count == 1
1460 assert User.following_count(user2) == 1
1462 {:ok, _user} = User.set_activation(user, false)
1464 user2 = User.get_cached_by_id(user2.id)
1466 assert refresh_record(user2).following_count == 0
1467 assert user2.following_count == 0
1468 assert User.following_count(user2) == 0
1469 assert [] = User.get_friends(user2)
1472 test "hide a user's statuses from timelines and notifications" do
1473 user = insert(:user)
1474 user2 = insert(:user)
1476 {:ok, user2, user} = User.follow(user2, user)
1478 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
1480 activity = Repo.preload(activity, :bookmark)
1482 [notification] = Pleroma.Notification.for_user(user2)
1483 assert notification.activity.id == activity.id
1485 assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
1487 assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
1488 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1492 {:ok, _user} = User.set_activation(user, false)
1494 assert [] == ActivityPub.fetch_public_activities(%{})
1495 assert [] == Pleroma.Notification.for_user(user2)
1498 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1504 describe "approve" do
1505 test "approves a user" do
1506 user = insert(:user, is_approved: false)
1507 refute user.is_approved
1508 {:ok, user} = User.approve(user)
1509 assert user.is_approved
1512 test "approves a list of users" do
1513 unapproved_users = [
1514 insert(:user, is_approved: false),
1515 insert(:user, is_approved: false),
1516 insert(:user, is_approved: false)
1519 {:ok, users} = User.approve(unapproved_users)
1521 assert Enum.count(users) == 3
1523 Enum.each(users, fn user ->
1524 assert user.is_approved
1528 test "it sends welcome email if it is set" do
1529 clear_config([:welcome, :email, :enabled], true)
1530 clear_config([:welcome, :email, :sender], "tester@test.me")
1532 user = insert(:user, is_approved: false)
1533 welcome_user = insert(:user, email: "tester@test.me")
1534 instance_name = Pleroma.Config.get([:instance, :name])
1538 ObanHelpers.perform_all()
1541 from: {instance_name, welcome_user.email},
1542 to: {user.name, user.email},
1543 html_body: "Welcome to #{instance_name}"
1547 test "approving an approved user does not trigger post-register actions" do
1548 clear_config([:welcome, :email, :enabled], true)
1550 user = insert(:user, is_approved: true)
1553 ObanHelpers.perform_all()
1555 assert_no_email_sent()
1559 describe "confirm" do
1560 test "confirms a user" do
1561 user = insert(:user, is_confirmed: false)
1562 refute user.is_confirmed
1563 {:ok, user} = User.confirm(user)
1564 assert user.is_confirmed
1567 test "confirms a list of users" do
1568 unconfirmed_users = [
1569 insert(:user, is_confirmed: false),
1570 insert(:user, is_confirmed: false),
1571 insert(:user, is_confirmed: false)
1574 {:ok, users} = User.confirm(unconfirmed_users)
1576 assert Enum.count(users) == 3
1578 Enum.each(users, fn user ->
1579 assert user.is_confirmed
1583 test "sends approval emails when `is_approved: false`" do
1584 admin = insert(:user, is_admin: true)
1585 user = insert(:user, is_confirmed: false, is_approved: false)
1588 ObanHelpers.perform_all()
1590 user_email = Pleroma.Emails.UserEmail.approval_pending_email(user)
1591 admin_email = Pleroma.Emails.AdminEmail.new_unapproved_registration(admin, user)
1593 notify_email = Pleroma.Config.get([:instance, :notify_email])
1594 instance_name = Pleroma.Config.get([:instance, :name])
1596 # User approval email
1598 from: {instance_name, notify_email},
1599 to: {user.name, user.email},
1600 html_body: user_email.html_body
1605 from: {instance_name, notify_email},
1606 to: {admin.name, admin.email},
1607 html_body: admin_email.html_body
1611 test "confirming a confirmed user does not trigger post-register actions" do
1612 user = insert(:user, is_confirmed: true, is_approved: false)
1615 ObanHelpers.perform_all()
1617 assert_no_email_sent()
1621 describe "delete" do
1623 {:ok, user} = insert(:user) |> User.set_cache()
1628 setup do: clear_config([:instance, :federating])
1630 test ".delete_user_activities deletes all create activities", %{user: user} do
1631 {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
1633 User.delete_user_activities(user)
1635 # TODO: Test removal favorites, repeats, delete activities.
1636 refute Activity.get_by_id(activity.id)
1639 test "it deactivates a user, all follow relationships and all activities", %{user: user} do
1640 follower = insert(:user)
1641 {:ok, follower, user} = User.follow(follower, user)
1643 locked_user = insert(:user, name: "locked", is_locked: true)
1644 {:ok, _, _} = User.follow(user, locked_user, :follow_pending)
1646 object = insert(:note, user: user)
1647 activity = insert(:note_activity, user: user, note: object)
1649 object_two = insert(:note, user: follower)
1650 activity_two = insert(:note_activity, user: follower, note: object_two)
1652 {:ok, like} = CommonAPI.favorite(user, activity_two.id)
1653 {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
1654 {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
1656 {:ok, job} = User.delete(user)
1657 {:ok, _user} = ObanHelpers.perform(job)
1659 follower = User.get_cached_by_id(follower.id)
1661 refute User.following?(follower, user)
1662 assert %{is_active: false} = User.get_by_id(user.id)
1664 assert [] == User.get_follow_requests(locked_user)
1668 |> Activity.Queries.by_actor()
1670 |> Enum.map(fn act -> act.data["type"] end)
1672 assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
1674 refute Activity.get_by_id(activity.id)
1675 refute Activity.get_by_id(like.id)
1676 refute Activity.get_by_id(like_two.id)
1677 refute Activity.get_by_id(repeat.id)
1681 test "delete/1 when confirmation is pending deletes the user" do
1682 clear_config([:instance, :account_activation_required], true)
1683 user = insert(:user, is_confirmed: false)
1685 {:ok, job} = User.delete(user)
1686 {:ok, _} = ObanHelpers.perform(job)
1688 refute User.get_cached_by_id(user.id)
1689 refute User.get_by_id(user.id)
1692 test "delete/1 when approval is pending deletes the user" do
1693 user = insert(:user, is_approved: false)
1695 {:ok, job} = User.delete(user)
1696 {:ok, _} = ObanHelpers.perform(job)
1698 refute User.get_cached_by_id(user.id)
1699 refute User.get_by_id(user.id)
1702 test "delete/1 purges a user when they wouldn't be fully deleted" do
1707 password_hash: "pdfk2$1b3n159001",
1708 keys: "RSA begin buplic key",
1709 public_key: "--PRIVATE KEYE--",
1710 avatar: %{"a" => "b"},
1712 banner: %{"a" => "b"},
1713 background: %{"a" => "b"},
1716 following_count: 9001,
1719 password_reset_pending: true,
1721 registration_reason: "ahhhhh",
1722 confirmation_token: "qqqq",
1723 domain_blocks: ["lain.com"],
1728 mastofe_settings: %{"a" => "b"},
1729 mascot: %{"a" => "b"},
1730 emoji: %{"a" => "b"},
1731 pleroma_settings_store: %{"q" => "x"},
1732 fields: [%{"gg" => "qq"}],
1733 raw_fields: [%{"gg" => "qq"}],
1734 is_discoverable: true,
1735 also_known_as: ["https://lol.olo/users/loll"]
1738 {:ok, job} = User.delete(user)
1739 {:ok, _} = ObanHelpers.perform(job)
1740 user = User.get_by_id(user.id)
1748 keys: "RSA begin buplic key",
1749 public_key: "--PRIVATE KEYE--",
1752 last_refreshed_at: nil,
1753 last_digest_emailed_at: nil,
1761 password_reset_pending: false,
1763 registration_reason: nil,
1764 confirmation_token: nil,
1768 is_moderator: false,
1770 mastofe_settings: nil,
1773 pleroma_settings_store: %{},
1776 is_discoverable: false,
1781 test "delete/1 purges a remote user" do
1785 avatar: %{"a" => "b"},
1786 banner: %{"a" => "b"},
1790 {:ok, job} = User.delete(user)
1791 {:ok, _} = ObanHelpers.perform(job)
1792 user = User.get_by_id(user.id)
1794 assert user.name == nil
1795 assert user.avatar == %{}
1796 assert user.banner == %{}
1799 describe "set_suggestion" do
1800 test "suggests a user" do
1801 user = insert(:user, is_suggested: false)
1802 refute user.is_suggested
1803 {:ok, user} = User.set_suggestion(user, true)
1804 assert user.is_suggested
1807 test "suggests a list of users" do
1808 unsuggested_users = [
1809 insert(:user, is_suggested: false),
1810 insert(:user, is_suggested: false),
1811 insert(:user, is_suggested: false)
1814 {:ok, users} = User.set_suggestion(unsuggested_users, true)
1816 assert Enum.count(users) == 3
1818 Enum.each(users, fn user ->
1819 assert user.is_suggested
1823 test "unsuggests a user" do
1824 user = insert(:user, is_suggested: true)
1825 assert user.is_suggested
1826 {:ok, user} = User.set_suggestion(user, false)
1827 refute user.is_suggested
1831 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1832 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1835 describe "per-user rich-text filtering" do
1836 test "html_filter_policy returns default policies, when rich-text is enabled" do
1837 user = insert(:user)
1839 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1842 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1843 user = insert(:user, no_rich_text: true)
1845 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1849 describe "caching" do
1850 test "invalidate_cache works" do
1851 user = insert(:user)
1853 User.set_cache(user)
1854 User.invalidate_cache(user)
1856 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1857 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1860 test "User.delete() plugs any possible zombie objects" do
1861 user = insert(:user)
1863 {:ok, job} = User.delete(user)
1864 {:ok, _} = ObanHelpers.perform(job)
1866 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1868 assert cached_user != user
1870 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1872 assert cached_user != user
1876 describe "account_status/1" do
1877 setup do: clear_config([:instance, :account_activation_required])
1879 test "return confirmation_pending for unconfirm user" do
1880 clear_config([:instance, :account_activation_required], true)
1881 user = insert(:user, is_confirmed: false)
1882 assert User.account_status(user) == :confirmation_pending
1885 test "return active for confirmed user" do
1886 clear_config([:instance, :account_activation_required], true)
1887 user = insert(:user, is_confirmed: true)
1888 assert User.account_status(user) == :active
1891 test "return active for remote user" do
1892 user = insert(:user, local: false)
1893 assert User.account_status(user) == :active
1896 test "returns :password_reset_pending for user with reset password" do
1897 user = insert(:user, password_reset_pending: true)
1898 assert User.account_status(user) == :password_reset_pending
1901 test "returns :deactivated for deactivated user" do
1902 user = insert(:user, local: true, is_confirmed: true, is_active: false)
1903 assert User.account_status(user) == :deactivated
1906 test "returns :approval_pending for unapproved user" do
1907 user = insert(:user, local: true, is_approved: false)
1908 assert User.account_status(user) == :approval_pending
1910 user = insert(:user, local: true, is_confirmed: false, is_approved: false)
1911 assert User.account_status(user) == :approval_pending
1915 describe "superuser?/1" do
1916 test "returns false for unprivileged users" do
1917 user = insert(:user, local: true)
1919 refute User.superuser?(user)
1922 test "returns false for remote users" do
1923 user = insert(:user, local: false)
1924 remote_admin_user = insert(:user, local: false, is_admin: true)
1926 refute User.superuser?(user)
1927 refute User.superuser?(remote_admin_user)
1930 test "returns true for local moderators" do
1931 user = insert(:user, local: true, is_moderator: true)
1933 assert User.superuser?(user)
1936 test "returns true for local admins" do
1937 user = insert(:user, local: true, is_admin: true)
1939 assert User.superuser?(user)
1943 describe "invisible?/1" do
1944 test "returns true for an invisible user" do
1945 user = insert(:user, local: true, invisible: true)
1947 assert User.invisible?(user)
1950 test "returns false for a non-invisible user" do
1951 user = insert(:user, local: true)
1953 refute User.invisible?(user)
1957 describe "visible_for/2" do
1958 test "returns true when the account is itself" do
1959 user = insert(:user, local: true)
1961 assert User.visible_for(user, user) == :visible
1964 test "returns false when the account is unconfirmed and confirmation is required" do
1965 clear_config([:instance, :account_activation_required], true)
1967 user = insert(:user, local: true, is_confirmed: false)
1968 other_user = insert(:user, local: true)
1970 refute User.visible_for(user, other_user) == :visible
1973 test "returns true when the account is unconfirmed and confirmation is required but the account is remote" do
1974 clear_config([:instance, :account_activation_required], true)
1976 user = insert(:user, local: false, is_confirmed: false)
1977 other_user = insert(:user, local: true)
1979 assert User.visible_for(user, other_user) == :visible
1982 test "returns true when the account is unconfirmed and being viewed by a privileged account (confirmation required)" do
1983 clear_config([:instance, :account_activation_required], true)
1985 user = insert(:user, local: true, is_confirmed: false)
1986 other_user = insert(:user, local: true, is_admin: true)
1988 assert User.visible_for(user, other_user) == :visible
1992 describe "parse_bio/2" do
1993 test "preserves hosts in user links text" do
1994 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1995 user = insert(:user)
1996 bio = "A.k.a. @nick@domain.com"
1999 ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{remote_user.ap_id}" rel="ugc">@<span>nick@domain.com</span></a></span>)
2001 assert expected_text == User.parse_bio(bio, user)
2004 test "Adds rel=me on linkbacked urls" do
2005 user = insert(:user, ap_id: "https://social.example.org/users/lain")
2007 bio = "http://example.com/rel_me/null"
2008 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
2009 assert expected_text == User.parse_bio(bio, user)
2011 bio = "http://example.com/rel_me/link"
2012 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
2013 assert expected_text == User.parse_bio(bio, user)
2015 bio = "http://example.com/rel_me/anchor"
2016 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
2017 assert expected_text == User.parse_bio(bio, user)
2021 test "follower count is updated when a follower is blocked" do
2022 user = insert(:user)
2023 follower = insert(:user)
2024 follower2 = insert(:user)
2025 follower3 = insert(:user)
2027 {:ok, follower, user} = User.follow(follower, user)
2028 {:ok, _follower2, _user} = User.follow(follower2, user)
2029 {:ok, _follower3, _user} = User.follow(follower3, user)
2031 {:ok, _user_relationship} = User.block(user, follower)
2032 user = refresh_record(user)
2034 assert user.follower_count == 2
2037 describe "list_inactive_users_query/1" do
2038 defp days_ago(days) do
2040 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
2041 -days * 60 * 60 * 24,
2046 test "Users are inactive by default" do
2050 Enum.map(1..total, fn _ ->
2051 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
2054 inactive_users_ids =
2055 Pleroma.User.list_inactive_users_query()
2056 |> Pleroma.Repo.all()
2057 |> Enum.map(& &1.id)
2059 Enum.each(users, fn user ->
2060 assert user.id in inactive_users_ids
2064 test "Only includes users who has no recent activity" do
2068 Enum.map(1..total, fn _ ->
2069 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
2072 {inactive, active} = Enum.split(users, trunc(total / 2))
2074 Enum.map(active, fn user ->
2075 to = Enum.random(users -- [user])
2078 CommonAPI.post(user, %{
2079 status: "hey @#{to.nickname}"
2083 inactive_users_ids =
2084 Pleroma.User.list_inactive_users_query()
2085 |> Pleroma.Repo.all()
2086 |> Enum.map(& &1.id)
2088 Enum.each(active, fn user ->
2089 refute user.id in inactive_users_ids
2092 Enum.each(inactive, fn user ->
2093 assert user.id in inactive_users_ids
2097 test "Only includes users with no read notifications" do
2101 Enum.map(1..total, fn _ ->
2102 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
2105 [sender | recipients] = users
2106 {inactive, active} = Enum.split(recipients, trunc(total / 2))
2108 Enum.each(recipients, fn to ->
2110 CommonAPI.post(sender, %{
2111 status: "hey @#{to.nickname}"
2115 CommonAPI.post(sender, %{
2116 status: "hey again @#{to.nickname}"
2120 Enum.each(active, fn user ->
2121 [n1, _n2] = Pleroma.Notification.for_user(user)
2122 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
2125 inactive_users_ids =
2126 Pleroma.User.list_inactive_users_query()
2127 |> Pleroma.Repo.all()
2128 |> Enum.map(& &1.id)
2130 Enum.each(active, fn user ->
2131 refute user.id in inactive_users_ids
2134 Enum.each(inactive, fn user ->
2135 assert user.id in inactive_users_ids
2140 describe "get_ap_ids_by_nicknames" do
2141 test "it returns a list of AP ids for a given set of nicknames" do
2142 user = insert(:user)
2143 user_two = insert(:user)
2145 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
2146 assert length(ap_ids) == 2
2147 assert user.ap_id in ap_ids
2148 assert user_two.ap_id in ap_ids
2152 describe "sync followers count" do
2154 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
2155 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
2156 insert(:user, local: true)
2157 insert(:user, local: false, is_active: false)
2158 {:ok, user1: user1, user2: user2}
2161 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
2162 [fdb_user1] = User.external_users(limit: 1)
2164 assert fdb_user1.ap_id
2165 assert fdb_user1.ap_id == user1.ap_id
2166 assert fdb_user1.id == user1.id
2168 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
2170 assert fdb_user2.ap_id
2171 assert fdb_user2.ap_id == user2.ap_id
2172 assert fdb_user2.id == user2.id
2174 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
2178 describe "is_internal_user?/1" do
2179 test "non-internal user returns false" do
2180 user = insert(:user)
2181 refute User.is_internal_user?(user)
2184 test "user with no nickname returns true" do
2185 user = insert(:user, %{nickname: nil})
2186 assert User.is_internal_user?(user)
2189 test "user with internal-prefixed nickname returns true" do
2190 user = insert(:user, %{nickname: "internal.test"})
2191 assert User.is_internal_user?(user)
2195 describe "update_and_set_cache/1" do
2196 test "returns error when user is stale instead Ecto.StaleEntryError" do
2197 user = insert(:user)
2199 changeset = Ecto.Changeset.change(user, bio: "test")
2203 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
2204 User.update_and_set_cache(changeset)
2207 test "performs update cache if user updated" do
2208 user = insert(:user)
2209 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
2211 changeset = Ecto.Changeset.change(user, bio: "test-bio")
2213 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
2214 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
2215 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
2218 test "removes report notifs when user isn't superuser any more" do
2219 report_activity = insert(:report_activity)
2220 user = insert(:user, is_moderator: true, is_admin: true)
2221 {:ok, _} = Notification.create_notifications(report_activity)
2223 assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
2225 {:ok, user} = user |> User.admin_api_update(%{is_moderator: false})
2226 # is still superuser because still admin
2227 assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
2229 {:ok, user} = user |> User.admin_api_update(%{is_moderator: true, is_admin: false})
2230 # is still superuser because still moderator
2231 assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
2233 {:ok, user} = user |> User.admin_api_update(%{is_moderator: false})
2234 # is not a superuser any more
2235 assert [] = Notification.for_user(user)
2239 describe "following/followers synchronization" do
2240 setup do: clear_config([:instance, :external_user_synchronization])
2242 test "updates the counters normally on following/getting a follow when disabled" do
2243 clear_config([:instance, :external_user_synchronization], false)
2244 user = insert(:user)
2249 follower_address: "http://localhost:4001/users/masto_closed/followers",
2250 following_address: "http://localhost:4001/users/masto_closed/following",
2254 assert other_user.following_count == 0
2255 assert other_user.follower_count == 0
2257 {:ok, user, other_user} = Pleroma.User.follow(user, other_user)
2259 assert user.following_count == 1
2260 assert other_user.follower_count == 1
2263 test "syncronizes the counters with the remote instance for the followed when enabled" do
2264 clear_config([:instance, :external_user_synchronization], false)
2266 user = insert(:user)
2271 follower_address: "http://localhost:4001/users/masto_closed/followers",
2272 following_address: "http://localhost:4001/users/masto_closed/following",
2276 assert other_user.following_count == 0
2277 assert other_user.follower_count == 0
2279 clear_config([:instance, :external_user_synchronization], true)
2280 {:ok, _user, other_user} = User.follow(user, other_user)
2282 assert other_user.follower_count == 437
2285 test "syncronizes the counters with the remote instance for the follower when enabled" do
2286 clear_config([:instance, :external_user_synchronization], false)
2288 user = insert(:user)
2293 follower_address: "http://localhost:4001/users/masto_closed/followers",
2294 following_address: "http://localhost:4001/users/masto_closed/following",
2298 assert other_user.following_count == 0
2299 assert other_user.follower_count == 0
2301 clear_config([:instance, :external_user_synchronization], true)
2302 {:ok, other_user, _user} = User.follow(other_user, user)
2304 assert other_user.following_count == 152
2308 describe "change_email/2" do
2310 [user: insert(:user)]
2313 test "blank email returns error if we require an email on registration", %{user: user} do
2314 orig_account_activation_required =
2315 Pleroma.Config.get([:instance, :account_activation_required])
2317 Pleroma.Config.put([:instance, :account_activation_required], true)
2321 [:instance, :account_activation_required],
2322 orig_account_activation_required
2326 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
2327 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
2330 test "blank email should be fine if we do not require an email on registration", %{user: user} do
2331 orig_account_activation_required =
2332 Pleroma.Config.get([:instance, :account_activation_required])
2334 Pleroma.Config.put([:instance, :account_activation_required], false)
2338 [:instance, :account_activation_required],
2339 orig_account_activation_required
2343 assert {:ok, %User{email: nil}} = User.change_email(user, "")
2344 assert {:ok, %User{email: nil}} = User.change_email(user, nil)
2347 test "non unique email returns error", %{user: user} do
2348 %{email: email} = insert(:user)
2350 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
2351 User.change_email(user, email)
2354 test "invalid email returns error", %{user: user} do
2355 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
2356 User.change_email(user, "cofe")
2359 test "changes email", %{user: user} do
2360 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
2363 test "adds email", %{user: user} do
2364 orig_account_activation_required =
2365 Pleroma.Config.get([:instance, :account_activation_required])
2367 Pleroma.Config.put([:instance, :account_activation_required], false)
2371 [:instance, :account_activation_required],
2372 orig_account_activation_required
2376 assert {:ok, _} = User.change_email(user, "")
2377 Pleroma.Config.put([:instance, :account_activation_required], true)
2379 assert {:ok, %User{email: "cofe2@cofe.party"}} = User.change_email(user, "cofe2@cofe.party")
2383 describe "get_cached_by_nickname_or_id" do
2385 local_user = insert(:user)
2386 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
2388 [local_user: local_user, remote_user: remote_user]
2391 setup do: clear_config([:instance, :limit_to_local_content])
2393 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
2394 remote_user: remote_user
2396 clear_config([:instance, :limit_to_local_content], false)
2397 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2399 clear_config([:instance, :limit_to_local_content], true)
2400 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2402 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2403 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2406 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
2407 %{remote_user: remote_user} do
2408 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2409 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2412 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
2413 %{remote_user: remote_user, local_user: local_user} do
2414 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2415 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
2418 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
2419 %{remote_user: remote_user} do
2420 clear_config([:instance, :limit_to_local_content], true)
2421 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2424 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
2425 %{local_user: local_user} do
2426 clear_config([:instance, :limit_to_local_content], false)
2427 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2429 clear_config([:instance, :limit_to_local_content], true)
2430 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2432 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2433 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2437 describe "update_email_notifications/2" do
2439 user = insert(:user, email_notifications: %{"digest" => true})
2444 test "Notifications are updated", %{user: user} do
2445 true = user.email_notifications["digest"]
2446 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
2447 assert result.email_notifications["digest"] == false
2451 describe "local_nickname/1" do
2452 test "returns nickname without host" do
2453 assert User.local_nickname("@mentioned") == "mentioned"
2454 assert User.local_nickname("a_local_nickname") == "a_local_nickname"
2455 assert User.local_nickname("nickname@host.com") == "nickname"
2459 describe "full_nickname/1" do
2460 test "returns fully qualified nickname for local and remote users" do
2462 insert(:user, nickname: "local_user", ap_id: "https://somehost.com/users/local_user")
2464 remote_user = insert(:user, nickname: "remote@host.com", local: false)
2466 assert User.full_nickname(local_user) == "local_user@somehost.com"
2467 assert User.full_nickname(remote_user) == "remote@host.com"
2470 test "strips leading @ from mentions" do
2471 assert User.full_nickname("@mentioned") == "mentioned"
2472 assert User.full_nickname("@nickname@host.com") == "nickname@host.com"
2475 test "does not modify nicknames" do
2476 assert User.full_nickname("nickname") == "nickname"
2477 assert User.full_nickname("nickname@host.com") == "nickname@host.com"
2481 test "avatar fallback" do
2482 user = insert(:user)
2483 assert User.avatar_url(user) =~ "/images/avi.png"
2485 clear_config([:assets, :default_user_avatar], "avatar.png")
2487 user = User.get_cached_by_nickname_or_id(user.nickname)
2488 assert User.avatar_url(user) =~ "avatar.png"
2490 assert User.avatar_url(user, no_default: true) == nil
2493 test "get_host/1" do
2494 user = insert(:user, ap_id: "https://lain.com/users/lain", nickname: "lain")
2495 assert User.get_host(user) == "lain.com"
2498 test "update_last_active_at/1" do
2499 user = insert(:user)
2500 assert is_nil(user.last_active_at)
2502 test_started_at = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
2504 assert {:ok, user} = User.update_last_active_at(user)
2506 assert user.last_active_at >= test_started_at
2507 assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
2510 NaiveDateTime.utc_now()
2511 |> NaiveDateTime.add(-:timer.hours(24), :millisecond)
2512 |> NaiveDateTime.truncate(:second)
2514 assert {:ok, user} =
2516 |> cast(%{last_active_at: last_active_at}, [:last_active_at])
2517 |> User.update_and_set_cache()
2519 assert user.last_active_at == last_active_at
2520 assert {:ok, user} = User.update_last_active_at(user)
2521 assert user.last_active_at >= test_started_at
2522 assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
2525 test "active_user_count/1" do
2527 insert(:user, %{local: false})
2528 insert(:user, %{last_active_at: NaiveDateTime.utc_now()})
2529 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), days: -15)})
2530 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), weeks: -6)})
2531 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), months: -7)})
2532 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), years: -2)})
2534 assert User.active_user_count() == 2
2535 assert User.active_user_count(180) == 3
2536 assert User.active_user_count(365) == 4
2537 assert User.active_user_count(1000) == 5
2542 user = insert(:user)
2544 [user: user, object_id: object_id_from_created_activity(user)]
2547 test "unique pins", %{user: user, object_id: object_id} do
2548 assert {:ok, %{pinned_objects: %{^object_id => pinned_at1} = pins} = updated_user} =
2549 User.add_pinned_object_id(user, object_id)
2551 assert Enum.count(pins) == 1
2553 assert {:ok, %{pinned_objects: %{^object_id => pinned_at2} = pins}} =
2554 User.add_pinned_object_id(updated_user, object_id)
2556 assert pinned_at1 == pinned_at2
2558 assert Enum.count(pins) == 1
2561 test "respects max_pinned_statuses limit", %{user: user, object_id: object_id} do
2562 clear_config([:instance, :max_pinned_statuses], 1)
2563 {:ok, updated} = User.add_pinned_object_id(user, object_id)
2565 object_id2 = object_id_from_created_activity(user)
2567 {:error, %{errors: errors}} = User.add_pinned_object_id(updated, object_id2)
2568 assert Keyword.has_key?(errors, :pinned_objects)
2571 test "remove_pinned_object_id/2", %{user: user, object_id: object_id} do
2572 assert {:ok, updated} = User.add_pinned_object_id(user, object_id)
2574 {:ok, after_remove} = User.remove_pinned_object_id(updated, object_id)
2575 assert after_remove.pinned_objects == %{}
2579 defp object_id_from_created_activity(user) do
2580 %{id: id} = insert(:note_activity, user: user)
2581 %{object: %{data: %{"id" => object_id}}} = Activity.get_by_id_with_object(id)
2585 describe "add_alias/2" do
2586 test "should add alias for another user" do
2587 user = insert(:user)
2588 user2 = insert(:user)
2590 assert {:ok, user_updated} = user |> User.add_alias(user2)
2592 assert user_updated.also_known_as |> length() == 1
2593 assert user2.ap_id in user_updated.also_known_as
2596 test "should add multiple aliases" do
2597 user = insert(:user)
2598 user2 = insert(:user)
2599 user3 = insert(:user)
2601 assert {:ok, user} = user |> User.add_alias(user2)
2602 assert {:ok, user_updated} = user |> User.add_alias(user3)
2604 assert user_updated.also_known_as |> length() == 2
2605 assert user2.ap_id in user_updated.also_known_as
2606 assert user3.ap_id in user_updated.also_known_as
2609 test "should not add duplicate aliases" do
2610 user = insert(:user)
2611 user2 = insert(:user)
2613 assert {:ok, user} = user |> User.add_alias(user2)
2615 assert {:ok, user_updated} = user |> User.add_alias(user2)
2617 assert user_updated.also_known_as |> length() == 1
2618 assert user2.ap_id in user_updated.also_known_as
2622 describe "alias_users/1" do
2623 test "should get aliases for a user" do
2624 user = insert(:user)
2625 user2 = insert(:user, also_known_as: [user.ap_id])
2627 aliases = user2 |> User.alias_users()
2629 assert aliases |> length() == 1
2631 alias_user = aliases |> Enum.at(0)
2633 assert alias_user.ap_id == user.ap_id
2637 describe "delete_alias/2" do
2638 test "should delete existing alias" do
2639 user = insert(:user)
2640 user2 = insert(:user, also_known_as: [user.ap_id])
2642 assert {:ok, user_updated} = user2 |> User.delete_alias(user)
2644 assert user_updated.also_known_as == []
2647 test "should report error on non-existing alias" do
2648 user = insert(:user)
2649 user2 = insert(:user)
2650 user3 = insert(:user, also_known_as: [user.ap_id])
2652 assert {:error, :no_such_alias} = user3 |> User.delete_alias(user2)
2654 user3_updated = User.get_cached_by_ap_id(user3.ap_id)
2656 assert user3_updated.also_known_as |> length() == 1
2657 assert user.ap_id in user3_updated.also_known_as