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
446 test "it sends a welcome chat message if it is set" do
447 welcome_user = insert(:user)
448 clear_config([:welcome, :chat_message, :enabled], true)
449 clear_config([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
450 clear_config([:welcome, :chat_message, :message], "Hello, this is a chat message")
452 cng = User.register_changeset(%User{}, @full_user_data)
453 {:ok, registered_user} = User.register(cng)
454 ObanHelpers.perform_all()
456 activity = Repo.one(Pleroma.Activity)
457 assert registered_user.ap_id in activity.recipients
458 assert Object.normalize(activity, fetch: false).data["content"] =~ "chat message"
459 assert activity.actor == welcome_user.ap_id
463 clear_config(:mrf_simple,
466 federated_timeline_removal: [],
479 Pleroma.Web.ActivityPub.MRF.SimplePolicy
483 test "it sends a welcome chat message when Simple policy applied to local instance" do
484 clear_config([:mrf_simple, :media_nsfw], [{"localhost", ""}])
486 welcome_user = insert(:user)
487 clear_config([:welcome, :chat_message, :enabled], true)
488 clear_config([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
489 clear_config([:welcome, :chat_message, :message], "Hello, this is a chat message")
491 cng = User.register_changeset(%User{}, @full_user_data)
492 {:ok, registered_user} = User.register(cng)
493 ObanHelpers.perform_all()
495 activity = Repo.one(Pleroma.Activity)
496 assert registered_user.ap_id in activity.recipients
497 assert Object.normalize(activity, fetch: false).data["content"] =~ "chat message"
498 assert activity.actor == welcome_user.ap_id
501 test "it sends a welcome email message if it is set" do
502 welcome_user = insert(:user)
503 clear_config([:welcome, :email, :enabled], true)
504 clear_config([:welcome, :email, :sender], welcome_user.email)
507 [:welcome, :email, :subject],
508 "Hello, welcome to cool site: <%= instance_name %>"
511 instance_name = Pleroma.Config.get([:instance, :name])
513 cng = User.register_changeset(%User{}, @full_user_data)
514 {:ok, registered_user} = User.register(cng)
515 ObanHelpers.perform_all()
518 from: {instance_name, welcome_user.email},
519 to: {registered_user.name, registered_user.email},
520 subject: "Hello, welcome to cool site: #{instance_name}",
521 html_body: "Welcome to #{instance_name}"
525 test "it sends a confirm email" do
526 clear_config([:instance, :account_activation_required], true)
528 cng = User.register_changeset(%User{}, @full_user_data)
529 {:ok, registered_user} = User.register(cng)
530 ObanHelpers.perform_all()
532 Pleroma.Emails.UserEmail.account_confirmation_email(registered_user)
533 # temporary hackney fix until hackney max_connections bug is fixed
534 # https://git.pleroma.social/pleroma/pleroma/-/issues/2101
535 |> Swoosh.Email.put_private(:hackney_options, ssl_options: [versions: [:"tlsv1.2"]])
536 |> assert_email_sent()
539 test "sends a pending approval email" do
540 clear_config([:instance, :account_approval_required], true)
543 User.register_changeset(%User{}, @full_user_data)
546 ObanHelpers.perform_all()
549 from: Pleroma.Config.Helpers.sender(),
550 to: {user.name, user.email},
551 subject: "Your account is awaiting approval"
555 test "it sends a registration confirmed email if no others will be sent" do
556 clear_config([:welcome, :email, :enabled], false)
557 clear_config([:instance, :account_activation_required], false)
558 clear_config([:instance, :account_approval_required], false)
561 User.register_changeset(%User{}, @full_user_data)
564 ObanHelpers.perform_all()
566 instance_name = Pleroma.Config.get([:instance, :name])
567 sender = Pleroma.Config.get([:instance, :notify_email])
570 from: {instance_name, sender},
571 to: {user.name, user.email},
572 subject: "Account registered on #{instance_name}"
576 test "it fails gracefully with invalid email config" do
577 cng = User.register_changeset(%User{}, @full_user_data)
579 # Disable the mailer but enable all the things that want to send emails
580 clear_config([Pleroma.Emails.Mailer, :enabled], false)
581 clear_config([:instance, :account_activation_required], true)
582 clear_config([:instance, :account_approval_required], true)
583 clear_config([:welcome, :email, :enabled], true)
584 clear_config([:welcome, :email, :sender], "lain@lain.com")
586 # The user is still created
587 assert {:ok, %User{nickname: "nick"}} = User.register(cng)
590 ObanHelpers.perform_all()
594 test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do
595 clear_config([:instance, :account_activation_required], true)
599 |> Enum.each(fn key ->
600 params = Map.delete(@full_user_data, key)
601 changeset = User.register_changeset(%User{}, params)
603 assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
607 test "it requires an name, nickname and password, bio and email are optional when account_activation_required is disabled" do
608 clear_config([:instance, :account_activation_required], false)
612 |> Enum.each(fn key ->
613 params = Map.delete(@full_user_data, key)
614 changeset = User.register_changeset(%User{}, params)
616 assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid?
620 test "it restricts certain nicknames" do
621 [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
623 assert is_bitstring(restricted_name)
627 |> Map.put(:nickname, restricted_name)
629 changeset = User.register_changeset(%User{}, params)
631 refute changeset.valid?
634 test "it blocks blacklisted email domains" do
635 clear_config([User, :email_blacklist], ["trolling.world"])
638 params = Map.put(@full_user_data, :email, "troll@trolling.world")
639 changeset = User.register_changeset(%User{}, params)
640 refute changeset.valid?
642 # Block with subdomain match
643 params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world")
644 changeset = User.register_changeset(%User{}, params)
645 refute changeset.valid?
647 # Pass with different domains that are similar
648 params = Map.put(@full_user_data, :email, "troll@gnomestrolling.world")
649 changeset = User.register_changeset(%User{}, params)
650 assert changeset.valid?
652 params = Map.put(@full_user_data, :email, "troll@trolling.world.us")
653 changeset = User.register_changeset(%User{}, params)
654 assert changeset.valid?
657 test "it sets the password_hash and ap_id" do
658 changeset = User.register_changeset(%User{}, @full_user_data)
660 assert changeset.valid?
662 assert is_binary(changeset.changes[:password_hash])
663 assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
665 assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
668 test "it sets the 'accepts_chat_messages' set to true" do
669 changeset = User.register_changeset(%User{}, @full_user_data)
670 assert changeset.valid?
672 {:ok, user} = Repo.insert(changeset)
674 assert user.accepts_chat_messages
677 test "it creates a confirmed user" do
678 changeset = User.register_changeset(%User{}, @full_user_data)
679 assert changeset.valid?
681 {:ok, user} = Repo.insert(changeset)
683 assert user.is_confirmed
687 describe "user registration, with :account_activation_required" do
693 password_confirmation: "test",
694 email: "email@example.com"
696 setup do: clear_config([:instance, :account_activation_required], true)
698 test "it creates unconfirmed user" do
699 changeset = User.register_changeset(%User{}, @full_user_data)
700 assert changeset.valid?
702 {:ok, user} = Repo.insert(changeset)
704 refute user.is_confirmed
705 assert user.confirmation_token
708 test "it creates confirmed user if :confirmed option is given" do
709 changeset = User.register_changeset(%User{}, @full_user_data, confirmed: true)
710 assert changeset.valid?
712 {:ok, user} = Repo.insert(changeset)
714 assert user.is_confirmed
715 refute user.confirmation_token
719 describe "user registration, with :account_approval_required" do
725 password_confirmation: "test",
726 email: "email@example.com",
727 registration_reason: "I'm a cool guy :)"
729 setup do: clear_config([:instance, :account_approval_required], true)
731 test "it creates unapproved user" do
732 changeset = User.register_changeset(%User{}, @full_user_data)
733 assert changeset.valid?
735 {:ok, user} = Repo.insert(changeset)
737 refute user.is_approved
738 assert user.registration_reason == "I'm a cool guy :)"
741 test "it restricts length of registration reason" do
742 reason_limit = Pleroma.Config.get([:instance, :registration_reason_length])
744 assert is_integer(reason_limit)
749 :registration_reason,
750 "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."
753 changeset = User.register_changeset(%User{}, params)
755 refute changeset.valid?
759 describe "get_or_fetch/1" do
760 test "gets an existing user by nickname" do
762 {:ok, fetched_user} = User.get_or_fetch(user.nickname)
764 assert user == fetched_user
767 test "gets an existing user by ap_id" do
768 ap_id = "http://mastodon.example.org/users/admin"
774 nickname: "admin@mastodon.example.org",
778 {:ok, fetched_user} = User.get_or_fetch(ap_id)
779 freshed_user = refresh_record(user)
780 assert freshed_user == fetched_user
784 describe "fetching a user from nickname or trying to build one" do
785 test "gets an existing user" do
787 {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
789 assert user == fetched_user
792 test "gets an existing user, case insensitive" do
793 user = insert(:user, nickname: "nick")
794 {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
796 assert user == fetched_user
799 test "gets an existing user by fully qualified nickname" do
802 {:ok, fetched_user} =
803 User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
805 assert user == fetched_user
808 test "gets an existing user by fully qualified nickname, case insensitive" do
809 user = insert(:user, nickname: "nick")
810 casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
812 {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
814 assert user == fetched_user
817 @tag capture_log: true
818 test "returns nil if no user could be fetched" do
819 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
820 assert fetched_user == "not found nonexistant@social.heldscal.la"
823 test "returns nil for nonexistant local user" do
824 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
825 assert fetched_user == "not found nonexistant"
828 test "updates an existing user, if stale" do
829 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
835 nickname: "admin@mastodon.example.org",
836 ap_id: "http://mastodon.example.org/users/admin",
837 last_refreshed_at: a_week_ago
840 assert orig_user.last_refreshed_at == a_week_ago
842 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
846 refute user.last_refreshed_at == orig_user.last_refreshed_at
849 test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
850 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
856 nickname: "admin@mastodon.example.org",
857 ap_id: "http://mastodon.example.org/users/harinezumigari",
858 last_refreshed_at: a_week_ago
861 assert orig_user.last_refreshed_at == a_week_ago
863 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
867 refute user.id == orig_user.id
869 orig_user = User.get_by_id(orig_user.id)
871 assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
874 @tag capture_log: true
875 test "it returns the old user if stale, but unfetchable" do
876 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
882 nickname: "admin@mastodon.example.org",
883 ap_id: "http://mastodon.example.org/users/raymoo",
884 last_refreshed_at: a_week_ago
887 assert orig_user.last_refreshed_at == a_week_ago
889 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/raymoo")
891 assert user.last_refreshed_at == orig_user.last_refreshed_at
895 test "returns an ap_id for a user" do
898 assert User.ap_id(user) ==
899 Pleroma.Web.Router.Helpers.user_feed_url(
900 Pleroma.Web.Endpoint,
906 test "returns an ap_followers link for a user" do
909 assert User.ap_followers(user) ==
910 Pleroma.Web.Router.Helpers.user_feed_url(
911 Pleroma.Web.Endpoint,
917 describe "remote user changeset" do
923 avatar: %{some: "avatar"}
925 setup do: clear_config([:instance, :user_bio_length])
926 setup do: clear_config([:instance, :user_name_length])
928 test "it confirms validity" do
929 cs = User.remote_user_changeset(@valid_remote)
933 test "it sets the follower_adress" do
934 cs = User.remote_user_changeset(@valid_remote)
935 # remote users get a fake local follower address
936 assert cs.changes.follower_address ==
937 User.ap_followers(%User{nickname: @valid_remote[:nickname]})
940 test "it enforces the fqn format for nicknames" do
941 cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})
942 assert Ecto.Changeset.get_field(cs, :local) == false
943 assert cs.changes.avatar
947 test "it has required fields" do
949 |> Enum.each(fn field ->
950 cs = User.remote_user_changeset(Map.delete(@valid_remote, field))
955 test "it is invalid given a local user" do
957 cs = User.remote_user_changeset(user, %{name: "tom from myspace"})
963 describe "followers and friends" do
964 test "gets all followers for a given user" do
966 follower_one = insert(:user)
967 follower_two = insert(:user)
968 not_follower = insert(:user)
970 {:ok, follower_one, user} = User.follow(follower_one, user)
971 {:ok, follower_two, user} = User.follow(follower_two, user)
973 res = User.get_followers(user)
975 assert Enum.member?(res, follower_one)
976 assert Enum.member?(res, follower_two)
977 refute Enum.member?(res, not_follower)
980 test "gets all friends (followed users) for a given user" do
982 followed_one = insert(:user)
983 followed_two = insert(:user)
984 not_followed = insert(:user)
986 {:ok, user, followed_one} = User.follow(user, followed_one)
987 {:ok, user, followed_two} = User.follow(user, followed_two)
989 res = User.get_friends(user)
991 followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
992 followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
993 assert Enum.member?(res, followed_one)
994 assert Enum.member?(res, followed_two)
995 refute Enum.member?(res, not_followed)
999 describe "updating note and follower count" do
1000 test "it sets the note_count property" do
1001 note = insert(:note)
1003 user = User.get_cached_by_ap_id(note.data["actor"])
1005 assert user.note_count == 0
1007 {:ok, user} = User.update_note_count(user)
1009 assert user.note_count == 1
1012 test "it increases the note_count property" do
1013 note = insert(:note)
1014 user = User.get_cached_by_ap_id(note.data["actor"])
1016 assert user.note_count == 0
1018 {:ok, user} = User.increase_note_count(user)
1020 assert user.note_count == 1
1022 {:ok, user} = User.increase_note_count(user)
1024 assert user.note_count == 2
1027 test "it decreases the note_count property" do
1028 note = insert(:note)
1029 user = User.get_cached_by_ap_id(note.data["actor"])
1031 assert user.note_count == 0
1033 {:ok, user} = User.increase_note_count(user)
1035 assert user.note_count == 1
1037 {:ok, user} = User.decrease_note_count(user)
1039 assert user.note_count == 0
1041 {:ok, user} = User.decrease_note_count(user)
1043 assert user.note_count == 0
1046 test "it sets the follower_count property" do
1047 user = insert(:user)
1048 follower = insert(:user)
1050 User.follow(follower, user)
1052 assert user.follower_count == 0
1054 {:ok, user} = User.update_follower_count(user)
1056 assert user.follower_count == 1
1061 test "it mutes people" do
1062 user = insert(:user)
1063 muted_user = insert(:user)
1065 refute User.mutes?(user, muted_user)
1066 refute User.muted_notifications?(user, muted_user)
1068 {:ok, _user_relationships} = User.mute(user, muted_user)
1070 assert User.mutes?(user, muted_user)
1071 assert User.muted_notifications?(user, muted_user)
1075 user = insert(:user)
1076 muted_user = insert(:user)
1078 {:ok, _user_relationships} = User.mute(user, muted_user, %{expires_in: 60})
1079 assert User.mutes?(user, muted_user)
1081 worker = Pleroma.Workers.MuteExpireWorker
1082 args = %{"op" => "unmute_user", "muter_id" => user.id, "mutee_id" => muted_user.id}
1089 assert :ok = perform_job(worker, args)
1091 refute User.mutes?(user, muted_user)
1092 refute User.muted_notifications?(user, muted_user)
1095 test "it unmutes users" do
1096 user = insert(:user)
1097 muted_user = insert(:user)
1099 {:ok, _user_relationships} = User.mute(user, muted_user)
1100 {:ok, _user_mute} = User.unmute(user, muted_user)
1102 refute User.mutes?(user, muted_user)
1103 refute User.muted_notifications?(user, muted_user)
1106 test "it unmutes users by id" do
1107 user = insert(:user)
1108 muted_user = insert(:user)
1110 {:ok, _user_relationships} = User.mute(user, muted_user)
1111 {:ok, _user_mute} = User.unmute(user.id, muted_user.id)
1113 refute User.mutes?(user, muted_user)
1114 refute User.muted_notifications?(user, muted_user)
1117 test "it mutes user without notifications" do
1118 user = insert(:user)
1119 muted_user = insert(:user)
1121 refute User.mutes?(user, muted_user)
1122 refute User.muted_notifications?(user, muted_user)
1124 {:ok, _user_relationships} = User.mute(user, muted_user, %{notifications: false})
1126 assert User.mutes?(user, muted_user)
1127 refute User.muted_notifications?(user, muted_user)
1131 describe "blocks" do
1132 test "it blocks people" do
1133 user = insert(:user)
1134 blocked_user = insert(:user)
1136 refute User.blocks?(user, blocked_user)
1138 {:ok, _user_relationship} = User.block(user, blocked_user)
1140 assert User.blocks?(user, blocked_user)
1143 test "it unblocks users" do
1144 user = insert(:user)
1145 blocked_user = insert(:user)
1147 {:ok, _user_relationship} = User.block(user, blocked_user)
1148 {:ok, _user_block} = User.unblock(user, blocked_user)
1150 refute User.blocks?(user, blocked_user)
1153 test "blocks tear down cyclical follow relationships" do
1154 blocker = insert(:user)
1155 blocked = insert(:user)
1157 {:ok, blocker, blocked} = User.follow(blocker, blocked)
1158 {:ok, blocked, blocker} = User.follow(blocked, blocker)
1160 assert User.following?(blocker, blocked)
1161 assert User.following?(blocked, blocker)
1163 {:ok, _user_relationship} = User.block(blocker, blocked)
1164 blocked = User.get_cached_by_id(blocked.id)
1166 assert User.blocks?(blocker, blocked)
1168 refute User.following?(blocker, blocked)
1169 refute User.following?(blocked, blocker)
1172 test "blocks tear down blocker->blocked follow relationships" do
1173 blocker = insert(:user)
1174 blocked = insert(:user)
1176 {:ok, blocker, blocked} = User.follow(blocker, blocked)
1178 assert User.following?(blocker, blocked)
1179 refute User.following?(blocked, blocker)
1181 {:ok, _user_relationship} = User.block(blocker, blocked)
1182 blocked = User.get_cached_by_id(blocked.id)
1184 assert User.blocks?(blocker, blocked)
1186 refute User.following?(blocker, blocked)
1187 refute User.following?(blocked, blocker)
1190 test "blocks tear down blocked->blocker follow relationships" do
1191 blocker = insert(:user)
1192 blocked = insert(:user)
1194 {:ok, blocked, blocker} = User.follow(blocked, blocker)
1196 refute User.following?(blocker, blocked)
1197 assert User.following?(blocked, blocker)
1199 {:ok, _user_relationship} = User.block(blocker, blocked)
1200 blocked = User.get_cached_by_id(blocked.id)
1202 assert User.blocks?(blocker, blocked)
1204 refute User.following?(blocker, blocked)
1205 refute User.following?(blocked, blocker)
1208 test "blocks tear down blocked->blocker subscription relationships" do
1209 blocker = insert(:user)
1210 blocked = insert(:user)
1212 {:ok, _subscription} = User.subscribe(blocked, blocker)
1214 assert User.subscribed_to?(blocked, blocker)
1215 refute User.subscribed_to?(blocker, blocked)
1217 {:ok, _user_relationship} = User.block(blocker, blocked)
1219 assert User.blocks?(blocker, blocked)
1220 refute User.subscribed_to?(blocker, blocked)
1221 refute User.subscribed_to?(blocked, blocker)
1225 describe "domain blocking" do
1226 test "blocks domains" do
1227 user = insert(:user)
1228 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1230 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1232 assert User.blocks?(user, collateral_user)
1235 test "does not block domain with same end" do
1236 user = insert(:user)
1239 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1241 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1243 refute User.blocks?(user, collateral_user)
1246 test "does not block domain with same end if wildcard added" do
1247 user = insert(:user)
1250 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1252 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1254 refute User.blocks?(user, collateral_user)
1257 test "blocks domain with wildcard for subdomain" do
1258 user = insert(:user)
1260 user_from_subdomain =
1261 insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
1263 user_with_two_subdomains =
1265 ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
1268 user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1270 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1272 assert User.blocks?(user, user_from_subdomain)
1273 assert User.blocks?(user, user_with_two_subdomains)
1274 assert User.blocks?(user, user_domain)
1277 test "unblocks domains" do
1278 user = insert(:user)
1279 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1281 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1282 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
1284 refute User.blocks?(user, collateral_user)
1287 test "follows take precedence over domain blocks" do
1288 user = insert(:user)
1289 good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
1291 {:ok, user} = User.block_domain(user, "meanies.social")
1292 {:ok, user, good_eggo} = User.follow(user, good_eggo)
1294 refute User.blocks?(user, good_eggo)
1298 describe "get_recipients_from_activity" do
1299 test "works for announces" do
1300 actor = insert(:user)
1301 user = insert(:user, local: true)
1303 {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
1304 {:ok, announce} = CommonAPI.repeat(activity.id, user)
1306 recipients = User.get_recipients_from_activity(announce)
1308 assert user in recipients
1311 test "get recipients" do
1312 actor = insert(:user)
1313 user = insert(:user, local: true)
1314 user_two = insert(:user, local: false)
1315 addressed = insert(:user, local: true)
1316 addressed_remote = insert(:user, local: false)
1319 CommonAPI.post(actor, %{
1320 status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
1323 assert Enum.map([actor, addressed], & &1.ap_id) --
1324 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1326 {:ok, user, actor} = User.follow(user, actor)
1327 {:ok, _user_two, _actor} = User.follow(user_two, actor)
1328 recipients = User.get_recipients_from_activity(activity)
1329 assert length(recipients) == 3
1330 assert user in recipients
1331 assert addressed in recipients
1334 test "has following" do
1335 actor = insert(:user)
1336 user = insert(:user)
1337 user_two = insert(:user)
1338 addressed = insert(:user, local: true)
1341 CommonAPI.post(actor, %{
1342 status: "hey @#{addressed.nickname}"
1345 assert Enum.map([actor, addressed], & &1.ap_id) --
1346 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1348 {:ok, _actor, _user} = User.follow(actor, user)
1349 {:ok, _actor, _user_two} = User.follow(actor, user_two)
1350 recipients = User.get_recipients_from_activity(activity)
1351 assert length(recipients) == 2
1352 assert addressed in recipients
1356 describe ".set_activation" do
1357 test "can de-activate then re-activate a user" do
1358 user = insert(:user)
1359 assert user.is_active
1360 {:ok, user} = User.set_activation(user, false)
1361 refute user.is_active
1362 {:ok, user} = User.set_activation(user, true)
1363 assert user.is_active
1366 test "hide a user from followers" do
1367 user = insert(:user)
1368 user2 = insert(:user)
1370 {:ok, user, user2} = User.follow(user, user2)
1371 {:ok, _user} = User.set_activation(user, false)
1373 user2 = User.get_cached_by_id(user2.id)
1375 assert user2.follower_count == 0
1376 assert [] = User.get_followers(user2)
1379 test "hide a user from friends" do
1380 user = insert(:user)
1381 user2 = insert(:user)
1383 {:ok, user2, user} = User.follow(user2, user)
1384 assert user2.following_count == 1
1385 assert User.following_count(user2) == 1
1387 {:ok, _user} = User.set_activation(user, false)
1389 user2 = User.get_cached_by_id(user2.id)
1391 assert refresh_record(user2).following_count == 0
1392 assert user2.following_count == 0
1393 assert User.following_count(user2) == 0
1394 assert [] = User.get_friends(user2)
1397 test "hide a user's statuses from timelines and notifications" do
1398 user = insert(:user)
1399 user2 = insert(:user)
1401 {:ok, user2, user} = User.follow(user2, user)
1403 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
1405 activity = Repo.preload(activity, :bookmark)
1407 [notification] = Pleroma.Notification.for_user(user2)
1408 assert notification.activity.id == activity.id
1410 assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
1412 assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
1413 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1417 {:ok, _user} = User.set_activation(user, false)
1419 assert [] == ActivityPub.fetch_public_activities(%{})
1420 assert [] == Pleroma.Notification.for_user(user2)
1423 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1429 describe "approve" do
1430 test "approves a user" do
1431 user = insert(:user, is_approved: false)
1432 refute user.is_approved
1433 {:ok, user} = User.approve(user)
1434 assert user.is_approved
1437 test "approves a list of users" do
1438 unapproved_users = [
1439 insert(:user, is_approved: false),
1440 insert(:user, is_approved: false),
1441 insert(:user, is_approved: false)
1444 {:ok, users} = User.approve(unapproved_users)
1446 assert Enum.count(users) == 3
1448 Enum.each(users, fn user ->
1449 assert user.is_approved
1453 test "it sends welcome email if it is set" do
1454 clear_config([:welcome, :email, :enabled], true)
1455 clear_config([:welcome, :email, :sender], "tester@test.me")
1457 user = insert(:user, is_approved: false)
1458 welcome_user = insert(:user, email: "tester@test.me")
1459 instance_name = Pleroma.Config.get([:instance, :name])
1463 ObanHelpers.perform_all()
1466 from: {instance_name, welcome_user.email},
1467 to: {user.name, user.email},
1468 html_body: "Welcome to #{instance_name}"
1472 test "approving an approved user does not trigger post-register actions" do
1473 clear_config([:welcome, :email, :enabled], true)
1475 user = insert(:user, is_approved: true)
1478 ObanHelpers.perform_all()
1480 assert_no_email_sent()
1484 describe "confirm" do
1485 test "confirms a user" do
1486 user = insert(:user, is_confirmed: false)
1487 refute user.is_confirmed
1488 {:ok, user} = User.confirm(user)
1489 assert user.is_confirmed
1492 test "confirms a list of users" do
1493 unconfirmed_users = [
1494 insert(:user, is_confirmed: false),
1495 insert(:user, is_confirmed: false),
1496 insert(:user, is_confirmed: false)
1499 {:ok, users} = User.confirm(unconfirmed_users)
1501 assert Enum.count(users) == 3
1503 Enum.each(users, fn user ->
1504 assert user.is_confirmed
1508 test "sends approval emails when `is_approved: false`" do
1509 admin = insert(:user, is_admin: true)
1510 user = insert(:user, is_confirmed: false, is_approved: false)
1513 ObanHelpers.perform_all()
1515 user_email = Pleroma.Emails.UserEmail.approval_pending_email(user)
1516 admin_email = Pleroma.Emails.AdminEmail.new_unapproved_registration(admin, user)
1518 notify_email = Pleroma.Config.get([:instance, :notify_email])
1519 instance_name = Pleroma.Config.get([:instance, :name])
1521 # User approval email
1523 from: {instance_name, notify_email},
1524 to: {user.name, user.email},
1525 html_body: user_email.html_body
1530 from: {instance_name, notify_email},
1531 to: {admin.name, admin.email},
1532 html_body: admin_email.html_body
1536 test "confirming a confirmed user does not trigger post-register actions" do
1537 user = insert(:user, is_confirmed: true, is_approved: false)
1540 ObanHelpers.perform_all()
1542 assert_no_email_sent()
1546 describe "delete" do
1548 {:ok, user} = insert(:user) |> User.set_cache()
1553 setup do: clear_config([:instance, :federating])
1555 test ".delete_user_activities deletes all create activities", %{user: user} do
1556 {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
1558 User.delete_user_activities(user)
1560 # TODO: Test removal favorites, repeats, delete activities.
1561 refute Activity.get_by_id(activity.id)
1564 test "it deactivates a user, all follow relationships and all activities", %{user: user} do
1565 follower = insert(:user)
1566 {:ok, follower, user} = User.follow(follower, user)
1568 locked_user = insert(:user, name: "locked", is_locked: true)
1569 {:ok, _, _} = User.follow(user, locked_user, :follow_pending)
1571 object = insert(:note, user: user)
1572 activity = insert(:note_activity, user: user, note: object)
1574 object_two = insert(:note, user: follower)
1575 activity_two = insert(:note_activity, user: follower, note: object_two)
1577 {:ok, like} = CommonAPI.favorite(user, activity_two.id)
1578 {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
1579 {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
1581 {:ok, job} = User.delete(user)
1582 {:ok, _user} = ObanHelpers.perform(job)
1584 follower = User.get_cached_by_id(follower.id)
1586 refute User.following?(follower, user)
1587 assert %{is_active: false} = User.get_by_id(user.id)
1589 assert [] == User.get_follow_requests(locked_user)
1593 |> Activity.Queries.by_actor()
1595 |> Enum.map(fn act -> act.data["type"] end)
1597 assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
1599 refute Activity.get_by_id(activity.id)
1600 refute Activity.get_by_id(like.id)
1601 refute Activity.get_by_id(like_two.id)
1602 refute Activity.get_by_id(repeat.id)
1606 test "delete/1 when confirmation is pending deletes the user" do
1607 clear_config([:instance, :account_activation_required], true)
1608 user = insert(:user, is_confirmed: false)
1610 {:ok, job} = User.delete(user)
1611 {:ok, _} = ObanHelpers.perform(job)
1613 refute User.get_cached_by_id(user.id)
1614 refute User.get_by_id(user.id)
1617 test "delete/1 when approval is pending deletes the user" do
1618 user = insert(:user, is_approved: false)
1620 {:ok, job} = User.delete(user)
1621 {:ok, _} = ObanHelpers.perform(job)
1623 refute User.get_cached_by_id(user.id)
1624 refute User.get_by_id(user.id)
1627 test "delete/1 purges a user when they wouldn't be fully deleted" do
1632 password_hash: "pdfk2$1b3n159001",
1633 keys: "RSA begin buplic key",
1634 public_key: "--PRIVATE KEYE--",
1635 avatar: %{"a" => "b"},
1637 banner: %{"a" => "b"},
1638 background: %{"a" => "b"},
1641 following_count: 9001,
1644 password_reset_pending: true,
1646 registration_reason: "ahhhhh",
1647 confirmation_token: "qqqq",
1648 domain_blocks: ["lain.com"],
1653 mastofe_settings: %{"a" => "b"},
1654 mascot: %{"a" => "b"},
1655 emoji: %{"a" => "b"},
1656 pleroma_settings_store: %{"q" => "x"},
1657 fields: [%{"gg" => "qq"}],
1658 raw_fields: [%{"gg" => "qq"}],
1659 is_discoverable: true,
1660 also_known_as: ["https://lol.olo/users/loll"]
1663 {:ok, job} = User.delete(user)
1664 {:ok, _} = ObanHelpers.perform(job)
1665 user = User.get_by_id(user.id)
1673 keys: "RSA begin buplic key",
1674 public_key: "--PRIVATE KEYE--",
1677 last_refreshed_at: nil,
1678 last_digest_emailed_at: nil,
1686 password_reset_pending: false,
1688 registration_reason: nil,
1689 confirmation_token: nil,
1693 is_moderator: false,
1695 mastofe_settings: nil,
1698 pleroma_settings_store: %{},
1701 is_discoverable: false,
1706 test "delete/1 purges a remote user" do
1710 avatar: %{"a" => "b"},
1711 banner: %{"a" => "b"},
1715 {:ok, job} = User.delete(user)
1716 {:ok, _} = ObanHelpers.perform(job)
1717 user = User.get_by_id(user.id)
1719 assert user.name == nil
1720 assert user.avatar == %{}
1721 assert user.banner == %{}
1724 describe "set_suggestion" do
1725 test "suggests a user" do
1726 user = insert(:user, is_suggested: false)
1727 refute user.is_suggested
1728 {:ok, user} = User.set_suggestion(user, true)
1729 assert user.is_suggested
1732 test "suggests a list of users" do
1733 unsuggested_users = [
1734 insert(:user, is_suggested: false),
1735 insert(:user, is_suggested: false),
1736 insert(:user, is_suggested: false)
1739 {:ok, users} = User.set_suggestion(unsuggested_users, true)
1741 assert Enum.count(users) == 3
1743 Enum.each(users, fn user ->
1744 assert user.is_suggested
1748 test "unsuggests a user" do
1749 user = insert(:user, is_suggested: true)
1750 assert user.is_suggested
1751 {:ok, user} = User.set_suggestion(user, false)
1752 refute user.is_suggested
1756 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1757 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1760 describe "per-user rich-text filtering" do
1761 test "html_filter_policy returns default policies, when rich-text is enabled" do
1762 user = insert(:user)
1764 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1767 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1768 user = insert(:user, no_rich_text: true)
1770 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1774 describe "caching" do
1775 test "invalidate_cache works" do
1776 user = insert(:user)
1778 User.set_cache(user)
1779 User.invalidate_cache(user)
1781 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1782 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1785 test "User.delete() plugs any possible zombie objects" do
1786 user = insert(:user)
1788 {:ok, job} = User.delete(user)
1789 {:ok, _} = ObanHelpers.perform(job)
1791 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1793 assert cached_user != user
1795 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1797 assert cached_user != user
1801 describe "account_status/1" do
1802 setup do: clear_config([:instance, :account_activation_required])
1804 test "return confirmation_pending for unconfirm user" do
1805 clear_config([:instance, :account_activation_required], true)
1806 user = insert(:user, is_confirmed: false)
1807 assert User.account_status(user) == :confirmation_pending
1810 test "return active for confirmed user" do
1811 clear_config([:instance, :account_activation_required], true)
1812 user = insert(:user, is_confirmed: true)
1813 assert User.account_status(user) == :active
1816 test "return active for remote user" do
1817 user = insert(:user, local: false)
1818 assert User.account_status(user) == :active
1821 test "returns :password_reset_pending for user with reset password" do
1822 user = insert(:user, password_reset_pending: true)
1823 assert User.account_status(user) == :password_reset_pending
1826 test "returns :deactivated for deactivated user" do
1827 user = insert(:user, local: true, is_confirmed: true, is_active: false)
1828 assert User.account_status(user) == :deactivated
1831 test "returns :approval_pending for unapproved user" do
1832 user = insert(:user, local: true, is_approved: false)
1833 assert User.account_status(user) == :approval_pending
1835 user = insert(:user, local: true, is_confirmed: false, is_approved: false)
1836 assert User.account_status(user) == :approval_pending
1840 describe "superuser?/1" do
1841 test "returns false for unprivileged users" do
1842 user = insert(:user, local: true)
1844 refute User.superuser?(user)
1847 test "returns false for remote users" do
1848 user = insert(:user, local: false)
1849 remote_admin_user = insert(:user, local: false, is_admin: true)
1851 refute User.superuser?(user)
1852 refute User.superuser?(remote_admin_user)
1855 test "returns true for local moderators" do
1856 user = insert(:user, local: true, is_moderator: true)
1858 assert User.superuser?(user)
1861 test "returns true for local admins" do
1862 user = insert(:user, local: true, is_admin: true)
1864 assert User.superuser?(user)
1868 describe "invisible?/1" do
1869 test "returns true for an invisible user" do
1870 user = insert(:user, local: true, invisible: true)
1872 assert User.invisible?(user)
1875 test "returns false for a non-invisible user" do
1876 user = insert(:user, local: true)
1878 refute User.invisible?(user)
1882 describe "visible_for/2" do
1883 test "returns true when the account is itself" do
1884 user = insert(:user, local: true)
1886 assert User.visible_for(user, user) == :visible
1889 test "returns false when the account is unconfirmed and confirmation is required" do
1890 clear_config([:instance, :account_activation_required], true)
1892 user = insert(:user, local: true, is_confirmed: false)
1893 other_user = insert(:user, local: true)
1895 refute User.visible_for(user, other_user) == :visible
1898 test "returns true when the account is unconfirmed and confirmation is required but the account is remote" do
1899 clear_config([:instance, :account_activation_required], true)
1901 user = insert(:user, local: false, is_confirmed: false)
1902 other_user = insert(:user, local: true)
1904 assert User.visible_for(user, other_user) == :visible
1907 test "returns true when the account is unconfirmed and being viewed by a privileged account (confirmation required)" do
1908 clear_config([:instance, :account_activation_required], true)
1910 user = insert(:user, local: true, is_confirmed: false)
1911 other_user = insert(:user, local: true, is_admin: true)
1913 assert User.visible_for(user, other_user) == :visible
1917 describe "parse_bio/2" do
1918 test "preserves hosts in user links text" do
1919 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1920 user = insert(:user)
1921 bio = "A.k.a. @nick@domain.com"
1924 ~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>)
1926 assert expected_text == User.parse_bio(bio, user)
1929 test "Adds rel=me on linkbacked urls" do
1930 user = insert(:user, ap_id: "https://social.example.org/users/lain")
1932 bio = "http://example.com/rel_me/null"
1933 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1934 assert expected_text == User.parse_bio(bio, user)
1936 bio = "http://example.com/rel_me/link"
1937 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1938 assert expected_text == User.parse_bio(bio, user)
1940 bio = "http://example.com/rel_me/anchor"
1941 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1942 assert expected_text == User.parse_bio(bio, user)
1946 test "follower count is updated when a follower is blocked" do
1947 user = insert(:user)
1948 follower = insert(:user)
1949 follower2 = insert(:user)
1950 follower3 = insert(:user)
1952 {:ok, follower, user} = User.follow(follower, user)
1953 {:ok, _follower2, _user} = User.follow(follower2, user)
1954 {:ok, _follower3, _user} = User.follow(follower3, user)
1956 {:ok, _user_relationship} = User.block(user, follower)
1957 user = refresh_record(user)
1959 assert user.follower_count == 2
1962 describe "list_inactive_users_query/1" do
1963 defp days_ago(days) do
1965 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
1966 -days * 60 * 60 * 24,
1971 test "Users are inactive by default" do
1975 Enum.map(1..total, fn _ ->
1976 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
1979 inactive_users_ids =
1980 Pleroma.User.list_inactive_users_query()
1981 |> Pleroma.Repo.all()
1982 |> Enum.map(& &1.id)
1984 Enum.each(users, fn user ->
1985 assert user.id in inactive_users_ids
1989 test "Only includes users who has no recent activity" do
1993 Enum.map(1..total, fn _ ->
1994 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
1997 {inactive, active} = Enum.split(users, trunc(total / 2))
1999 Enum.map(active, fn user ->
2000 to = Enum.random(users -- [user])
2003 CommonAPI.post(user, %{
2004 status: "hey @#{to.nickname}"
2008 inactive_users_ids =
2009 Pleroma.User.list_inactive_users_query()
2010 |> Pleroma.Repo.all()
2011 |> Enum.map(& &1.id)
2013 Enum.each(active, fn user ->
2014 refute user.id in inactive_users_ids
2017 Enum.each(inactive, fn user ->
2018 assert user.id in inactive_users_ids
2022 test "Only includes users with no read notifications" do
2026 Enum.map(1..total, fn _ ->
2027 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
2030 [sender | recipients] = users
2031 {inactive, active} = Enum.split(recipients, trunc(total / 2))
2033 Enum.each(recipients, fn to ->
2035 CommonAPI.post(sender, %{
2036 status: "hey @#{to.nickname}"
2040 CommonAPI.post(sender, %{
2041 status: "hey again @#{to.nickname}"
2045 Enum.each(active, fn user ->
2046 [n1, _n2] = Pleroma.Notification.for_user(user)
2047 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
2050 inactive_users_ids =
2051 Pleroma.User.list_inactive_users_query()
2052 |> Pleroma.Repo.all()
2053 |> Enum.map(& &1.id)
2055 Enum.each(active, fn user ->
2056 refute user.id in inactive_users_ids
2059 Enum.each(inactive, fn user ->
2060 assert user.id in inactive_users_ids
2065 describe "ensure_keys_present" do
2066 test "it creates keys for a user and stores them in info" do
2067 user = insert(:user)
2068 refute is_binary(user.keys)
2069 {:ok, user} = User.ensure_keys_present(user)
2070 assert is_binary(user.keys)
2073 test "it doesn't create keys if there already are some" do
2074 user = insert(:user, keys: "xxx")
2075 {:ok, user} = User.ensure_keys_present(user)
2076 assert user.keys == "xxx"
2080 describe "get_ap_ids_by_nicknames" do
2081 test "it returns a list of AP ids for a given set of nicknames" do
2082 user = insert(:user)
2083 user_two = insert(:user)
2085 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
2086 assert length(ap_ids) == 2
2087 assert user.ap_id in ap_ids
2088 assert user_two.ap_id in ap_ids
2092 describe "sync followers count" do
2094 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
2095 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
2096 insert(:user, local: true)
2097 insert(:user, local: false, is_active: false)
2098 {:ok, user1: user1, user2: user2}
2101 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
2102 [fdb_user1] = User.external_users(limit: 1)
2104 assert fdb_user1.ap_id
2105 assert fdb_user1.ap_id == user1.ap_id
2106 assert fdb_user1.id == user1.id
2108 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
2110 assert fdb_user2.ap_id
2111 assert fdb_user2.ap_id == user2.ap_id
2112 assert fdb_user2.id == user2.id
2114 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
2118 describe "is_internal_user?/1" do
2119 test "non-internal user returns false" do
2120 user = insert(:user)
2121 refute User.is_internal_user?(user)
2124 test "user with no nickname returns true" do
2125 user = insert(:user, %{nickname: nil})
2126 assert User.is_internal_user?(user)
2129 test "user with internal-prefixed nickname returns true" do
2130 user = insert(:user, %{nickname: "internal.test"})
2131 assert User.is_internal_user?(user)
2135 describe "update_and_set_cache/1" do
2136 test "returns error when user is stale instead Ecto.StaleEntryError" do
2137 user = insert(:user)
2139 changeset = Ecto.Changeset.change(user, bio: "test")
2143 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
2144 User.update_and_set_cache(changeset)
2147 test "performs update cache if user updated" do
2148 user = insert(:user)
2149 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
2151 changeset = Ecto.Changeset.change(user, bio: "test-bio")
2153 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
2154 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
2155 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
2158 test "removes report notifs when user isn't superuser any more" do
2159 report_activity = insert(:report_activity)
2160 user = insert(:user, is_moderator: true, is_admin: true)
2161 {:ok, _} = Notification.create_notifications(report_activity)
2163 assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
2165 {:ok, user} = user |> User.admin_api_update(%{is_moderator: false})
2166 # is still superuser because still admin
2167 assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
2169 {:ok, user} = user |> User.admin_api_update(%{is_moderator: true, is_admin: false})
2170 # is still superuser because still moderator
2171 assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
2173 {:ok, user} = user |> User.admin_api_update(%{is_moderator: false})
2174 # is not a superuser any more
2175 assert [] = Notification.for_user(user)
2179 describe "following/followers synchronization" do
2180 setup do: clear_config([:instance, :external_user_synchronization])
2182 test "updates the counters normally on following/getting a follow when disabled" do
2183 clear_config([:instance, :external_user_synchronization], false)
2184 user = insert(:user)
2189 follower_address: "http://localhost:4001/users/masto_closed/followers",
2190 following_address: "http://localhost:4001/users/masto_closed/following",
2194 assert other_user.following_count == 0
2195 assert other_user.follower_count == 0
2197 {:ok, user, other_user} = Pleroma.User.follow(user, other_user)
2199 assert user.following_count == 1
2200 assert other_user.follower_count == 1
2203 test "syncronizes the counters with the remote instance for the followed when enabled" do
2204 clear_config([:instance, :external_user_synchronization], false)
2206 user = insert(:user)
2211 follower_address: "http://localhost:4001/users/masto_closed/followers",
2212 following_address: "http://localhost:4001/users/masto_closed/following",
2216 assert other_user.following_count == 0
2217 assert other_user.follower_count == 0
2219 clear_config([:instance, :external_user_synchronization], true)
2220 {:ok, _user, other_user} = User.follow(user, other_user)
2222 assert other_user.follower_count == 437
2225 test "syncronizes the counters with the remote instance for the follower when enabled" do
2226 clear_config([:instance, :external_user_synchronization], false)
2228 user = insert(:user)
2233 follower_address: "http://localhost:4001/users/masto_closed/followers",
2234 following_address: "http://localhost:4001/users/masto_closed/following",
2238 assert other_user.following_count == 0
2239 assert other_user.follower_count == 0
2241 clear_config([:instance, :external_user_synchronization], true)
2242 {:ok, other_user, _user} = User.follow(other_user, user)
2244 assert other_user.following_count == 152
2248 describe "change_email/2" do
2250 [user: insert(:user)]
2253 test "blank email returns error if we require an email on registration", %{user: user} do
2254 orig_account_activation_required =
2255 Pleroma.Config.get([:instance, :account_activation_required])
2257 Pleroma.Config.put([:instance, :account_activation_required], true)
2261 [:instance, :account_activation_required],
2262 orig_account_activation_required
2266 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
2267 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
2270 test "blank email should be fine if we do not require an email on registration", %{user: user} do
2271 orig_account_activation_required =
2272 Pleroma.Config.get([:instance, :account_activation_required])
2274 Pleroma.Config.put([:instance, :account_activation_required], false)
2278 [:instance, :account_activation_required],
2279 orig_account_activation_required
2283 assert {:ok, %User{email: nil}} = User.change_email(user, "")
2284 assert {:ok, %User{email: nil}} = User.change_email(user, nil)
2287 test "non unique email returns error", %{user: user} do
2288 %{email: email} = insert(:user)
2290 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
2291 User.change_email(user, email)
2294 test "invalid email returns error", %{user: user} do
2295 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
2296 User.change_email(user, "cofe")
2299 test "changes email", %{user: user} do
2300 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
2303 test "adds email", %{user: user} do
2304 orig_account_activation_required =
2305 Pleroma.Config.get([:instance, :account_activation_required])
2307 Pleroma.Config.put([:instance, :account_activation_required], false)
2311 [:instance, :account_activation_required],
2312 orig_account_activation_required
2316 assert {:ok, _} = User.change_email(user, "")
2317 Pleroma.Config.put([:instance, :account_activation_required], true)
2319 assert {:ok, %User{email: "cofe2@cofe.party"}} = User.change_email(user, "cofe2@cofe.party")
2323 describe "get_cached_by_nickname_or_id" do
2325 local_user = insert(:user)
2326 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
2328 [local_user: local_user, remote_user: remote_user]
2331 setup do: clear_config([:instance, :limit_to_local_content])
2333 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
2334 remote_user: remote_user
2336 clear_config([:instance, :limit_to_local_content], false)
2337 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2339 clear_config([:instance, :limit_to_local_content], true)
2340 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2342 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2343 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2346 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
2347 %{remote_user: remote_user} do
2348 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2349 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2352 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
2353 %{remote_user: remote_user, local_user: local_user} do
2354 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2355 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
2358 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
2359 %{remote_user: remote_user} do
2360 clear_config([:instance, :limit_to_local_content], true)
2361 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2364 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
2365 %{local_user: local_user} do
2366 clear_config([:instance, :limit_to_local_content], false)
2367 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2369 clear_config([:instance, :limit_to_local_content], true)
2370 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2372 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2373 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2377 describe "update_email_notifications/2" do
2379 user = insert(:user, email_notifications: %{"digest" => true})
2384 test "Notifications are updated", %{user: user} do
2385 true = user.email_notifications["digest"]
2386 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
2387 assert result.email_notifications["digest"] == false
2391 describe "local_nickname/1" do
2392 test "returns nickname without host" do
2393 assert User.local_nickname("@mentioned") == "mentioned"
2394 assert User.local_nickname("a_local_nickname") == "a_local_nickname"
2395 assert User.local_nickname("nickname@host.com") == "nickname"
2399 describe "full_nickname/1" do
2400 test "returns fully qualified nickname for local and remote users" do
2402 insert(:user, nickname: "local_user", ap_id: "https://somehost.com/users/local_user")
2404 remote_user = insert(:user, nickname: "remote@host.com", local: false)
2406 assert User.full_nickname(local_user) == "local_user@somehost.com"
2407 assert User.full_nickname(remote_user) == "remote@host.com"
2410 test "strips leading @ from mentions" do
2411 assert User.full_nickname("@mentioned") == "mentioned"
2412 assert User.full_nickname("@nickname@host.com") == "nickname@host.com"
2415 test "does not modify nicknames" do
2416 assert User.full_nickname("nickname") == "nickname"
2417 assert User.full_nickname("nickname@host.com") == "nickname@host.com"
2421 test "avatar fallback" do
2422 user = insert(:user)
2423 assert User.avatar_url(user) =~ "/images/avi.png"
2425 clear_config([:assets, :default_user_avatar], "avatar.png")
2427 user = User.get_cached_by_nickname_or_id(user.nickname)
2428 assert User.avatar_url(user) =~ "avatar.png"
2430 assert User.avatar_url(user, no_default: true) == nil
2433 test "get_host/1" do
2434 user = insert(:user, ap_id: "https://lain.com/users/lain", nickname: "lain")
2435 assert User.get_host(user) == "lain.com"
2438 test "update_last_active_at/1" do
2439 user = insert(:user)
2440 assert is_nil(user.last_active_at)
2442 test_started_at = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
2444 assert {:ok, user} = User.update_last_active_at(user)
2446 assert user.last_active_at >= test_started_at
2447 assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
2450 NaiveDateTime.utc_now()
2451 |> NaiveDateTime.add(-:timer.hours(24), :millisecond)
2452 |> NaiveDateTime.truncate(:second)
2454 assert {:ok, user} =
2456 |> cast(%{last_active_at: last_active_at}, [:last_active_at])
2457 |> User.update_and_set_cache()
2459 assert user.last_active_at == last_active_at
2460 assert {:ok, user} = User.update_last_active_at(user)
2461 assert user.last_active_at >= test_started_at
2462 assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
2465 test "active_user_count/1" do
2467 insert(:user, %{local: false})
2468 insert(:user, %{last_active_at: NaiveDateTime.utc_now()})
2469 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), days: -15)})
2470 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), weeks: -6)})
2471 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), months: -7)})
2472 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), years: -2)})
2474 assert User.active_user_count() == 2
2475 assert User.active_user_count(180) == 3
2476 assert User.active_user_count(365) == 4
2477 assert User.active_user_count(1000) == 5
2482 user = insert(:user)
2484 [user: user, object_id: object_id_from_created_activity(user)]
2487 test "unique pins", %{user: user, object_id: object_id} do
2488 assert {:ok, %{pinned_objects: %{^object_id => pinned_at1} = pins} = updated_user} =
2489 User.add_pinned_object_id(user, object_id)
2491 assert Enum.count(pins) == 1
2493 assert {:ok, %{pinned_objects: %{^object_id => pinned_at2} = pins}} =
2494 User.add_pinned_object_id(updated_user, object_id)
2496 assert pinned_at1 == pinned_at2
2498 assert Enum.count(pins) == 1
2501 test "respects max_pinned_statuses limit", %{user: user, object_id: object_id} do
2502 clear_config([:instance, :max_pinned_statuses], 1)
2503 {:ok, updated} = User.add_pinned_object_id(user, object_id)
2505 object_id2 = object_id_from_created_activity(user)
2507 {:error, %{errors: errors}} = User.add_pinned_object_id(updated, object_id2)
2508 assert Keyword.has_key?(errors, :pinned_objects)
2511 test "remove_pinned_object_id/2", %{user: user, object_id: object_id} do
2512 assert {:ok, updated} = User.add_pinned_object_id(user, object_id)
2514 {:ok, after_remove} = User.remove_pinned_object_id(updated, object_id)
2515 assert after_remove.pinned_objects == %{}
2519 defp object_id_from_created_activity(user) do
2520 %{id: id} = insert(:note_activity, user: user)
2521 %{object: %{data: %{"id" => object_id}}} = Activity.get_by_id_with_object(id)
2525 describe "add_alias/2" do
2526 test "should add alias for another user" do
2527 user = insert(:user)
2528 user2 = insert(:user)
2530 assert {:ok, user_updated} = user |> User.add_alias(user2)
2532 assert user_updated.also_known_as |> length() == 1
2533 assert user2.ap_id in user_updated.also_known_as
2536 test "should add multiple aliases" do
2537 user = insert(:user)
2538 user2 = insert(:user)
2539 user3 = insert(:user)
2541 assert {:ok, user} = user |> User.add_alias(user2)
2542 assert {:ok, user_updated} = user |> User.add_alias(user3)
2544 assert user_updated.also_known_as |> length() == 2
2545 assert user2.ap_id in user_updated.also_known_as
2546 assert user3.ap_id in user_updated.also_known_as
2549 test "should not add duplicate aliases" do
2550 user = insert(:user)
2551 user2 = insert(:user)
2553 assert {:ok, user} = user |> User.add_alias(user2)
2555 assert {:ok, user_updated} = user |> User.add_alias(user2)
2557 assert user_updated.also_known_as |> length() == 1
2558 assert user2.ap_id in user_updated.also_known_as
2562 describe "alias_users/1" do
2563 test "should get aliases for a user" do
2564 user = insert(:user)
2565 user2 = insert(:user, also_known_as: [user.ap_id])
2567 aliases = user2 |> User.alias_users()
2569 assert aliases |> length() == 1
2571 alias_user = aliases |> Enum.at(0)
2573 assert alias_user.ap_id == user.ap_id
2577 describe "delete_alias/2" do
2578 test "should delete existing alias" do
2579 user = insert(:user)
2580 user2 = insert(:user, also_known_as: [user.ap_id])
2582 assert {:ok, user_updated} = user2 |> User.delete_alias(user)
2584 assert user_updated.also_known_as == []
2587 test "should report error on non-existing alias" do
2588 user = insert(:user)
2589 user2 = insert(:user)
2590 user3 = insert(:user, also_known_as: [user.ap_id])
2592 assert {:error, :no_such_alias} = user3 |> User.delete_alias(user2)
2594 user3_updated = User.get_cached_by_ap_id(user3.ap_id)
2596 assert user3_updated.also_known_as |> length() == 1
2597 assert user.ap_id in user3_updated.also_known_as