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 synchronizes 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
452 federated_timeline_removal: [],
466 Pleroma.Web.ActivityPub.MRF.SimplePolicy
470 test "it sends a welcome email message if it is set" do
471 welcome_user = insert(:user)
472 clear_config([:welcome, :email, :enabled], true)
473 clear_config([:welcome, :email, :sender], welcome_user.email)
476 [:welcome, :email, :subject],
477 "Hello, welcome to cool site: <%= instance_name %>"
480 instance_name = Pleroma.Config.get([:instance, :name])
482 cng = User.register_changeset(%User{}, @full_user_data)
483 {:ok, registered_user} = User.register(cng)
484 ObanHelpers.perform_all()
487 from: {instance_name, welcome_user.email},
488 to: {registered_user.name, registered_user.email},
489 subject: "Hello, welcome to cool site: #{instance_name}",
490 html_body: "Welcome to #{instance_name}"
494 test "it sends a confirm email" do
495 clear_config([:instance, :account_activation_required], true)
497 cng = User.register_changeset(%User{}, @full_user_data)
498 {:ok, registered_user} = User.register(cng)
499 ObanHelpers.perform_all()
501 Pleroma.Emails.UserEmail.account_confirmation_email(registered_user)
502 # temporary hackney fix until hackney max_connections bug is fixed
503 # https://git.pleroma.social/pleroma/pleroma/-/issues/2101
504 |> Swoosh.Email.put_private(:hackney_options, ssl_options: [versions: [:"tlsv1.2"]])
505 |> assert_email_sent()
508 test "sends a pending approval email" do
509 clear_config([:instance, :account_approval_required], true)
512 User.register_changeset(%User{}, @full_user_data)
515 ObanHelpers.perform_all()
518 from: Pleroma.Config.Helpers.sender(),
519 to: {user.name, user.email},
520 subject: "Your account is awaiting approval"
524 test "it sends a registration confirmed email if no others will be sent" do
525 clear_config([:welcome, :email, :enabled], false)
526 clear_config([:instance, :account_activation_required], false)
527 clear_config([:instance, :account_approval_required], false)
530 User.register_changeset(%User{}, @full_user_data)
533 ObanHelpers.perform_all()
535 instance_name = Pleroma.Config.get([:instance, :name])
536 sender = Pleroma.Config.get([:instance, :notify_email])
539 from: {instance_name, sender},
540 to: {user.name, user.email},
541 subject: "Account registered on #{instance_name}"
545 test "it fails gracefully with invalid email config" do
546 cng = User.register_changeset(%User{}, @full_user_data)
548 # Disable the mailer but enable all the things that want to send emails
549 clear_config([Pleroma.Emails.Mailer, :enabled], false)
550 clear_config([:instance, :account_activation_required], true)
551 clear_config([:instance, :account_approval_required], true)
552 clear_config([:welcome, :email, :enabled], true)
553 clear_config([:welcome, :email, :sender], "lain@lain.com")
555 # The user is still created
556 assert {:ok, %User{nickname: "nick"}} = User.register(cng)
559 ObanHelpers.perform_all()
563 test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do
564 clear_config([:instance, :account_activation_required], true)
568 |> Enum.each(fn key ->
569 params = Map.delete(@full_user_data, key)
570 changeset = User.register_changeset(%User{}, params)
572 assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
576 test "it requires an name, nickname and password, bio and email are optional when account_activation_required is disabled" do
577 clear_config([:instance, :account_activation_required], false)
581 |> Enum.each(fn key ->
582 params = Map.delete(@full_user_data, key)
583 changeset = User.register_changeset(%User{}, params)
585 assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid?
589 test "it restricts certain nicknames" do
590 [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
592 assert is_bitstring(restricted_name)
596 |> Map.put(:nickname, restricted_name)
598 changeset = User.register_changeset(%User{}, params)
600 refute changeset.valid?
603 test "it blocks blacklisted email domains" do
604 clear_config([User, :email_blacklist], ["trolling.world"])
607 params = Map.put(@full_user_data, :email, "troll@trolling.world")
608 changeset = User.register_changeset(%User{}, params)
609 refute changeset.valid?
611 # Block with subdomain match
612 params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world")
613 changeset = User.register_changeset(%User{}, params)
614 refute changeset.valid?
616 # Pass with different domains that are similar
617 params = Map.put(@full_user_data, :email, "troll@gnomestrolling.world")
618 changeset = User.register_changeset(%User{}, params)
619 assert changeset.valid?
621 params = Map.put(@full_user_data, :email, "troll@trolling.world.us")
622 changeset = User.register_changeset(%User{}, params)
623 assert changeset.valid?
626 test "it sets the password_hash, ap_id, private key and followers collection address" do
627 changeset = User.register_changeset(%User{}, @full_user_data)
629 assert changeset.valid?
631 assert is_binary(changeset.changes[:password_hash])
632 assert is_binary(changeset.changes[:keys])
633 assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
634 assert is_binary(changeset.changes[:keys])
635 assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
638 test "it creates a confirmed user" do
639 changeset = User.register_changeset(%User{}, @full_user_data)
640 assert changeset.valid?
642 {:ok, user} = Repo.insert(changeset)
644 assert user.is_confirmed
648 describe "user registration, with :account_activation_required" do
654 password_confirmation: "test",
655 email: "email@example.com"
657 setup do: clear_config([:instance, :account_activation_required], true)
659 test "it creates unconfirmed user" do
660 changeset = User.register_changeset(%User{}, @full_user_data)
661 assert changeset.valid?
663 {:ok, user} = Repo.insert(changeset)
665 refute user.is_confirmed
666 assert user.confirmation_token
669 test "it creates confirmed user if :confirmed option is given" do
670 changeset = User.register_changeset(%User{}, @full_user_data, confirmed: true)
671 assert changeset.valid?
673 {:ok, user} = Repo.insert(changeset)
675 assert user.is_confirmed
676 refute user.confirmation_token
680 describe "user registration, with :account_approval_required" do
686 password_confirmation: "test",
687 email: "email@example.com",
688 registration_reason: "I'm a cool guy :)"
690 setup do: clear_config([:instance, :account_approval_required], true)
692 test "it creates unapproved user" do
693 changeset = User.register_changeset(%User{}, @full_user_data)
694 assert changeset.valid?
696 {:ok, user} = Repo.insert(changeset)
698 refute user.is_approved
699 assert user.registration_reason == "I'm a cool guy :)"
702 test "it restricts length of registration reason" do
703 reason_limit = Pleroma.Config.get([:instance, :registration_reason_length])
705 assert is_integer(reason_limit)
710 :registration_reason,
711 "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."
714 changeset = User.register_changeset(%User{}, params)
716 refute changeset.valid?
720 describe "get_or_fetch/1" do
721 test "gets an existing user by nickname" do
723 {:ok, fetched_user} = User.get_or_fetch(user.nickname)
725 assert user == fetched_user
728 test "gets an existing user by ap_id" do
729 ap_id = "http://mastodon.example.org/users/admin"
735 nickname: "admin@mastodon.example.org",
739 {:ok, fetched_user} = User.get_or_fetch(ap_id)
740 freshed_user = refresh_record(user)
741 assert freshed_user == fetched_user
744 test "gets an existing user by nickname starting with http" do
745 user = insert(:user, nickname: "httpssome")
746 {:ok, fetched_user} = User.get_or_fetch("httpssome")
748 assert user == fetched_user
752 describe "get_or_fetch/1 remote users with tld, while BE is runned on subdomain" do
753 setup do: clear_config([Pleroma.Web.WebFinger, :update_nickname_on_user_fetch], true)
755 test "for mastodon" do
757 %{url: "https://example.com/.well-known/host-meta"} ->
760 headers: [{"location", "https://sub.example.com/.well-known/host-meta"}]
763 %{url: "https://sub.example.com/.well-known/host-meta"} ->
767 "test/fixtures/webfinger/masto-host-meta.xml"
769 |> String.replace("{{domain}}", "sub.example.com")
772 %{url: "https://sub.example.com/.well-known/webfinger?resource=acct:a@example.com"} ->
776 "test/fixtures/webfinger/masto-webfinger.json"
778 |> String.replace("{{nickname}}", "a")
779 |> String.replace("{{domain}}", "example.com")
780 |> String.replace("{{subdomain}}", "sub.example.com"),
781 headers: [{"content-type", "application/jrd+json"}]
784 %{url: "https://sub.example.com/users/a"} ->
788 "test/fixtures/webfinger/masto-user.json"
790 |> String.replace("{{nickname}}", "a")
791 |> String.replace("{{domain}}", "sub.example.com"),
792 headers: [{"content-type", "application/activity+json"}]
795 %{url: "https://sub.example.com/users/a/collections/featured"} ->
799 File.read!("test/fixtures/users_mock/masto_featured.json")
800 |> String.replace("{{domain}}", "sub.example.com")
801 |> String.replace("{{nickname}}", "a"),
802 headers: [{"content-type", "application/activity+json"}]
806 ap_id = "a@example.com"
807 {:ok, fetched_user} = User.get_or_fetch(ap_id)
809 assert fetched_user.ap_id == "https://sub.example.com/users/a"
810 assert fetched_user.nickname == "a@example.com"
813 test "for pleroma" do
815 %{url: "https://example.com/.well-known/host-meta"} ->
818 headers: [{"location", "https://sub.example.com/.well-known/host-meta"}]
821 %{url: "https://sub.example.com/.well-known/host-meta"} ->
825 "test/fixtures/webfinger/pleroma-host-meta.xml"
827 |> String.replace("{{domain}}", "sub.example.com")
830 %{url: "https://sub.example.com/.well-known/webfinger?resource=acct:a@example.com"} ->
834 "test/fixtures/webfinger/pleroma-webfinger.json"
836 |> String.replace("{{nickname}}", "a")
837 |> String.replace("{{domain}}", "example.com")
838 |> String.replace("{{subdomain}}", "sub.example.com"),
839 headers: [{"content-type", "application/jrd+json"}]
842 %{url: "https://sub.example.com/users/a"} ->
846 "test/fixtures/webfinger/pleroma-user.json"
848 |> String.replace("{{nickname}}", "a")
849 |> String.replace("{{domain}}", "sub.example.com"),
850 headers: [{"content-type", "application/activity+json"}]
854 ap_id = "a@example.com"
855 {:ok, fetched_user} = User.get_or_fetch(ap_id)
857 assert fetched_user.ap_id == "https://sub.example.com/users/a"
858 assert fetched_user.nickname == "a@example.com"
862 describe "fetching a user from nickname or trying to build one" do
863 test "gets an existing user" do
865 {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
867 assert user == fetched_user
870 test "gets an existing user, case insensitive" do
871 user = insert(:user, nickname: "nick")
872 {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
874 assert user == fetched_user
877 test "gets an existing user by fully qualified nickname" do
880 {:ok, fetched_user} =
881 User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
883 assert user == fetched_user
886 test "gets an existing user by fully qualified nickname, case insensitive" do
887 user = insert(:user, nickname: "nick")
888 casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
890 {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
892 assert user == fetched_user
895 @tag capture_log: true
896 test "returns nil if no user could be fetched" do
897 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
898 assert fetched_user == "not found nonexistant@social.heldscal.la"
901 test "returns nil for nonexistant local user" do
902 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
903 assert fetched_user == "not found nonexistant"
906 test "updates an existing user, if stale" do
907 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
913 nickname: "admin@mastodon.example.org",
914 ap_id: "http://mastodon.example.org/users/admin",
915 last_refreshed_at: a_week_ago
918 assert orig_user.last_refreshed_at == a_week_ago
920 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
924 refute user.last_refreshed_at == orig_user.last_refreshed_at
927 test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
928 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
934 nickname: "admin@mastodon.example.org",
935 ap_id: "http://mastodon.example.org/users/harinezumigari",
936 last_refreshed_at: a_week_ago
939 assert orig_user.last_refreshed_at == a_week_ago
941 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
945 refute user.id == orig_user.id
947 orig_user = User.get_by_id(orig_user.id)
949 assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
952 @tag capture_log: true
953 test "it returns the old user if stale, but unfetchable" do
954 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
960 nickname: "admin@mastodon.example.org",
961 ap_id: "http://mastodon.example.org/users/raymoo",
962 last_refreshed_at: a_week_ago
965 assert orig_user.last_refreshed_at == a_week_ago
967 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/raymoo")
969 assert user.last_refreshed_at == orig_user.last_refreshed_at
973 test "returns an ap_id for a user" do
976 assert User.ap_id(user) ==
977 Pleroma.Web.Router.Helpers.user_feed_url(
978 Pleroma.Web.Endpoint,
984 test "returns an ap_followers link for a user" do
987 assert User.ap_followers(user) ==
988 Pleroma.Web.Router.Helpers.user_feed_url(
989 Pleroma.Web.Endpoint,
995 describe "remote user changeset" do
1001 avatar: %{some: "avatar"}
1003 setup do: clear_config([:instance, :user_bio_length])
1004 setup do: clear_config([:instance, :user_name_length])
1006 test "it confirms validity" do
1007 cs = User.remote_user_changeset(@valid_remote)
1011 test "it sets the follower_adress" do
1012 cs = User.remote_user_changeset(@valid_remote)
1013 # remote users get a fake local follower address
1014 assert cs.changes.follower_address ==
1015 User.ap_followers(%User{nickname: @valid_remote[:nickname]})
1018 test "it enforces the fqn format for nicknames" do
1019 cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})
1020 assert Ecto.Changeset.get_field(cs, :local) == false
1021 assert cs.changes.avatar
1025 test "it has required fields" do
1027 |> Enum.each(fn field ->
1028 cs = User.remote_user_changeset(Map.delete(@valid_remote, field))
1033 test "it is invalid given a local user" do
1034 user = insert(:user)
1035 cs = User.remote_user_changeset(user, %{name: "tom from myspace"})
1041 describe "followers and friends" do
1042 test "gets all followers for a given user" do
1043 user = insert(:user)
1044 follower_one = insert(:user)
1045 follower_two = insert(:user)
1046 not_follower = insert(:user)
1048 {:ok, follower_one, user} = User.follow(follower_one, user)
1049 {:ok, follower_two, user} = User.follow(follower_two, user)
1051 res = User.get_followers(user)
1053 assert Enum.member?(res, follower_one)
1054 assert Enum.member?(res, follower_two)
1055 refute Enum.member?(res, not_follower)
1058 test "gets all friends (followed users) for a given user" do
1059 user = insert(:user)
1060 followed_one = insert(:user)
1061 followed_two = insert(:user)
1062 not_followed = insert(:user)
1064 {:ok, user, followed_one} = User.follow(user, followed_one)
1065 {:ok, user, followed_two} = User.follow(user, followed_two)
1067 res = User.get_friends(user)
1069 followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
1070 followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
1071 assert Enum.member?(res, followed_one)
1072 assert Enum.member?(res, followed_two)
1073 refute Enum.member?(res, not_followed)
1077 describe "updating note and follower count" do
1078 test "it sets the note_count property" do
1079 note = insert(:note)
1081 user = User.get_cached_by_ap_id(note.data["actor"])
1083 assert user.note_count == 0
1085 {:ok, user} = User.update_note_count(user)
1087 assert user.note_count == 1
1090 test "it increases the note_count property" do
1091 note = insert(:note)
1092 user = User.get_cached_by_ap_id(note.data["actor"])
1094 assert user.note_count == 0
1096 {:ok, user} = User.increase_note_count(user)
1098 assert user.note_count == 1
1100 {:ok, user} = User.increase_note_count(user)
1102 assert user.note_count == 2
1105 test "it decreases the note_count property" do
1106 note = insert(:note)
1107 user = User.get_cached_by_ap_id(note.data["actor"])
1109 assert user.note_count == 0
1111 {:ok, user} = User.increase_note_count(user)
1113 assert user.note_count == 1
1115 {:ok, user} = User.decrease_note_count(user)
1117 assert user.note_count == 0
1119 {:ok, user} = User.decrease_note_count(user)
1121 assert user.note_count == 0
1124 test "it sets the follower_count property" do
1125 user = insert(:user)
1126 follower = insert(:user)
1128 User.follow(follower, user)
1130 assert user.follower_count == 0
1132 {:ok, user} = User.update_follower_count(user)
1134 assert user.follower_count == 1
1139 test "it mutes people" do
1140 user = insert(:user)
1141 muted_user = insert(:user)
1143 refute User.mutes?(user, muted_user)
1144 refute User.muted_notifications?(user, muted_user)
1146 {:ok, _user_relationships} = User.mute(user, muted_user)
1148 assert User.mutes?(user, muted_user)
1149 assert User.muted_notifications?(user, muted_user)
1153 user = insert(:user)
1154 muted_user = insert(:user)
1156 {:ok, _user_relationships} = User.mute(user, muted_user, %{expires_in: 60})
1157 assert User.mutes?(user, muted_user)
1159 worker = Pleroma.Workers.MuteExpireWorker
1160 args = %{"op" => "unmute_user", "muter_id" => user.id, "mutee_id" => muted_user.id}
1167 assert :ok = perform_job(worker, args)
1169 refute User.mutes?(user, muted_user)
1170 refute User.muted_notifications?(user, muted_user)
1173 test "it unmutes users" do
1174 user = insert(:user)
1175 muted_user = insert(:user)
1177 {:ok, _user_relationships} = User.mute(user, muted_user)
1178 {:ok, _user_mute} = User.unmute(user, muted_user)
1180 refute User.mutes?(user, muted_user)
1181 refute User.muted_notifications?(user, muted_user)
1184 test "it unmutes users by id" do
1185 user = insert(:user)
1186 muted_user = insert(:user)
1188 {:ok, _user_relationships} = User.mute(user, muted_user)
1189 {:ok, _user_mute} = User.unmute(user.id, muted_user.id)
1191 refute User.mutes?(user, muted_user)
1192 refute User.muted_notifications?(user, muted_user)
1195 test "it mutes user without notifications" do
1196 user = insert(:user)
1197 muted_user = insert(:user)
1199 refute User.mutes?(user, muted_user)
1200 refute User.muted_notifications?(user, muted_user)
1202 {:ok, _user_relationships} = User.mute(user, muted_user, %{notifications: false})
1204 assert User.mutes?(user, muted_user)
1205 refute User.muted_notifications?(user, muted_user)
1209 describe "blocks" do
1210 test "it blocks people" do
1211 user = insert(:user)
1212 blocked_user = insert(:user)
1214 refute User.blocks?(user, blocked_user)
1216 {:ok, _user_relationship} = User.block(user, blocked_user)
1218 assert User.blocks?(user, blocked_user)
1221 test "it unblocks users" do
1222 user = insert(:user)
1223 blocked_user = insert(:user)
1225 {:ok, _user_relationship} = User.block(user, blocked_user)
1226 {:ok, _user_block} = User.unblock(user, blocked_user)
1228 refute User.blocks?(user, blocked_user)
1231 test "blocks tear down cyclical follow relationships" do
1232 blocker = insert(:user)
1233 blocked = insert(:user)
1235 {:ok, blocker, blocked} = User.follow(blocker, blocked)
1236 {:ok, blocked, blocker} = User.follow(blocked, blocker)
1238 assert User.following?(blocker, blocked)
1239 assert User.following?(blocked, blocker)
1241 {:ok, _user_relationship} = User.block(blocker, blocked)
1242 blocked = User.get_cached_by_id(blocked.id)
1244 assert User.blocks?(blocker, blocked)
1246 refute User.following?(blocker, blocked)
1247 refute User.following?(blocked, blocker)
1250 test "blocks tear down blocker->blocked follow relationships" do
1251 blocker = insert(:user)
1252 blocked = insert(:user)
1254 {:ok, blocker, blocked} = User.follow(blocker, blocked)
1256 assert User.following?(blocker, blocked)
1257 refute User.following?(blocked, blocker)
1259 {:ok, _user_relationship} = User.block(blocker, blocked)
1260 blocked = User.get_cached_by_id(blocked.id)
1262 assert User.blocks?(blocker, blocked)
1264 refute User.following?(blocker, blocked)
1265 refute User.following?(blocked, blocker)
1268 test "blocks tear down blocked->blocker follow relationships" do
1269 blocker = insert(:user)
1270 blocked = insert(:user)
1272 {:ok, blocked, blocker} = User.follow(blocked, blocker)
1274 refute User.following?(blocker, blocked)
1275 assert User.following?(blocked, blocker)
1277 {:ok, _user_relationship} = User.block(blocker, blocked)
1278 blocked = User.get_cached_by_id(blocked.id)
1280 assert User.blocks?(blocker, blocked)
1282 refute User.following?(blocker, blocked)
1283 refute User.following?(blocked, blocker)
1286 test "blocks tear down blocked->blocker subscription relationships" do
1287 blocker = insert(:user)
1288 blocked = insert(:user)
1290 {:ok, _subscription} = User.subscribe(blocked, blocker)
1292 assert User.subscribed_to?(blocked, blocker)
1293 refute User.subscribed_to?(blocker, blocked)
1295 {:ok, _user_relationship} = User.block(blocker, blocked)
1297 assert User.blocks?(blocker, blocked)
1298 refute User.subscribed_to?(blocker, blocked)
1299 refute User.subscribed_to?(blocked, blocker)
1303 describe "domain blocking" do
1304 test "blocks domains" do
1305 user = insert(:user)
1306 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1308 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1310 assert User.blocks?(user, collateral_user)
1313 test "does not block domain with same end" do
1314 user = insert(:user)
1317 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1319 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1321 refute User.blocks?(user, collateral_user)
1324 test "does not block domain with same end if wildcard added" do
1325 user = insert(:user)
1328 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1330 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1332 refute User.blocks?(user, collateral_user)
1335 test "blocks domain with wildcard for subdomain" do
1336 user = insert(:user)
1338 user_from_subdomain =
1339 insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
1341 user_with_two_subdomains =
1343 ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
1346 user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1348 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1350 assert User.blocks?(user, user_from_subdomain)
1351 assert User.blocks?(user, user_with_two_subdomains)
1352 assert User.blocks?(user, user_domain)
1355 test "unblocks domains" do
1356 user = insert(:user)
1357 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1359 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1360 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
1362 refute User.blocks?(user, collateral_user)
1365 test "follows take precedence over domain blocks" do
1366 user = insert(:user)
1367 good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
1369 {:ok, user} = User.block_domain(user, "meanies.social")
1370 {:ok, user, good_eggo} = User.follow(user, good_eggo)
1372 refute User.blocks?(user, good_eggo)
1376 describe "get_recipients_from_activity" do
1377 test "works for announces" do
1378 actor = insert(:user)
1379 user = insert(:user, local: true)
1381 {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
1382 {:ok, announce} = CommonAPI.repeat(activity.id, user)
1384 recipients = User.get_recipients_from_activity(announce)
1386 assert user in recipients
1389 test "get recipients" do
1390 actor = insert(:user)
1391 user = insert(:user, local: true)
1392 user_two = insert(:user, local: false)
1393 addressed = insert(:user, local: true)
1394 addressed_remote = insert(:user, local: false)
1397 CommonAPI.post(actor, %{
1398 status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
1401 assert Enum.map([actor, addressed], & &1.ap_id) --
1402 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1404 {:ok, user, actor} = User.follow(user, actor)
1405 {:ok, _user_two, _actor} = User.follow(user_two, actor)
1406 recipients = User.get_recipients_from_activity(activity)
1407 assert length(recipients) == 3
1408 assert user in recipients
1409 assert addressed in recipients
1412 test "has following" do
1413 actor = insert(:user)
1414 user = insert(:user)
1415 user_two = insert(:user)
1416 addressed = insert(:user, local: true)
1419 CommonAPI.post(actor, %{
1420 status: "hey @#{addressed.nickname}"
1423 assert Enum.map([actor, addressed], & &1.ap_id) --
1424 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1426 {:ok, _actor, _user} = User.follow(actor, user)
1427 {:ok, _actor, _user_two} = User.follow(actor, user_two)
1428 recipients = User.get_recipients_from_activity(activity)
1429 assert length(recipients) == 2
1430 assert addressed in recipients
1434 describe ".set_activation" do
1435 test "can de-activate then re-activate a user" do
1436 user = insert(:user)
1437 assert user.is_active
1438 {:ok, user} = User.set_activation(user, false)
1439 refute user.is_active
1440 {:ok, user} = User.set_activation(user, true)
1441 assert user.is_active
1444 test "hide a user from followers" do
1445 user = insert(:user)
1446 user2 = insert(:user)
1448 {:ok, user, user2} = User.follow(user, user2)
1449 {:ok, _user} = User.set_activation(user, false)
1451 user2 = User.get_cached_by_id(user2.id)
1453 assert user2.follower_count == 0
1454 assert [] = User.get_followers(user2)
1457 test "hide a user from friends" do
1458 user = insert(:user)
1459 user2 = insert(:user)
1461 {:ok, user2, user} = User.follow(user2, user)
1462 assert user2.following_count == 1
1463 assert User.following_count(user2) == 1
1465 {:ok, _user} = User.set_activation(user, false)
1467 user2 = User.get_cached_by_id(user2.id)
1469 assert refresh_record(user2).following_count == 0
1470 assert user2.following_count == 0
1471 assert User.following_count(user2) == 0
1472 assert [] = User.get_friends(user2)
1475 test "hide a user's statuses from timelines and notifications" do
1476 user = insert(:user)
1477 user2 = insert(:user)
1479 {:ok, user2, user} = User.follow(user2, user)
1481 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
1483 activity = Repo.preload(activity, :bookmark)
1485 [notification] = Pleroma.Notification.for_user(user2)
1486 assert notification.activity.id == activity.id
1488 assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
1490 assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
1491 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1495 {:ok, _user} = User.set_activation(user, false)
1497 assert [] == ActivityPub.fetch_public_activities(%{})
1498 assert [] == Pleroma.Notification.for_user(user2)
1501 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1507 describe "approve" do
1508 test "approves a user" do
1509 user = insert(:user, is_approved: false)
1510 refute user.is_approved
1511 {:ok, user} = User.approve(user)
1512 assert user.is_approved
1515 test "approves a list of users" do
1516 unapproved_users = [
1517 insert(:user, is_approved: false),
1518 insert(:user, is_approved: false),
1519 insert(:user, is_approved: false)
1522 {:ok, users} = User.approve(unapproved_users)
1524 assert Enum.count(users) == 3
1526 Enum.each(users, fn user ->
1527 assert user.is_approved
1531 test "it sends welcome email if it is set" do
1532 clear_config([:welcome, :email, :enabled], true)
1533 clear_config([:welcome, :email, :sender], "tester@test.me")
1535 user = insert(:user, is_approved: false)
1536 welcome_user = insert(:user, email: "tester@test.me")
1537 instance_name = Pleroma.Config.get([:instance, :name])
1541 ObanHelpers.perform_all()
1544 from: {instance_name, welcome_user.email},
1545 to: {user.name, user.email},
1546 html_body: "Welcome to #{instance_name}"
1550 test "approving an approved user does not trigger post-register actions" do
1551 clear_config([:welcome, :email, :enabled], true)
1553 user = insert(:user, is_approved: true)
1556 ObanHelpers.perform_all()
1558 assert_no_email_sent()
1562 describe "confirm" do
1563 test "confirms a user" do
1564 user = insert(:user, is_confirmed: false)
1565 refute user.is_confirmed
1566 {:ok, user} = User.confirm(user)
1567 assert user.is_confirmed
1570 test "confirms a list of users" do
1571 unconfirmed_users = [
1572 insert(:user, is_confirmed: false),
1573 insert(:user, is_confirmed: false),
1574 insert(:user, is_confirmed: false)
1577 {:ok, users} = User.confirm(unconfirmed_users)
1579 assert Enum.count(users) == 3
1581 Enum.each(users, fn user ->
1582 assert user.is_confirmed
1586 test "sends approval emails when `is_approved: false`" do
1587 admin = insert(:user, is_admin: true)
1588 user = insert(:user, is_confirmed: false, is_approved: false)
1591 ObanHelpers.perform_all()
1593 user_email = Pleroma.Emails.UserEmail.approval_pending_email(user)
1594 admin_email = Pleroma.Emails.AdminEmail.new_unapproved_registration(admin, user)
1596 notify_email = Pleroma.Config.get([:instance, :notify_email])
1597 instance_name = Pleroma.Config.get([:instance, :name])
1599 # User approval email
1601 from: {instance_name, notify_email},
1602 to: {user.name, user.email},
1603 html_body: user_email.html_body
1608 from: {instance_name, notify_email},
1609 to: {admin.name, admin.email},
1610 html_body: admin_email.html_body
1614 test "confirming a confirmed user does not trigger post-register actions" do
1615 user = insert(:user, is_confirmed: true, is_approved: false)
1618 ObanHelpers.perform_all()
1620 assert_no_email_sent()
1624 describe "delete" do
1626 {:ok, user} = insert(:user) |> User.set_cache()
1631 setup do: clear_config([:instance, :federating])
1633 test ".delete_user_activities deletes all create activities", %{user: user} do
1634 {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
1636 User.delete_user_activities(user)
1638 # TODO: Test removal favorites, repeats, delete activities.
1639 refute Activity.get_by_id(activity.id)
1642 test "it deactivates a user, all follow relationships and all activities", %{user: user} do
1643 follower = insert(:user)
1644 {:ok, follower, user} = User.follow(follower, user)
1646 locked_user = insert(:user, name: "locked", is_locked: true)
1647 {:ok, _, _} = User.follow(user, locked_user, :follow_pending)
1649 object = insert(:note, user: user)
1650 activity = insert(:note_activity, user: user, note: object)
1652 object_two = insert(:note, user: follower)
1653 activity_two = insert(:note_activity, user: follower, note: object_two)
1655 {:ok, like} = CommonAPI.favorite(user, activity_two.id)
1656 {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
1657 {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
1659 {:ok, job} = User.delete(user)
1660 {:ok, _user} = ObanHelpers.perform(job)
1662 follower = User.get_cached_by_id(follower.id)
1664 refute User.following?(follower, user)
1665 assert %{is_active: false} = User.get_by_id(user.id)
1667 assert [] == User.get_follow_requests(locked_user)
1671 |> Activity.Queries.by_actor()
1673 |> Enum.map(fn act -> act.data["type"] end)
1675 assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
1677 refute Activity.get_by_id(activity.id)
1678 refute Activity.get_by_id(like.id)
1679 refute Activity.get_by_id(like_two.id)
1680 refute Activity.get_by_id(repeat.id)
1684 test "delete/1 when confirmation is pending deletes the user" do
1685 clear_config([:instance, :account_activation_required], true)
1686 user = insert(:user, is_confirmed: false)
1688 {:ok, job} = User.delete(user)
1689 {:ok, _} = ObanHelpers.perform(job)
1691 refute User.get_cached_by_id(user.id)
1692 refute User.get_by_id(user.id)
1695 test "delete/1 when approval is pending deletes the user" do
1696 user = insert(:user, is_approved: false)
1698 {:ok, job} = User.delete(user)
1699 {:ok, _} = ObanHelpers.perform(job)
1701 refute User.get_cached_by_id(user.id)
1702 refute User.get_by_id(user.id)
1705 test "delete/1 purges a user when they wouldn't be fully deleted" do
1710 password_hash: "pdfk2$1b3n159001",
1711 keys: "RSA begin buplic key",
1712 public_key: "--PRIVATE KEYE--",
1713 avatar: %{"a" => "b"},
1715 banner: %{"a" => "b"},
1716 background: %{"a" => "b"},
1719 following_count: 9001,
1722 password_reset_pending: true,
1724 registration_reason: "ahhhhh",
1725 confirmation_token: "qqqq",
1726 domain_blocks: ["lain.com"],
1731 mastofe_settings: %{"a" => "b"},
1732 mascot: %{"a" => "b"},
1733 emoji: %{"a" => "b"},
1734 pleroma_settings_store: %{"q" => "x"},
1735 fields: [%{"gg" => "qq"}],
1736 raw_fields: [%{"gg" => "qq"}],
1737 is_discoverable: true,
1738 also_known_as: ["https://lol.olo/users/loll"]
1741 {:ok, job} = User.delete(user)
1742 {:ok, _} = ObanHelpers.perform(job)
1743 user = User.get_by_id(user.id)
1751 keys: "RSA begin buplic key",
1752 public_key: "--PRIVATE KEYE--",
1755 last_refreshed_at: nil,
1756 last_digest_emailed_at: nil,
1764 password_reset_pending: false,
1766 registration_reason: nil,
1767 confirmation_token: nil,
1771 is_moderator: false,
1773 mastofe_settings: nil,
1776 pleroma_settings_store: %{},
1779 is_discoverable: false,
1784 test "delete/1 purges a remote user" do
1788 avatar: %{"a" => "b"},
1789 banner: %{"a" => "b"},
1793 {:ok, job} = User.delete(user)
1794 {:ok, _} = ObanHelpers.perform(job)
1795 user = User.get_by_id(user.id)
1797 assert user.name == nil
1798 assert user.avatar == %{}
1799 assert user.banner == %{}
1802 describe "set_suggestion" do
1803 test "suggests a user" do
1804 user = insert(:user, is_suggested: false)
1805 refute user.is_suggested
1806 {:ok, user} = User.set_suggestion(user, true)
1807 assert user.is_suggested
1810 test "suggests a list of users" do
1811 unsuggested_users = [
1812 insert(:user, is_suggested: false),
1813 insert(:user, is_suggested: false),
1814 insert(:user, is_suggested: false)
1817 {:ok, users} = User.set_suggestion(unsuggested_users, true)
1819 assert Enum.count(users) == 3
1821 Enum.each(users, fn user ->
1822 assert user.is_suggested
1826 test "unsuggests a user" do
1827 user = insert(:user, is_suggested: true)
1828 assert user.is_suggested
1829 {:ok, user} = User.set_suggestion(user, false)
1830 refute user.is_suggested
1834 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1835 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1838 describe "per-user rich-text filtering" do
1839 test "html_filter_policy returns default policies, when rich-text is enabled" do
1840 user = insert(:user)
1842 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1845 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1846 user = insert(:user, no_rich_text: true)
1848 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1852 describe "caching" do
1853 test "invalidate_cache works" do
1854 user = insert(:user)
1856 User.set_cache(user)
1857 User.invalidate_cache(user)
1859 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1860 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1863 test "User.delete() plugs any possible zombie objects" do
1864 user = insert(:user)
1866 {:ok, job} = User.delete(user)
1867 {:ok, _} = ObanHelpers.perform(job)
1869 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1871 assert cached_user != user
1873 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1875 assert cached_user != user
1879 describe "account_status/1" do
1880 setup do: clear_config([:instance, :account_activation_required])
1882 test "return confirmation_pending for unconfirm user" do
1883 clear_config([:instance, :account_activation_required], true)
1884 user = insert(:user, is_confirmed: false)
1885 assert User.account_status(user) == :confirmation_pending
1888 test "return active for confirmed user" do
1889 clear_config([:instance, :account_activation_required], true)
1890 user = insert(:user, is_confirmed: true)
1891 assert User.account_status(user) == :active
1894 test "return active for remote user" do
1895 user = insert(:user, local: false)
1896 assert User.account_status(user) == :active
1899 test "returns :password_reset_pending for user with reset password" do
1900 user = insert(:user, password_reset_pending: true)
1901 assert User.account_status(user) == :password_reset_pending
1904 test "returns :deactivated for deactivated user" do
1905 user = insert(:user, local: true, is_confirmed: true, is_active: false)
1906 assert User.account_status(user) == :deactivated
1909 test "returns :approval_pending for unapproved user" do
1910 user = insert(:user, local: true, is_approved: false)
1911 assert User.account_status(user) == :approval_pending
1913 user = insert(:user, local: true, is_confirmed: false, is_approved: false)
1914 assert User.account_status(user) == :approval_pending
1918 describe "superuser?/1" do
1919 test "returns false for unprivileged users" do
1920 user = insert(:user, local: true)
1922 refute User.superuser?(user)
1925 test "returns false for remote users" do
1926 user = insert(:user, local: false)
1927 remote_admin_user = insert(:user, local: false, is_admin: true)
1929 refute User.superuser?(user)
1930 refute User.superuser?(remote_admin_user)
1933 test "returns true for local moderators" do
1934 user = insert(:user, local: true, is_moderator: true)
1936 assert User.superuser?(user)
1939 test "returns true for local admins" do
1940 user = insert(:user, local: true, is_admin: true)
1942 assert User.superuser?(user)
1946 describe "invisible?/1" do
1947 test "returns true for an invisible user" do
1948 user = insert(:user, local: true, invisible: true)
1950 assert User.invisible?(user)
1953 test "returns false for a non-invisible user" do
1954 user = insert(:user, local: true)
1956 refute User.invisible?(user)
1960 describe "visible_for/2" do
1961 test "returns true when the account is itself" do
1962 user = insert(:user, local: true)
1964 assert User.visible_for(user, user) == :visible
1967 test "returns false when the account is unconfirmed and confirmation is required" do
1968 clear_config([:instance, :account_activation_required], true)
1970 user = insert(:user, local: true, is_confirmed: false)
1971 other_user = insert(:user, local: true)
1973 refute User.visible_for(user, other_user) == :visible
1976 test "returns true when the account is unconfirmed and confirmation is required but the account is remote" do
1977 clear_config([:instance, :account_activation_required], true)
1979 user = insert(:user, local: false, is_confirmed: false)
1980 other_user = insert(:user, local: true)
1982 assert User.visible_for(user, other_user) == :visible
1985 test "returns true when the account is unconfirmed and being viewed by a privileged account (confirmation required)" do
1986 clear_config([:instance, :account_activation_required], true)
1988 user = insert(:user, local: true, is_confirmed: false)
1989 other_user = insert(:user, local: true, is_admin: true)
1991 assert User.visible_for(user, other_user) == :visible
1995 describe "parse_bio/2" do
1996 test "preserves hosts in user links text" do
1997 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1998 user = insert(:user)
1999 bio = "A.k.a. @nick@domain.com"
2002 ~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>)
2004 assert expected_text == User.parse_bio(bio, user)
2007 test "Adds rel=me on linkbacked urls" do
2008 user = insert(:user, ap_id: "https://social.example.org/users/lain")
2010 bio = "http://example.com/rel_me/null"
2011 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
2012 assert expected_text == User.parse_bio(bio, user)
2014 bio = "http://example.com/rel_me/link"
2015 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
2016 assert expected_text == User.parse_bio(bio, user)
2018 bio = "http://example.com/rel_me/anchor"
2019 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
2020 assert expected_text == User.parse_bio(bio, user)
2024 test "follower count is updated when a follower is blocked" do
2025 user = insert(:user)
2026 follower = insert(:user)
2027 follower2 = insert(:user)
2028 follower3 = insert(:user)
2030 {:ok, follower, user} = User.follow(follower, user)
2031 {:ok, _follower2, _user} = User.follow(follower2, user)
2032 {:ok, _follower3, _user} = User.follow(follower3, user)
2034 {:ok, _user_relationship} = User.block(user, follower)
2035 user = refresh_record(user)
2037 assert user.follower_count == 2
2040 describe "list_inactive_users_query/1" do
2041 defp days_ago(days) do
2043 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
2044 -days * 60 * 60 * 24,
2049 test "Users are inactive by default" do
2053 Enum.map(1..total, fn _ ->
2054 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
2057 inactive_users_ids =
2058 Pleroma.User.list_inactive_users_query()
2059 |> Pleroma.Repo.all()
2060 |> Enum.map(& &1.id)
2062 Enum.each(users, fn user ->
2063 assert user.id in inactive_users_ids
2067 test "Only includes users who has no recent activity" do
2071 Enum.map(1..total, fn _ ->
2072 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
2075 {inactive, active} = Enum.split(users, trunc(total / 2))
2077 Enum.map(active, fn user ->
2078 to = Enum.random(users -- [user])
2081 CommonAPI.post(user, %{
2082 status: "hey @#{to.nickname}"
2086 inactive_users_ids =
2087 Pleroma.User.list_inactive_users_query()
2088 |> Pleroma.Repo.all()
2089 |> Enum.map(& &1.id)
2091 Enum.each(active, fn user ->
2092 refute user.id in inactive_users_ids
2095 Enum.each(inactive, fn user ->
2096 assert user.id in inactive_users_ids
2100 test "Only includes users with no read notifications" do
2104 Enum.map(1..total, fn _ ->
2105 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
2108 [sender | recipients] = users
2109 {inactive, active} = Enum.split(recipients, trunc(total / 2))
2111 Enum.each(recipients, fn to ->
2113 CommonAPI.post(sender, %{
2114 status: "hey @#{to.nickname}"
2118 CommonAPI.post(sender, %{
2119 status: "hey again @#{to.nickname}"
2123 Enum.each(active, fn user ->
2124 [n1, _n2] = Pleroma.Notification.for_user(user)
2125 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
2128 inactive_users_ids =
2129 Pleroma.User.list_inactive_users_query()
2130 |> Pleroma.Repo.all()
2131 |> Enum.map(& &1.id)
2133 Enum.each(active, fn user ->
2134 refute user.id in inactive_users_ids
2137 Enum.each(inactive, fn user ->
2138 assert user.id in inactive_users_ids
2143 describe "get_ap_ids_by_nicknames" do
2144 test "it returns a list of AP ids for a given set of nicknames" do
2145 user = insert(:user)
2146 user_two = insert(:user)
2148 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
2149 assert length(ap_ids) == 2
2150 assert user.ap_id in ap_ids
2151 assert user_two.ap_id in ap_ids
2155 describe "sync followers count" do
2157 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
2158 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
2159 insert(:user, local: true)
2160 insert(:user, local: false, is_active: false)
2161 {:ok, user1: user1, user2: user2}
2164 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
2165 [fdb_user1] = User.external_users(limit: 1)
2167 assert fdb_user1.ap_id
2168 assert fdb_user1.ap_id == user1.ap_id
2169 assert fdb_user1.id == user1.id
2171 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
2173 assert fdb_user2.ap_id
2174 assert fdb_user2.ap_id == user2.ap_id
2175 assert fdb_user2.id == user2.id
2177 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
2181 describe "is_internal_user?/1" do
2182 test "non-internal user returns false" do
2183 user = insert(:user)
2184 refute User.is_internal_user?(user)
2187 test "user with no nickname returns true" do
2188 user = insert(:user, %{nickname: nil})
2189 assert User.is_internal_user?(user)
2192 test "user with internal-prefixed nickname returns true" do
2193 user = insert(:user, %{nickname: "internal.test"})
2194 assert User.is_internal_user?(user)
2198 describe "update_and_set_cache/1" do
2199 test "returns error when user is stale instead Ecto.StaleEntryError" do
2200 user = insert(:user)
2202 changeset = Ecto.Changeset.change(user, bio: "test")
2206 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
2207 User.update_and_set_cache(changeset)
2210 test "performs update cache if user updated" do
2211 user = insert(:user)
2212 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
2214 changeset = Ecto.Changeset.change(user, bio: "test-bio")
2216 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
2217 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
2218 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
2221 test "removes report notifs when user isn't superuser any more" do
2222 report_activity = insert(:report_activity)
2223 user = insert(:user, is_moderator: true, is_admin: true)
2224 {:ok, _} = Notification.create_notifications(report_activity)
2226 assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
2228 {:ok, user} = user |> User.admin_api_update(%{is_moderator: false})
2229 # is still superuser because still admin
2230 assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
2232 {:ok, user} = user |> User.admin_api_update(%{is_moderator: true, is_admin: false})
2233 # is still superuser because still moderator
2234 assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
2236 {:ok, user} = user |> User.admin_api_update(%{is_moderator: false})
2237 # is not a superuser any more
2238 assert [] = Notification.for_user(user)
2242 describe "following/followers synchronization" do
2243 setup do: clear_config([:instance, :external_user_synchronization])
2245 test "updates the counters normally on following/getting a follow when disabled" do
2246 clear_config([:instance, :external_user_synchronization], false)
2247 user = insert(:user)
2252 follower_address: "http://localhost:4001/users/masto_closed/followers",
2253 following_address: "http://localhost:4001/users/masto_closed/following",
2257 assert other_user.following_count == 0
2258 assert other_user.follower_count == 0
2260 {:ok, user, other_user} = Pleroma.User.follow(user, other_user)
2262 assert user.following_count == 1
2263 assert other_user.follower_count == 1
2266 test "synchronizes the counters with the remote instance for the followed when enabled" do
2267 clear_config([:instance, :external_user_synchronization], false)
2269 user = insert(:user)
2274 follower_address: "http://localhost:4001/users/masto_closed/followers",
2275 following_address: "http://localhost:4001/users/masto_closed/following",
2279 assert other_user.following_count == 0
2280 assert other_user.follower_count == 0
2282 clear_config([:instance, :external_user_synchronization], true)
2283 {:ok, _user, other_user} = User.follow(user, other_user)
2285 assert other_user.follower_count == 437
2288 test "synchronizes the counters with the remote instance for the follower when enabled" do
2289 clear_config([:instance, :external_user_synchronization], false)
2291 user = insert(:user)
2296 follower_address: "http://localhost:4001/users/masto_closed/followers",
2297 following_address: "http://localhost:4001/users/masto_closed/following",
2301 assert other_user.following_count == 0
2302 assert other_user.follower_count == 0
2304 clear_config([:instance, :external_user_synchronization], true)
2305 {:ok, other_user, _user} = User.follow(other_user, user)
2307 assert other_user.following_count == 152
2311 describe "change_email/2" do
2313 [user: insert(:user)]
2316 test "blank email returns error if we require an email on registration", %{user: user} do
2317 orig_account_activation_required =
2318 Pleroma.Config.get([:instance, :account_activation_required])
2320 Pleroma.Config.put([:instance, :account_activation_required], true)
2324 [:instance, :account_activation_required],
2325 orig_account_activation_required
2329 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
2330 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
2333 test "blank email should be fine if we do not require an email on registration", %{user: user} do
2334 orig_account_activation_required =
2335 Pleroma.Config.get([:instance, :account_activation_required])
2337 Pleroma.Config.put([:instance, :account_activation_required], false)
2341 [:instance, :account_activation_required],
2342 orig_account_activation_required
2346 assert {:ok, %User{email: nil}} = User.change_email(user, "")
2347 assert {:ok, %User{email: nil}} = User.change_email(user, nil)
2350 test "non unique email returns error", %{user: user} do
2351 %{email: email} = insert(:user)
2353 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
2354 User.change_email(user, email)
2357 test "invalid email returns error", %{user: user} do
2358 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
2359 User.change_email(user, "cofe")
2362 test "changes email", %{user: user} do
2363 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
2366 test "adds email", %{user: user} do
2367 orig_account_activation_required =
2368 Pleroma.Config.get([:instance, :account_activation_required])
2370 Pleroma.Config.put([:instance, :account_activation_required], false)
2374 [:instance, :account_activation_required],
2375 orig_account_activation_required
2379 assert {:ok, _} = User.change_email(user, "")
2380 Pleroma.Config.put([:instance, :account_activation_required], true)
2382 assert {:ok, %User{email: "cofe2@cofe.party"}} = User.change_email(user, "cofe2@cofe.party")
2386 describe "get_cached_by_nickname_or_id" do
2388 local_user = insert(:user)
2389 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
2391 [local_user: local_user, remote_user: remote_user]
2394 setup do: clear_config([:instance, :limit_to_local_content])
2396 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
2397 remote_user: remote_user
2399 clear_config([:instance, :limit_to_local_content], false)
2400 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2402 clear_config([:instance, :limit_to_local_content], true)
2403 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2405 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2406 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2409 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
2410 %{remote_user: remote_user} do
2411 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2412 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2415 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
2416 %{remote_user: remote_user, local_user: local_user} do
2417 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2418 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
2421 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
2422 %{remote_user: remote_user} do
2423 clear_config([:instance, :limit_to_local_content], true)
2424 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2427 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
2428 %{local_user: local_user} do
2429 clear_config([:instance, :limit_to_local_content], false)
2430 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2432 clear_config([:instance, :limit_to_local_content], true)
2433 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2435 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2436 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2440 describe "update_email_notifications/2" do
2442 user = insert(:user, email_notifications: %{"digest" => true})
2447 test "Notifications are updated", %{user: user} do
2448 true = user.email_notifications["digest"]
2449 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
2450 assert result.email_notifications["digest"] == false
2454 describe "local_nickname/1" do
2455 test "returns nickname without host" do
2456 assert User.local_nickname("@mentioned") == "mentioned"
2457 assert User.local_nickname("a_local_nickname") == "a_local_nickname"
2458 assert User.local_nickname("nickname@host.com") == "nickname"
2462 describe "full_nickname/1" do
2463 test "returns fully qualified nickname for local and remote users" do
2465 insert(:user, nickname: "local_user", ap_id: "https://somehost.com/users/local_user")
2467 remote_user = insert(:user, nickname: "remote@host.com", local: false)
2469 assert User.full_nickname(local_user) == "local_user@somehost.com"
2470 assert User.full_nickname(remote_user) == "remote@host.com"
2473 test "strips leading @ from mentions" do
2474 assert User.full_nickname("@mentioned") == "mentioned"
2475 assert User.full_nickname("@nickname@host.com") == "nickname@host.com"
2478 test "does not modify nicknames" do
2479 assert User.full_nickname("nickname") == "nickname"
2480 assert User.full_nickname("nickname@host.com") == "nickname@host.com"
2484 test "avatar fallback" do
2485 user = insert(:user)
2486 assert User.avatar_url(user) =~ "/images/avi.png"
2488 clear_config([:assets, :default_user_avatar], "avatar.png")
2490 user = User.get_cached_by_nickname_or_id(user.nickname)
2491 assert User.avatar_url(user) =~ "avatar.png"
2493 assert User.avatar_url(user, no_default: true) == nil
2496 test "get_host/1" do
2497 user = insert(:user, ap_id: "https://lain.com/users/lain", nickname: "lain")
2498 assert User.get_host(user) == "lain.com"
2501 test "update_last_active_at/1" do
2502 user = insert(:user)
2503 assert is_nil(user.last_active_at)
2505 test_started_at = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
2507 assert {:ok, user} = User.update_last_active_at(user)
2509 assert user.last_active_at >= test_started_at
2510 assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
2513 NaiveDateTime.utc_now()
2514 |> NaiveDateTime.add(-:timer.hours(24), :millisecond)
2515 |> NaiveDateTime.truncate(:second)
2517 assert {:ok, user} =
2519 |> cast(%{last_active_at: last_active_at}, [:last_active_at])
2520 |> User.update_and_set_cache()
2522 assert user.last_active_at == last_active_at
2523 assert {:ok, user} = User.update_last_active_at(user)
2524 assert user.last_active_at >= test_started_at
2525 assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
2528 test "active_user_count/1" do
2530 insert(:user, %{local: false})
2531 insert(:user, %{last_active_at: NaiveDateTime.utc_now()})
2532 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), days: -15)})
2533 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), weeks: -6)})
2534 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), months: -7)})
2535 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), years: -2)})
2537 assert User.active_user_count() == 2
2538 assert User.active_user_count(180) == 3
2539 assert User.active_user_count(365) == 4
2540 assert User.active_user_count(1000) == 5
2545 user = insert(:user)
2547 [user: user, object_id: object_id_from_created_activity(user)]
2550 test "unique pins", %{user: user, object_id: object_id} do
2551 assert {:ok, %{pinned_objects: %{^object_id => pinned_at1} = pins} = updated_user} =
2552 User.add_pinned_object_id(user, object_id)
2554 assert Enum.count(pins) == 1
2556 assert {:ok, %{pinned_objects: %{^object_id => pinned_at2} = pins}} =
2557 User.add_pinned_object_id(updated_user, object_id)
2559 assert pinned_at1 == pinned_at2
2561 assert Enum.count(pins) == 1
2564 test "respects max_pinned_statuses limit", %{user: user, object_id: object_id} do
2565 clear_config([:instance, :max_pinned_statuses], 1)
2566 {:ok, updated} = User.add_pinned_object_id(user, object_id)
2568 object_id2 = object_id_from_created_activity(user)
2570 {:error, %{errors: errors}} = User.add_pinned_object_id(updated, object_id2)
2571 assert Keyword.has_key?(errors, :pinned_objects)
2574 test "remove_pinned_object_id/2", %{user: user, object_id: object_id} do
2575 assert {:ok, updated} = User.add_pinned_object_id(user, object_id)
2577 {:ok, after_remove} = User.remove_pinned_object_id(updated, object_id)
2578 assert after_remove.pinned_objects == %{}
2582 defp object_id_from_created_activity(user) do
2583 %{id: id} = insert(:note_activity, user: user)
2584 %{object: %{data: %{"id" => object_id}}} = Activity.get_by_id_with_object(id)
2588 describe "add_alias/2" do
2589 test "should add alias for another user" do
2590 user = insert(:user)
2591 user2 = insert(:user)
2593 assert {:ok, user_updated} = user |> User.add_alias(user2)
2595 assert user_updated.also_known_as |> length() == 1
2596 assert user2.ap_id in user_updated.also_known_as
2599 test "should add multiple aliases" do
2600 user = insert(:user)
2601 user2 = insert(:user)
2602 user3 = insert(:user)
2604 assert {:ok, user} = user |> User.add_alias(user2)
2605 assert {:ok, user_updated} = user |> User.add_alias(user3)
2607 assert user_updated.also_known_as |> length() == 2
2608 assert user2.ap_id in user_updated.also_known_as
2609 assert user3.ap_id in user_updated.also_known_as
2612 test "should not add duplicate aliases" do
2613 user = insert(:user)
2614 user2 = insert(:user)
2616 assert {:ok, user} = user |> User.add_alias(user2)
2618 assert {:ok, user_updated} = user |> User.add_alias(user2)
2620 assert user_updated.also_known_as |> length() == 1
2621 assert user2.ap_id in user_updated.also_known_as
2625 describe "alias_users/1" do
2626 test "should get aliases for a user" do
2627 user = insert(:user)
2628 user2 = insert(:user, also_known_as: [user.ap_id])
2630 aliases = user2 |> User.alias_users()
2632 assert aliases |> length() == 1
2634 alias_user = aliases |> Enum.at(0)
2636 assert alias_user.ap_id == user.ap_id
2640 describe "delete_alias/2" do
2641 test "should delete existing alias" do
2642 user = insert(:user)
2643 user2 = insert(:user, also_known_as: [user.ap_id])
2645 assert {:ok, user_updated} = user2 |> User.delete_alias(user)
2647 assert user_updated.also_known_as == []
2650 test "should report error on non-existing alias" do
2651 user = insert(:user)
2652 user2 = insert(:user)
2653 user3 = insert(:user, also_known_as: [user.ap_id])
2655 assert {:error, :no_such_alias} = user3 |> User.delete_alias(user2)
2657 user3_updated = User.get_cached_by_ap_id(user3.ap_id)
2659 assert user3_updated.also_known_as |> length() == 1
2660 assert user.ap_id in user3_updated.also_known_as