1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.UserTest do
7 alias Pleroma.Builders.UserBuilder
10 alias Pleroma.Tests.ObanHelpers
12 alias Pleroma.Web.ActivityPub.ActivityPub
13 alias Pleroma.Web.CommonAPI
16 use Oban.Testing, repo: Pleroma.Repo
18 import Pleroma.Factory
19 import ExUnit.CaptureLog
20 import Swoosh.TestAssertions
23 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
27 setup do: clear_config([:instance, :account_activation_required])
29 describe "service actors" do
30 test "returns updated invisible actor" do
31 uri = "#{Pleroma.Web.Endpoint.url()}/relay"
32 followers_uri = "#{uri}/followers"
41 follower_address: followers_uri
45 actor = User.get_or_create_service_actor_by_ap_id(uri, "relay")
46 assert actor.invisible
49 test "returns relay user" do
50 uri = "#{Pleroma.Web.Endpoint.url()}/relay"
51 followers_uri = "#{uri}/followers"
58 follower_address: ^followers_uri
59 } = User.get_or_create_service_actor_by_ap_id(uri, "relay")
61 assert capture_log(fn ->
62 refute User.get_or_create_service_actor_by_ap_id("/relay", "relay")
63 end) =~ "Cannot create service actor:"
66 test "returns invisible actor" do
67 uri = "#{Pleroma.Web.Endpoint.url()}/internal/fetch-test"
68 followers_uri = "#{uri}/followers"
69 user = User.get_or_create_service_actor_by_ap_id(uri, "internal.fetch-test")
72 nickname: "internal.fetch-test",
76 follower_address: ^followers_uri
79 user2 = User.get_or_create_service_actor_by_ap_id(uri, "internal.fetch-test")
80 assert user.id == user2.id
84 describe "AP ID user relationships" do
86 {:ok, user: insert(:user)}
89 test "outgoing_relationships_ap_ids/1", %{user: user} do
90 rel_types = [:block, :mute, :notification_mute, :reblog_mute, :inverse_subscription]
98 insert_list(2, :user_relationship, %{source: user, relationship_type: rel_type})
100 ap_ids = Enum.map(rel_records, fn rr -> Repo.preload(rr, :target).target.ap_id end)
101 {rel_type, Enum.sort(ap_ids)}
105 assert ap_ids_by_rel[:block] == Enum.sort(User.blocked_users_ap_ids(user))
106 assert ap_ids_by_rel[:block] == Enum.sort(Enum.map(User.blocked_users(user), & &1.ap_id))
108 assert ap_ids_by_rel[:mute] == Enum.sort(User.muted_users_ap_ids(user))
109 assert ap_ids_by_rel[:mute] == Enum.sort(Enum.map(User.muted_users(user), & &1.ap_id))
111 assert ap_ids_by_rel[:notification_mute] ==
112 Enum.sort(User.notification_muted_users_ap_ids(user))
114 assert ap_ids_by_rel[:notification_mute] ==
115 Enum.sort(Enum.map(User.notification_muted_users(user), & &1.ap_id))
117 assert ap_ids_by_rel[:reblog_mute] == Enum.sort(User.reblog_muted_users_ap_ids(user))
119 assert ap_ids_by_rel[:reblog_mute] ==
120 Enum.sort(Enum.map(User.reblog_muted_users(user), & &1.ap_id))
122 assert ap_ids_by_rel[:inverse_subscription] == Enum.sort(User.subscriber_users_ap_ids(user))
124 assert ap_ids_by_rel[:inverse_subscription] ==
125 Enum.sort(Enum.map(User.subscriber_users(user), & &1.ap_id))
127 outgoing_relationships_ap_ids = User.outgoing_relationships_ap_ids(user, rel_types)
129 assert ap_ids_by_rel ==
130 Enum.into(outgoing_relationships_ap_ids, %{}, fn {k, v} -> {k, Enum.sort(v)} end)
134 describe "when tags are nil" do
135 test "tagging a user" do
136 user = insert(:user, %{tags: nil})
137 user = User.tag(user, ["cool", "dude"])
139 assert "cool" in user.tags
140 assert "dude" in user.tags
143 test "untagging a user" do
144 user = insert(:user, %{tags: nil})
145 user = User.untag(user, ["cool", "dude"])
147 assert user.tags == []
151 test "ap_id returns the activity pub id for the user" do
152 user = UserBuilder.build()
154 expected_ap_id = "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
156 assert expected_ap_id == User.ap_id(user)
159 test "ap_followers returns the followers collection for the user" do
160 user = UserBuilder.build()
162 expected_followers_collection = "#{User.ap_id(user)}/followers"
164 assert expected_followers_collection == User.ap_followers(user)
167 test "ap_following returns the following collection for the user" do
168 user = UserBuilder.build()
170 expected_followers_collection = "#{User.ap_id(user)}/following"
172 assert expected_followers_collection == User.ap_following(user)
175 test "returns all pending follow requests" do
176 unlocked = insert(:user)
177 locked = insert(:user, is_locked: true)
178 follower = insert(:user)
180 CommonAPI.follow(follower, unlocked)
181 CommonAPI.follow(follower, locked)
183 assert [] = User.get_follow_requests(unlocked)
184 assert [activity] = User.get_follow_requests(locked)
189 test "doesn't return already accepted or duplicate follow requests" do
190 locked = insert(:user, is_locked: true)
191 pending_follower = insert(:user)
192 accepted_follower = insert(:user)
194 CommonAPI.follow(pending_follower, locked)
195 CommonAPI.follow(pending_follower, locked)
196 CommonAPI.follow(accepted_follower, locked)
198 Pleroma.FollowingRelationship.update(accepted_follower, locked, :follow_accept)
200 assert [^pending_follower] = User.get_follow_requests(locked)
203 test "doesn't return follow requests for deactivated accounts" do
204 locked = insert(:user, is_locked: true)
205 pending_follower = insert(:user, %{deactivated: true})
207 CommonAPI.follow(pending_follower, locked)
209 assert true == pending_follower.deactivated
210 assert [] = User.get_follow_requests(locked)
213 test "clears follow requests when requester is blocked" do
214 followed = insert(:user, is_locked: true)
215 follower = insert(:user)
217 CommonAPI.follow(follower, followed)
218 assert [_activity] = User.get_follow_requests(followed)
220 {:ok, _user_relationship} = User.block(followed, follower)
221 assert [] = User.get_follow_requests(followed)
224 test "follow_all follows mutliple users" do
226 followed_zero = insert(:user)
227 followed_one = insert(:user)
228 followed_two = insert(:user)
229 blocked = insert(:user)
230 not_followed = insert(:user)
231 reverse_blocked = insert(:user)
233 {:ok, _user_relationship} = User.block(user, blocked)
234 {:ok, _user_relationship} = User.block(reverse_blocked, user)
236 {:ok, user, followed_zero} = User.follow(user, followed_zero)
238 {:ok, user} = User.follow_all(user, [followed_one, followed_two, blocked, reverse_blocked])
240 assert User.following?(user, followed_one)
241 assert User.following?(user, followed_two)
242 assert User.following?(user, followed_zero)
243 refute User.following?(user, not_followed)
244 refute User.following?(user, blocked)
245 refute User.following?(user, reverse_blocked)
248 test "follow_all follows mutliple users without duplicating" do
250 followed_zero = insert(:user)
251 followed_one = insert(:user)
252 followed_two = insert(:user)
254 {:ok, user} = User.follow_all(user, [followed_zero, followed_one])
255 assert length(User.following(user)) == 3
257 {:ok, user} = User.follow_all(user, [followed_one, followed_two])
258 assert length(User.following(user)) == 4
261 test "follow takes a user and another user" do
263 followed = insert(:user)
265 {:ok, user, followed} = User.follow(user, followed)
267 user = User.get_cached_by_id(user.id)
268 followed = User.get_cached_by_ap_id(followed.ap_id)
270 assert followed.follower_count == 1
271 assert user.following_count == 1
273 assert User.ap_followers(followed) in User.following(user)
276 test "can't follow a deactivated users" do
278 followed = insert(:user, %{deactivated: true})
280 {:error, _} = User.follow(user, followed)
283 test "can't follow a user who blocked us" do
284 blocker = insert(:user)
285 blockee = insert(:user)
287 {:ok, _user_relationship} = User.block(blocker, blockee)
289 {:error, _} = User.follow(blockee, blocker)
292 test "can't subscribe to a user who blocked us" do
293 blocker = insert(:user)
294 blocked = insert(:user)
296 {:ok, _user_relationship} = User.block(blocker, blocked)
298 {:error, _} = User.subscribe(blocked, blocker)
301 test "local users do not automatically follow local locked accounts" do
302 follower = insert(:user, is_locked: true)
303 followed = insert(:user, is_locked: true)
305 {:ok, follower, followed} = User.maybe_direct_follow(follower, followed)
307 refute User.following?(follower, followed)
310 describe "unfollow/2" do
311 setup do: clear_config([:instance, :external_user_synchronization])
313 test "unfollow with syncronizes external user" do
314 Pleroma.Config.put([:instance, :external_user_synchronization], true)
319 follower_address: "http://localhost:4001/users/fuser1/followers",
320 following_address: "http://localhost:4001/users/fuser1/following",
321 ap_id: "http://localhost:4001/users/fuser1"
328 ap_id: "http://localhost:4001/users/fuser2",
329 follower_address: "http://localhost:4001/users/fuser2/followers",
330 following_address: "http://localhost:4001/users/fuser2/following"
333 {:ok, user, followed} = User.follow(user, followed, :follow_accept)
335 {:ok, user, _activity} = User.unfollow(user, followed)
337 user = User.get_cached_by_id(user.id)
339 assert User.following(user) == []
342 test "unfollow takes a user and another user" do
343 followed = insert(:user)
346 {:ok, user, followed} = User.follow(user, followed, :follow_accept)
348 assert User.following(user) == [user.follower_address, followed.follower_address]
350 {:ok, user, _activity} = User.unfollow(user, followed)
352 assert User.following(user) == [user.follower_address]
355 test "unfollow doesn't unfollow yourself" do
358 {:error, _} = User.unfollow(user, user)
360 assert User.following(user) == [user.follower_address]
364 test "test if a user is following another user" do
365 followed = insert(:user)
367 User.follow(user, followed, :follow_accept)
369 assert User.following?(user, followed)
370 refute User.following?(followed, user)
373 test "fetches correct profile for nickname beginning with number" do
374 # Use old-style integer ID to try to reproduce the problem
375 user = insert(:user, %{id: 1080})
376 user_with_numbers = insert(:user, %{nickname: "#{user.id}garbage"})
377 assert user_with_numbers == User.get_cached_by_nickname_or_id(user_with_numbers.nickname)
380 describe "user registration" do
386 password_confirmation: "test",
387 email: "email@example.com"
390 setup do: clear_config([:instance, :autofollowed_nicknames])
391 setup do: clear_config([:instance, :autofollowing_nicknames])
392 setup do: clear_config([:welcome])
393 setup do: clear_config([:instance, :account_activation_required])
395 test "it autofollows accounts that are set for it" do
397 remote_user = insert(:user, %{local: false})
399 Pleroma.Config.put([:instance, :autofollowed_nicknames], [
404 cng = User.register_changeset(%User{}, @full_user_data)
406 {:ok, registered_user} = User.register(cng)
408 assert User.following?(registered_user, user)
409 refute User.following?(registered_user, remote_user)
412 test "it adds automatic followers for new registered accounts" do
413 user1 = insert(:user)
414 user2 = insert(:user)
416 Pleroma.Config.put([:instance, :autofollowing_nicknames], [
421 cng = User.register_changeset(%User{}, @full_user_data)
423 {:ok, registered_user} = User.register(cng)
425 assert User.following?(user1, registered_user)
426 assert User.following?(user2, registered_user)
429 test "it sends a welcome message if it is set" do
430 welcome_user = insert(:user)
431 Pleroma.Config.put([:welcome, :direct_message, :enabled], true)
432 Pleroma.Config.put([:welcome, :direct_message, :sender_nickname], welcome_user.nickname)
433 Pleroma.Config.put([:welcome, :direct_message, :message], "Hello, this is a direct message")
435 cng = User.register_changeset(%User{}, @full_user_data)
436 {:ok, registered_user} = User.register(cng)
437 ObanHelpers.perform_all()
439 activity = Repo.one(Pleroma.Activity)
440 assert registered_user.ap_id in activity.recipients
441 assert Object.normalize(activity).data["content"] =~ "direct message"
442 assert activity.actor == welcome_user.ap_id
445 test "it sends a welcome chat message if it is set" do
446 welcome_user = insert(:user)
447 Pleroma.Config.put([:welcome, :chat_message, :enabled], true)
448 Pleroma.Config.put([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
449 Pleroma.Config.put([:welcome, :chat_message, :message], "Hello, this is a chat message")
451 cng = User.register_changeset(%User{}, @full_user_data)
452 {:ok, registered_user} = User.register(cng)
453 ObanHelpers.perform_all()
455 activity = Repo.one(Pleroma.Activity)
456 assert registered_user.ap_id in activity.recipients
457 assert Object.normalize(activity).data["content"] =~ "chat message"
458 assert activity.actor == welcome_user.ap_id
462 clear_config(:mrf_simple,
465 federated_timeline_removal: [],
478 Pleroma.Web.ActivityPub.MRF.SimplePolicy
482 test "it sends a welcome chat message when Simple policy applied to local instance" do
483 Pleroma.Config.put([:mrf_simple, :media_nsfw], ["localhost"])
485 welcome_user = insert(:user)
486 Pleroma.Config.put([:welcome, :chat_message, :enabled], true)
487 Pleroma.Config.put([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
488 Pleroma.Config.put([:welcome, :chat_message, :message], "Hello, this is a chat message")
490 cng = User.register_changeset(%User{}, @full_user_data)
491 {:ok, registered_user} = User.register(cng)
492 ObanHelpers.perform_all()
494 activity = Repo.one(Pleroma.Activity)
495 assert registered_user.ap_id in activity.recipients
496 assert Object.normalize(activity).data["content"] =~ "chat message"
497 assert activity.actor == welcome_user.ap_id
500 test "it sends a welcome email message if it is set" do
501 welcome_user = insert(:user)
502 Pleroma.Config.put([:welcome, :email, :enabled], true)
503 Pleroma.Config.put([:welcome, :email, :sender], welcome_user.email)
506 [:welcome, :email, :subject],
507 "Hello, welcome to cool site: <%= instance_name %>"
510 instance_name = Pleroma.Config.get([:instance, :name])
512 cng = User.register_changeset(%User{}, @full_user_data)
513 {:ok, registered_user} = User.register(cng)
514 ObanHelpers.perform_all()
517 from: {instance_name, welcome_user.email},
518 to: {registered_user.name, registered_user.email},
519 subject: "Hello, welcome to cool site: #{instance_name}",
520 html_body: "Welcome to #{instance_name}"
524 test "it sends a confirm email" do
525 Pleroma.Config.put([:instance, :account_activation_required], true)
527 cng = User.register_changeset(%User{}, @full_user_data)
528 {:ok, registered_user} = User.register(cng)
529 ObanHelpers.perform_all()
531 Pleroma.Emails.UserEmail.account_confirmation_email(registered_user)
532 # temporary hackney fix until hackney max_connections bug is fixed
533 # https://git.pleroma.social/pleroma/pleroma/-/issues/2101
534 |> Swoosh.Email.put_private(:hackney_options, ssl_options: [versions: [:"tlsv1.2"]])
535 |> assert_email_sent()
538 test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do
539 Pleroma.Config.put([:instance, :account_activation_required], true)
543 |> Enum.each(fn key ->
544 params = Map.delete(@full_user_data, key)
545 changeset = User.register_changeset(%User{}, params)
547 assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
551 test "it requires an name, nickname and password, bio and email are optional when account_activation_required is disabled" do
552 Pleroma.Config.put([:instance, :account_activation_required], false)
556 |> Enum.each(fn key ->
557 params = Map.delete(@full_user_data, key)
558 changeset = User.register_changeset(%User{}, params)
560 assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid?
564 test "it restricts certain nicknames" do
565 [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
567 assert is_bitstring(restricted_name)
571 |> Map.put(:nickname, restricted_name)
573 changeset = User.register_changeset(%User{}, params)
575 refute changeset.valid?
578 test "it blocks blacklisted email domains" do
579 clear_config([User, :email_blacklist], ["trolling.world"])
582 params = Map.put(@full_user_data, :email, "troll@trolling.world")
583 changeset = User.register_changeset(%User{}, params)
584 refute changeset.valid?
586 # Block with subdomain match
587 params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world")
588 changeset = User.register_changeset(%User{}, params)
589 refute changeset.valid?
591 # Pass with different domains that are similar
592 params = Map.put(@full_user_data, :email, "troll@gnomestrolling.world")
593 changeset = User.register_changeset(%User{}, params)
594 assert changeset.valid?
596 params = Map.put(@full_user_data, :email, "troll@trolling.world.us")
597 changeset = User.register_changeset(%User{}, params)
598 assert changeset.valid?
601 test "it sets the password_hash and ap_id" do
602 changeset = User.register_changeset(%User{}, @full_user_data)
604 assert changeset.valid?
606 assert is_binary(changeset.changes[:password_hash])
607 assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
609 assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
612 test "it sets the 'accepts_chat_messages' set to true" do
613 changeset = User.register_changeset(%User{}, @full_user_data)
614 assert changeset.valid?
616 {:ok, user} = Repo.insert(changeset)
618 assert user.accepts_chat_messages
621 test "it creates a confirmed user" do
622 changeset = User.register_changeset(%User{}, @full_user_data)
623 assert changeset.valid?
625 {:ok, user} = Repo.insert(changeset)
627 refute user.confirmation_pending
631 describe "user registration, with :account_activation_required" do
637 password_confirmation: "test",
638 email: "email@example.com"
640 setup do: clear_config([:instance, :account_activation_required], true)
642 test "it creates unconfirmed user" do
643 changeset = User.register_changeset(%User{}, @full_user_data)
644 assert changeset.valid?
646 {:ok, user} = Repo.insert(changeset)
648 assert user.confirmation_pending
649 assert user.confirmation_token
652 test "it creates confirmed user if :confirmed option is given" do
653 changeset = User.register_changeset(%User{}, @full_user_data, need_confirmation: false)
654 assert changeset.valid?
656 {:ok, user} = Repo.insert(changeset)
658 refute user.confirmation_pending
659 refute user.confirmation_token
663 describe "user registration, with :account_approval_required" do
669 password_confirmation: "test",
670 email: "email@example.com",
671 registration_reason: "I'm a cool guy :)"
673 setup do: clear_config([:instance, :account_approval_required], true)
675 test "it creates unapproved user" do
676 changeset = User.register_changeset(%User{}, @full_user_data)
677 assert changeset.valid?
679 {:ok, user} = Repo.insert(changeset)
681 assert user.approval_pending
682 assert user.registration_reason == "I'm a cool guy :)"
685 test "it restricts length of registration reason" do
686 reason_limit = Pleroma.Config.get([:instance, :registration_reason_length])
688 assert is_integer(reason_limit)
693 :registration_reason,
694 "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."
697 changeset = User.register_changeset(%User{}, params)
699 refute changeset.valid?
703 describe "get_or_fetch/1" do
704 test "gets an existing user by nickname" do
706 {:ok, fetched_user} = User.get_or_fetch(user.nickname)
708 assert user == fetched_user
711 test "gets an existing user by ap_id" do
712 ap_id = "http://mastodon.example.org/users/admin"
718 nickname: "admin@mastodon.example.org",
722 {:ok, fetched_user} = User.get_or_fetch(ap_id)
723 freshed_user = refresh_record(user)
724 assert freshed_user == fetched_user
728 describe "fetching a user from nickname or trying to build one" do
729 test "gets an existing user" do
731 {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
733 assert user == fetched_user
736 test "gets an existing user, case insensitive" do
737 user = insert(:user, nickname: "nick")
738 {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
740 assert user == fetched_user
743 test "gets an existing user by fully qualified nickname" do
746 {:ok, fetched_user} =
747 User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
749 assert user == fetched_user
752 test "gets an existing user by fully qualified nickname, case insensitive" do
753 user = insert(:user, nickname: "nick")
754 casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
756 {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
758 assert user == fetched_user
761 @tag capture_log: true
762 test "returns nil if no user could be fetched" do
763 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
764 assert fetched_user == "not found nonexistant@social.heldscal.la"
767 test "returns nil for nonexistant local user" do
768 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
769 assert fetched_user == "not found nonexistant"
772 test "updates an existing user, if stale" do
773 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
779 nickname: "admin@mastodon.example.org",
780 ap_id: "http://mastodon.example.org/users/admin",
781 last_refreshed_at: a_week_ago
784 assert orig_user.last_refreshed_at == a_week_ago
786 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
790 refute user.last_refreshed_at == orig_user.last_refreshed_at
793 test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
794 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
800 nickname: "admin@mastodon.example.org",
801 ap_id: "http://mastodon.example.org/users/harinezumigari",
802 last_refreshed_at: a_week_ago
805 assert orig_user.last_refreshed_at == a_week_ago
807 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
811 refute user.id == orig_user.id
813 orig_user = User.get_by_id(orig_user.id)
815 assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
818 @tag capture_log: true
819 test "it returns the old user if stale, but unfetchable" do
820 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
826 nickname: "admin@mastodon.example.org",
827 ap_id: "http://mastodon.example.org/users/raymoo",
828 last_refreshed_at: a_week_ago
831 assert orig_user.last_refreshed_at == a_week_ago
833 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/raymoo")
835 assert user.last_refreshed_at == orig_user.last_refreshed_at
839 test "returns an ap_id for a user" do
842 assert User.ap_id(user) ==
843 Pleroma.Web.Router.Helpers.user_feed_url(
844 Pleroma.Web.Endpoint,
850 test "returns an ap_followers link for a user" do
853 assert User.ap_followers(user) ==
854 Pleroma.Web.Router.Helpers.user_feed_url(
855 Pleroma.Web.Endpoint,
861 describe "remote user changeset" do
867 avatar: %{some: "avatar"}
869 setup do: clear_config([:instance, :user_bio_length])
870 setup do: clear_config([:instance, :user_name_length])
872 test "it confirms validity" do
873 cs = User.remote_user_changeset(@valid_remote)
877 test "it sets the follower_adress" do
878 cs = User.remote_user_changeset(@valid_remote)
879 # remote users get a fake local follower address
880 assert cs.changes.follower_address ==
881 User.ap_followers(%User{nickname: @valid_remote[:nickname]})
884 test "it enforces the fqn format for nicknames" do
885 cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})
886 assert Ecto.Changeset.get_field(cs, :local) == false
887 assert cs.changes.avatar
891 test "it has required fields" do
893 |> Enum.each(fn field ->
894 cs = User.remote_user_changeset(Map.delete(@valid_remote, field))
899 test "it is invalid given a local user" do
901 cs = User.remote_user_changeset(user, %{name: "tom from myspace"})
907 describe "followers and friends" do
908 test "gets all followers for a given user" do
910 follower_one = insert(:user)
911 follower_two = insert(:user)
912 not_follower = insert(:user)
914 {:ok, follower_one, user} = User.follow(follower_one, user)
915 {:ok, follower_two, user} = User.follow(follower_two, user)
917 res = User.get_followers(user)
919 assert Enum.member?(res, follower_one)
920 assert Enum.member?(res, follower_two)
921 refute Enum.member?(res, not_follower)
924 test "gets all friends (followed users) for a given user" do
926 followed_one = insert(:user)
927 followed_two = insert(:user)
928 not_followed = insert(:user)
930 {:ok, user, followed_one} = User.follow(user, followed_one)
931 {:ok, user, followed_two} = User.follow(user, followed_two)
933 res = User.get_friends(user)
935 followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
936 followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
937 assert Enum.member?(res, followed_one)
938 assert Enum.member?(res, followed_two)
939 refute Enum.member?(res, not_followed)
943 describe "updating note and follower count" do
944 test "it sets the note_count property" do
947 user = User.get_cached_by_ap_id(note.data["actor"])
949 assert user.note_count == 0
951 {:ok, user} = User.update_note_count(user)
953 assert user.note_count == 1
956 test "it increases the note_count property" do
958 user = User.get_cached_by_ap_id(note.data["actor"])
960 assert user.note_count == 0
962 {:ok, user} = User.increase_note_count(user)
964 assert user.note_count == 1
966 {:ok, user} = User.increase_note_count(user)
968 assert user.note_count == 2
971 test "it decreases the note_count property" do
973 user = User.get_cached_by_ap_id(note.data["actor"])
975 assert user.note_count == 0
977 {:ok, user} = User.increase_note_count(user)
979 assert user.note_count == 1
981 {:ok, user} = User.decrease_note_count(user)
983 assert user.note_count == 0
985 {:ok, user} = User.decrease_note_count(user)
987 assert user.note_count == 0
990 test "it sets the follower_count property" do
992 follower = insert(:user)
994 User.follow(follower, user)
996 assert user.follower_count == 0
998 {:ok, user} = User.update_follower_count(user)
1000 assert user.follower_count == 1
1005 test "it mutes people" do
1006 user = insert(:user)
1007 muted_user = insert(:user)
1009 refute User.mutes?(user, muted_user)
1010 refute User.muted_notifications?(user, muted_user)
1012 {:ok, _user_relationships} = User.mute(user, muted_user)
1014 assert User.mutes?(user, muted_user)
1015 assert User.muted_notifications?(user, muted_user)
1019 user = insert(:user)
1020 muted_user = insert(:user)
1022 {:ok, _user_relationships} = User.mute(user, muted_user, %{expires_in: 60})
1023 assert User.mutes?(user, muted_user)
1025 worker = Pleroma.Workers.MuteExpireWorker
1026 args = %{"op" => "unmute_user", "muter_id" => user.id, "mutee_id" => muted_user.id}
1033 assert :ok = perform_job(worker, args)
1035 refute User.mutes?(user, muted_user)
1036 refute User.muted_notifications?(user, muted_user)
1039 test "it unmutes users" do
1040 user = insert(:user)
1041 muted_user = insert(:user)
1043 {:ok, _user_relationships} = User.mute(user, muted_user)
1044 {:ok, _user_mute} = User.unmute(user, muted_user)
1046 refute User.mutes?(user, muted_user)
1047 refute User.muted_notifications?(user, muted_user)
1050 test "it unmutes users by id" do
1051 user = insert(:user)
1052 muted_user = insert(:user)
1054 {:ok, _user_relationships} = User.mute(user, muted_user)
1055 {:ok, _user_mute} = User.unmute(user.id, muted_user.id)
1057 refute User.mutes?(user, muted_user)
1058 refute User.muted_notifications?(user, muted_user)
1061 test "it mutes user without notifications" 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, %{notifications: false})
1070 assert User.mutes?(user, muted_user)
1071 refute User.muted_notifications?(user, muted_user)
1075 describe "blocks" do
1076 test "it blocks people" do
1077 user = insert(:user)
1078 blocked_user = insert(:user)
1080 refute User.blocks?(user, blocked_user)
1082 {:ok, _user_relationship} = User.block(user, blocked_user)
1084 assert User.blocks?(user, blocked_user)
1087 test "it unblocks users" do
1088 user = insert(:user)
1089 blocked_user = insert(:user)
1091 {:ok, _user_relationship} = User.block(user, blocked_user)
1092 {:ok, _user_block} = User.unblock(user, blocked_user)
1094 refute User.blocks?(user, blocked_user)
1097 test "blocks tear down cyclical follow relationships" do
1098 blocker = insert(:user)
1099 blocked = insert(:user)
1101 {:ok, blocker, blocked} = User.follow(blocker, blocked)
1102 {:ok, blocked, blocker} = User.follow(blocked, blocker)
1104 assert User.following?(blocker, blocked)
1105 assert User.following?(blocked, blocker)
1107 {:ok, _user_relationship} = User.block(blocker, blocked)
1108 blocked = User.get_cached_by_id(blocked.id)
1110 assert User.blocks?(blocker, blocked)
1112 refute User.following?(blocker, blocked)
1113 refute User.following?(blocked, blocker)
1116 test "blocks tear down blocker->blocked follow relationships" do
1117 blocker = insert(:user)
1118 blocked = insert(:user)
1120 {:ok, blocker, blocked} = User.follow(blocker, blocked)
1122 assert User.following?(blocker, blocked)
1123 refute User.following?(blocked, blocker)
1125 {:ok, _user_relationship} = User.block(blocker, blocked)
1126 blocked = User.get_cached_by_id(blocked.id)
1128 assert User.blocks?(blocker, blocked)
1130 refute User.following?(blocker, blocked)
1131 refute User.following?(blocked, blocker)
1134 test "blocks tear down blocked->blocker follow relationships" do
1135 blocker = insert(:user)
1136 blocked = insert(:user)
1138 {:ok, blocked, blocker} = User.follow(blocked, blocker)
1140 refute User.following?(blocker, blocked)
1141 assert User.following?(blocked, blocker)
1143 {:ok, _user_relationship} = User.block(blocker, blocked)
1144 blocked = User.get_cached_by_id(blocked.id)
1146 assert User.blocks?(blocker, blocked)
1148 refute User.following?(blocker, blocked)
1149 refute User.following?(blocked, blocker)
1152 test "blocks tear down blocked->blocker subscription relationships" do
1153 blocker = insert(:user)
1154 blocked = insert(:user)
1156 {:ok, _subscription} = User.subscribe(blocked, blocker)
1158 assert User.subscribed_to?(blocked, blocker)
1159 refute User.subscribed_to?(blocker, blocked)
1161 {:ok, _user_relationship} = User.block(blocker, blocked)
1163 assert User.blocks?(blocker, blocked)
1164 refute User.subscribed_to?(blocker, blocked)
1165 refute User.subscribed_to?(blocked, blocker)
1169 describe "domain blocking" do
1170 test "blocks domains" do
1171 user = insert(:user)
1172 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1174 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1176 assert User.blocks?(user, collateral_user)
1179 test "does not block domain with same end" do
1180 user = insert(:user)
1183 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1185 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1187 refute User.blocks?(user, collateral_user)
1190 test "does not block domain with same end if wildcard added" do
1191 user = insert(:user)
1194 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1196 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1198 refute User.blocks?(user, collateral_user)
1201 test "blocks domain with wildcard for subdomain" do
1202 user = insert(:user)
1204 user_from_subdomain =
1205 insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
1207 user_with_two_subdomains =
1209 ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
1212 user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1214 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1216 assert User.blocks?(user, user_from_subdomain)
1217 assert User.blocks?(user, user_with_two_subdomains)
1218 assert User.blocks?(user, user_domain)
1221 test "unblocks domains" do
1222 user = insert(:user)
1223 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1225 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1226 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
1228 refute User.blocks?(user, collateral_user)
1231 test "follows take precedence over domain blocks" do
1232 user = insert(:user)
1233 good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
1235 {:ok, user} = User.block_domain(user, "meanies.social")
1236 {:ok, user, good_eggo} = User.follow(user, good_eggo)
1238 refute User.blocks?(user, good_eggo)
1242 describe "get_recipients_from_activity" do
1243 test "works for announces" do
1244 actor = insert(:user)
1245 user = insert(:user, local: true)
1247 {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
1248 {:ok, announce} = CommonAPI.repeat(activity.id, user)
1250 recipients = User.get_recipients_from_activity(announce)
1252 assert user in recipients
1255 test "get recipients" do
1256 actor = insert(:user)
1257 user = insert(:user, local: true)
1258 user_two = insert(:user, local: false)
1259 addressed = insert(:user, local: true)
1260 addressed_remote = insert(:user, local: false)
1263 CommonAPI.post(actor, %{
1264 status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
1267 assert Enum.map([actor, addressed], & &1.ap_id) --
1268 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1270 {:ok, user, actor} = User.follow(user, actor)
1271 {:ok, _user_two, _actor} = User.follow(user_two, actor)
1272 recipients = User.get_recipients_from_activity(activity)
1273 assert length(recipients) == 3
1274 assert user in recipients
1275 assert addressed in recipients
1278 test "has following" do
1279 actor = insert(:user)
1280 user = insert(:user)
1281 user_two = insert(:user)
1282 addressed = insert(:user, local: true)
1285 CommonAPI.post(actor, %{
1286 status: "hey @#{addressed.nickname}"
1289 assert Enum.map([actor, addressed], & &1.ap_id) --
1290 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1292 {:ok, _actor, _user} = User.follow(actor, user)
1293 {:ok, _actor, _user_two} = User.follow(actor, user_two)
1294 recipients = User.get_recipients_from_activity(activity)
1295 assert length(recipients) == 2
1296 assert addressed in recipients
1300 describe ".deactivate" do
1301 test "can de-activate then re-activate a user" do
1302 user = insert(:user)
1303 assert false == user.deactivated
1304 {:ok, user} = User.deactivate(user)
1305 assert true == user.deactivated
1306 {:ok, user} = User.deactivate(user, false)
1307 assert false == user.deactivated
1310 test "hide a user from followers" do
1311 user = insert(:user)
1312 user2 = insert(:user)
1314 {:ok, user, user2} = User.follow(user, user2)
1315 {:ok, _user} = User.deactivate(user)
1317 user2 = User.get_cached_by_id(user2.id)
1319 assert user2.follower_count == 0
1320 assert [] = User.get_followers(user2)
1323 test "hide a user from friends" do
1324 user = insert(:user)
1325 user2 = insert(:user)
1327 {:ok, user2, user} = User.follow(user2, user)
1328 assert user2.following_count == 1
1329 assert User.following_count(user2) == 1
1331 {:ok, _user} = User.deactivate(user)
1333 user2 = User.get_cached_by_id(user2.id)
1335 assert refresh_record(user2).following_count == 0
1336 assert user2.following_count == 0
1337 assert User.following_count(user2) == 0
1338 assert [] = User.get_friends(user2)
1341 test "hide a user's statuses from timelines and notifications" do
1342 user = insert(:user)
1343 user2 = insert(:user)
1345 {:ok, user2, user} = User.follow(user2, user)
1347 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
1349 activity = Repo.preload(activity, :bookmark)
1351 [notification] = Pleroma.Notification.for_user(user2)
1352 assert notification.activity.id == activity.id
1354 assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
1356 assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
1357 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1361 {:ok, _user} = User.deactivate(user)
1363 assert [] == ActivityPub.fetch_public_activities(%{})
1364 assert [] == Pleroma.Notification.for_user(user2)
1367 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1373 describe "approve" do
1374 test "approves a user" do
1375 user = insert(:user, approval_pending: true)
1376 assert true == user.approval_pending
1377 {:ok, user} = User.approve(user)
1378 assert false == user.approval_pending
1381 test "approves a list of users" do
1382 unapproved_users = [
1383 insert(:user, approval_pending: true),
1384 insert(:user, approval_pending: true),
1385 insert(:user, approval_pending: true)
1388 {:ok, users} = User.approve(unapproved_users)
1390 assert Enum.count(users) == 3
1392 Enum.each(users, fn user ->
1393 assert false == user.approval_pending
1398 describe "delete" do
1400 {:ok, user} = insert(:user) |> User.set_cache()
1405 setup do: clear_config([:instance, :federating])
1407 test ".delete_user_activities deletes all create activities", %{user: user} do
1408 {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
1410 User.delete_user_activities(user)
1412 # TODO: Test removal favorites, repeats, delete activities.
1413 refute Activity.get_by_id(activity.id)
1416 test "it deactivates a user, all follow relationships and all activities", %{user: user} do
1417 follower = insert(:user)
1418 {:ok, follower, user} = User.follow(follower, user)
1420 locked_user = insert(:user, name: "locked", is_locked: true)
1421 {:ok, _, _} = User.follow(user, locked_user, :follow_pending)
1423 object = insert(:note, user: user)
1424 activity = insert(:note_activity, user: user, note: object)
1426 object_two = insert(:note, user: follower)
1427 activity_two = insert(:note_activity, user: follower, note: object_two)
1429 {:ok, like} = CommonAPI.favorite(user, activity_two.id)
1430 {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
1431 {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
1433 {:ok, job} = User.delete(user)
1434 {:ok, _user} = ObanHelpers.perform(job)
1436 follower = User.get_cached_by_id(follower.id)
1438 refute User.following?(follower, user)
1439 assert %{deactivated: true} = User.get_by_id(user.id)
1441 assert [] == User.get_follow_requests(locked_user)
1445 |> Activity.Queries.by_actor()
1447 |> Enum.map(fn act -> act.data["type"] end)
1449 assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
1451 refute Activity.get_by_id(activity.id)
1452 refute Activity.get_by_id(like.id)
1453 refute Activity.get_by_id(like_two.id)
1454 refute Activity.get_by_id(repeat.id)
1458 describe "delete/1 when confirmation is pending" do
1460 user = insert(:user, confirmation_pending: true)
1464 test "deletes user from database when activation required", %{user: user} do
1465 clear_config([:instance, :account_activation_required], true)
1467 {:ok, job} = User.delete(user)
1468 {:ok, _} = ObanHelpers.perform(job)
1470 refute User.get_cached_by_id(user.id)
1471 refute User.get_by_id(user.id)
1474 test "deactivates user when activation is not required", %{user: user} do
1475 clear_config([:instance, :account_activation_required], false)
1477 {:ok, job} = User.delete(user)
1478 {:ok, _} = ObanHelpers.perform(job)
1480 assert %{deactivated: true} = User.get_cached_by_id(user.id)
1481 assert %{deactivated: true} = User.get_by_id(user.id)
1485 test "delete/1 when approval is pending deletes the user" do
1486 user = insert(:user, approval_pending: true)
1488 {:ok, job} = User.delete(user)
1489 {:ok, _} = ObanHelpers.perform(job)
1491 refute User.get_cached_by_id(user.id)
1492 refute User.get_by_id(user.id)
1495 test "delete/1 purges a user when they wouldn't be fully deleted" do
1500 password_hash: "pdfk2$1b3n159001",
1501 keys: "RSA begin buplic key",
1502 public_key: "--PRIVATE KEYE--",
1503 avatar: %{"a" => "b"},
1505 banner: %{"a" => "b"},
1506 background: %{"a" => "b"},
1509 following_count: 9001,
1511 confirmation_pending: true,
1512 password_reset_pending: true,
1513 approval_pending: true,
1514 registration_reason: "ahhhhh",
1515 confirmation_token: "qqqq",
1516 domain_blocks: ["lain.com"],
1521 mastofe_settings: %{"a" => "b"},
1522 mascot: %{"a" => "b"},
1523 emoji: %{"a" => "b"},
1524 pleroma_settings_store: %{"q" => "x"},
1525 fields: [%{"gg" => "qq"}],
1526 raw_fields: [%{"gg" => "qq"}],
1527 is_discoverable: true,
1528 also_known_as: ["https://lol.olo/users/loll"]
1531 {:ok, job} = User.delete(user)
1532 {:ok, _} = ObanHelpers.perform(job)
1533 user = User.get_by_id(user.id)
1545 last_refreshed_at: nil,
1546 last_digest_emailed_at: nil,
1553 confirmation_pending: false,
1554 password_reset_pending: false,
1555 approval_pending: false,
1556 registration_reason: nil,
1557 confirmation_token: nil,
1561 is_moderator: false,
1563 mastofe_settings: nil,
1566 pleroma_settings_store: %{},
1569 is_discoverable: false,
1574 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1575 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1578 describe "per-user rich-text filtering" do
1579 test "html_filter_policy returns default policies, when rich-text is enabled" do
1580 user = insert(:user)
1582 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1585 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1586 user = insert(:user, no_rich_text: true)
1588 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1592 describe "caching" do
1593 test "invalidate_cache works" do
1594 user = insert(:user)
1596 User.set_cache(user)
1597 User.invalidate_cache(user)
1599 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1600 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1603 test "User.delete() plugs any possible zombie objects" do
1604 user = insert(:user)
1606 {:ok, job} = User.delete(user)
1607 {:ok, _} = ObanHelpers.perform(job)
1609 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1611 assert cached_user != user
1613 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1615 assert cached_user != user
1619 describe "account_status/1" do
1620 setup do: clear_config([:instance, :account_activation_required])
1622 test "return confirmation_pending for unconfirm user" do
1623 Pleroma.Config.put([:instance, :account_activation_required], true)
1624 user = insert(:user, confirmation_pending: true)
1625 assert User.account_status(user) == :confirmation_pending
1628 test "return active for confirmed user" do
1629 Pleroma.Config.put([:instance, :account_activation_required], true)
1630 user = insert(:user, confirmation_pending: false)
1631 assert User.account_status(user) == :active
1634 test "return active for remote user" do
1635 user = insert(:user, local: false)
1636 assert User.account_status(user) == :active
1639 test "returns :password_reset_pending for user with reset password" do
1640 user = insert(:user, password_reset_pending: true)
1641 assert User.account_status(user) == :password_reset_pending
1644 test "returns :deactivated for deactivated user" do
1645 user = insert(:user, local: true, confirmation_pending: false, deactivated: true)
1646 assert User.account_status(user) == :deactivated
1649 test "returns :approval_pending for unapproved user" do
1650 user = insert(:user, local: true, approval_pending: true)
1651 assert User.account_status(user) == :approval_pending
1653 user = insert(:user, local: true, confirmation_pending: true, approval_pending: true)
1654 assert User.account_status(user) == :approval_pending
1658 describe "superuser?/1" do
1659 test "returns false for unprivileged users" do
1660 user = insert(:user, local: true)
1662 refute User.superuser?(user)
1665 test "returns false for remote users" do
1666 user = insert(:user, local: false)
1667 remote_admin_user = insert(:user, local: false, is_admin: true)
1669 refute User.superuser?(user)
1670 refute User.superuser?(remote_admin_user)
1673 test "returns true for local moderators" do
1674 user = insert(:user, local: true, is_moderator: true)
1676 assert User.superuser?(user)
1679 test "returns true for local admins" do
1680 user = insert(:user, local: true, is_admin: true)
1682 assert User.superuser?(user)
1686 describe "invisible?/1" do
1687 test "returns true for an invisible user" do
1688 user = insert(:user, local: true, invisible: true)
1690 assert User.invisible?(user)
1693 test "returns false for a non-invisible user" do
1694 user = insert(:user, local: true)
1696 refute User.invisible?(user)
1700 describe "visible_for/2" do
1701 test "returns true when the account is itself" do
1702 user = insert(:user, local: true)
1704 assert User.visible_for(user, user) == :visible
1707 test "returns false when the account is unconfirmed and confirmation is required" do
1708 Pleroma.Config.put([:instance, :account_activation_required], true)
1710 user = insert(:user, local: true, confirmation_pending: true)
1711 other_user = insert(:user, local: true)
1713 refute User.visible_for(user, other_user) == :visible
1716 test "returns true when the account is unconfirmed and confirmation is required but the account is remote" do
1717 Pleroma.Config.put([:instance, :account_activation_required], true)
1719 user = insert(:user, local: false, confirmation_pending: true)
1720 other_user = insert(:user, local: true)
1722 assert User.visible_for(user, other_user) == :visible
1725 test "returns true when the account is unconfirmed and confirmation is not required" do
1726 user = insert(:user, local: true, confirmation_pending: true)
1727 other_user = insert(:user, local: true)
1729 assert User.visible_for(user, other_user) == :visible
1732 test "returns true when the account is unconfirmed and being viewed by a privileged account (confirmation required)" do
1733 Pleroma.Config.put([:instance, :account_activation_required], true)
1735 user = insert(:user, local: true, confirmation_pending: true)
1736 other_user = insert(:user, local: true, is_admin: true)
1738 assert User.visible_for(user, other_user) == :visible
1742 describe "parse_bio/2" do
1743 test "preserves hosts in user links text" do
1744 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1745 user = insert(:user)
1746 bio = "A.k.a. @nick@domain.com"
1749 ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
1751 }" rel="ugc">@<span>nick@domain.com</span></a></span>)
1753 assert expected_text == User.parse_bio(bio, user)
1756 test "Adds rel=me on linkbacked urls" do
1757 user = insert(:user, ap_id: "https://social.example.org/users/lain")
1759 bio = "http://example.com/rel_me/null"
1760 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1761 assert expected_text == User.parse_bio(bio, user)
1763 bio = "http://example.com/rel_me/link"
1764 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1765 assert expected_text == User.parse_bio(bio, user)
1767 bio = "http://example.com/rel_me/anchor"
1768 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1769 assert expected_text == User.parse_bio(bio, user)
1773 test "follower count is updated when a follower is blocked" do
1774 user = insert(:user)
1775 follower = insert(:user)
1776 follower2 = insert(:user)
1777 follower3 = insert(:user)
1779 {:ok, follower, user} = User.follow(follower, user)
1780 {:ok, _follower2, _user} = User.follow(follower2, user)
1781 {:ok, _follower3, _user} = User.follow(follower3, user)
1783 {:ok, _user_relationship} = User.block(user, follower)
1784 user = refresh_record(user)
1786 assert user.follower_count == 2
1789 describe "list_inactive_users_query/1" do
1790 defp days_ago(days) do
1792 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
1793 -days * 60 * 60 * 24,
1798 test "Users are inactive by default" do
1802 Enum.map(1..total, fn _ ->
1803 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1806 inactive_users_ids =
1807 Pleroma.User.list_inactive_users_query()
1808 |> Pleroma.Repo.all()
1809 |> Enum.map(& &1.id)
1811 Enum.each(users, fn user ->
1812 assert user.id in inactive_users_ids
1816 test "Only includes users who has no recent activity" do
1820 Enum.map(1..total, fn _ ->
1821 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1824 {inactive, active} = Enum.split(users, trunc(total / 2))
1826 Enum.map(active, fn user ->
1827 to = Enum.random(users -- [user])
1830 CommonAPI.post(user, %{
1831 status: "hey @#{to.nickname}"
1835 inactive_users_ids =
1836 Pleroma.User.list_inactive_users_query()
1837 |> Pleroma.Repo.all()
1838 |> Enum.map(& &1.id)
1840 Enum.each(active, fn user ->
1841 refute user.id in inactive_users_ids
1844 Enum.each(inactive, fn user ->
1845 assert user.id in inactive_users_ids
1849 test "Only includes users with no read notifications" do
1853 Enum.map(1..total, fn _ ->
1854 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1857 [sender | recipients] = users
1858 {inactive, active} = Enum.split(recipients, trunc(total / 2))
1860 Enum.each(recipients, fn to ->
1862 CommonAPI.post(sender, %{
1863 status: "hey @#{to.nickname}"
1867 CommonAPI.post(sender, %{
1868 status: "hey again @#{to.nickname}"
1872 Enum.each(active, fn user ->
1873 [n1, _n2] = Pleroma.Notification.for_user(user)
1874 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
1877 inactive_users_ids =
1878 Pleroma.User.list_inactive_users_query()
1879 |> Pleroma.Repo.all()
1880 |> Enum.map(& &1.id)
1882 Enum.each(active, fn user ->
1883 refute user.id in inactive_users_ids
1886 Enum.each(inactive, fn user ->
1887 assert user.id in inactive_users_ids
1892 describe "toggle_confirmation/1" do
1893 test "if user is confirmed" do
1894 user = insert(:user, confirmation_pending: false)
1895 {:ok, user} = User.toggle_confirmation(user)
1897 assert user.confirmation_pending
1898 assert user.confirmation_token
1901 test "if user is unconfirmed" do
1902 user = insert(:user, confirmation_pending: true, confirmation_token: "some token")
1903 {:ok, user} = User.toggle_confirmation(user)
1905 refute user.confirmation_pending
1906 refute user.confirmation_token
1910 describe "ensure_keys_present" do
1911 test "it creates keys for a user and stores them in info" do
1912 user = insert(:user)
1913 refute is_binary(user.keys)
1914 {:ok, user} = User.ensure_keys_present(user)
1915 assert is_binary(user.keys)
1918 test "it doesn't create keys if there already are some" do
1919 user = insert(:user, keys: "xxx")
1920 {:ok, user} = User.ensure_keys_present(user)
1921 assert user.keys == "xxx"
1925 describe "get_ap_ids_by_nicknames" do
1926 test "it returns a list of AP ids for a given set of nicknames" do
1927 user = insert(:user)
1928 user_two = insert(:user)
1930 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
1931 assert length(ap_ids) == 2
1932 assert user.ap_id in ap_ids
1933 assert user_two.ap_id in ap_ids
1937 describe "sync followers count" do
1939 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
1940 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
1941 insert(:user, local: true)
1942 insert(:user, local: false, deactivated: true)
1943 {:ok, user1: user1, user2: user2}
1946 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
1947 [fdb_user1] = User.external_users(limit: 1)
1949 assert fdb_user1.ap_id
1950 assert fdb_user1.ap_id == user1.ap_id
1951 assert fdb_user1.id == user1.id
1953 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
1955 assert fdb_user2.ap_id
1956 assert fdb_user2.ap_id == user2.ap_id
1957 assert fdb_user2.id == user2.id
1959 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
1963 describe "is_internal_user?/1" do
1964 test "non-internal user returns false" do
1965 user = insert(:user)
1966 refute User.is_internal_user?(user)
1969 test "user with no nickname returns true" do
1970 user = insert(:user, %{nickname: nil})
1971 assert User.is_internal_user?(user)
1974 test "user with internal-prefixed nickname returns true" do
1975 user = insert(:user, %{nickname: "internal.test"})
1976 assert User.is_internal_user?(user)
1980 describe "update_and_set_cache/1" do
1981 test "returns error when user is stale instead Ecto.StaleEntryError" do
1982 user = insert(:user)
1984 changeset = Ecto.Changeset.change(user, bio: "test")
1988 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
1989 User.update_and_set_cache(changeset)
1992 test "performs update cache if user updated" do
1993 user = insert(:user)
1994 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1996 changeset = Ecto.Changeset.change(user, bio: "test-bio")
1998 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
1999 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
2000 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
2004 describe "following/followers synchronization" do
2005 setup do: clear_config([:instance, :external_user_synchronization])
2007 test "updates the counters normally on following/getting a follow when disabled" do
2008 Pleroma.Config.put([:instance, :external_user_synchronization], false)
2009 user = insert(:user)
2014 follower_address: "http://localhost:4001/users/masto_closed/followers",
2015 following_address: "http://localhost:4001/users/masto_closed/following",
2019 assert other_user.following_count == 0
2020 assert other_user.follower_count == 0
2022 {:ok, user, other_user} = Pleroma.User.follow(user, other_user)
2024 assert user.following_count == 1
2025 assert other_user.follower_count == 1
2028 test "syncronizes the counters with the remote instance for the followed when enabled" do
2029 Pleroma.Config.put([:instance, :external_user_synchronization], false)
2031 user = insert(:user)
2036 follower_address: "http://localhost:4001/users/masto_closed/followers",
2037 following_address: "http://localhost:4001/users/masto_closed/following",
2041 assert other_user.following_count == 0
2042 assert other_user.follower_count == 0
2044 Pleroma.Config.put([:instance, :external_user_synchronization], true)
2045 {:ok, _user, other_user} = User.follow(user, other_user)
2047 assert other_user.follower_count == 437
2050 test "syncronizes the counters with the remote instance for the follower when enabled" do
2051 Pleroma.Config.put([:instance, :external_user_synchronization], false)
2053 user = insert(:user)
2058 follower_address: "http://localhost:4001/users/masto_closed/followers",
2059 following_address: "http://localhost:4001/users/masto_closed/following",
2063 assert other_user.following_count == 0
2064 assert other_user.follower_count == 0
2066 Pleroma.Config.put([:instance, :external_user_synchronization], true)
2067 {:ok, other_user, _user} = User.follow(other_user, user)
2069 assert other_user.following_count == 152
2073 describe "change_email/2" do
2075 [user: insert(:user)]
2078 test "blank email returns error", %{user: user} do
2079 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
2080 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
2083 test "non unique email returns error", %{user: user} do
2084 %{email: email} = insert(:user)
2086 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
2087 User.change_email(user, email)
2090 test "invalid email returns error", %{user: user} do
2091 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
2092 User.change_email(user, "cofe")
2095 test "changes email", %{user: user} do
2096 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
2100 describe "get_cached_by_nickname_or_id" do
2102 local_user = insert(:user)
2103 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
2105 [local_user: local_user, remote_user: remote_user]
2108 setup do: clear_config([:instance, :limit_to_local_content])
2110 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
2111 remote_user: remote_user
2113 Pleroma.Config.put([:instance, :limit_to_local_content], false)
2114 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2116 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2117 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2119 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2120 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2123 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
2124 %{remote_user: remote_user} do
2125 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2126 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2129 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
2130 %{remote_user: remote_user, local_user: local_user} do
2131 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2132 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
2135 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
2136 %{remote_user: remote_user} do
2137 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2138 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2141 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
2142 %{local_user: local_user} do
2143 Pleroma.Config.put([:instance, :limit_to_local_content], false)
2144 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2146 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2147 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2149 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2150 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2154 describe "update_email_notifications/2" do
2156 user = insert(:user, email_notifications: %{"digest" => true})
2161 test "Notifications are updated", %{user: user} do
2162 true = user.email_notifications["digest"]
2163 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
2164 assert result.email_notifications["digest"] == false
2168 test "avatar fallback" do
2169 user = insert(:user)
2170 assert User.avatar_url(user) =~ "/images/avi.png"
2172 clear_config([:assets, :default_user_avatar], "avatar.png")
2174 user = User.get_cached_by_nickname_or_id(user.nickname)
2175 assert User.avatar_url(user) =~ "avatar.png"
2177 assert User.avatar_url(user, no_default: true) == nil
2180 test "get_host/1" do
2181 user = insert(:user, ap_id: "https://lain.com/users/lain", nickname: "lain")
2182 assert User.get_host(user) == "lain.com"