Merge branch 'develop' into feature/expire-mutes
[akkoma] / test / user_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.UserTest do
6 alias Pleroma.Activity
7 alias Pleroma.Builders.UserBuilder
8 alias Pleroma.Object
9 alias Pleroma.Repo
10 alias Pleroma.Tests.ObanHelpers
11 alias Pleroma.User
12 alias Pleroma.Web.ActivityPub.ActivityPub
13 alias Pleroma.Web.CommonAPI
14
15 use Pleroma.DataCase
16 use Oban.Testing, repo: Pleroma.Repo
17
18 import Pleroma.Factory
19 import ExUnit.CaptureLog
20 import Swoosh.TestAssertions
21
22 setup_all do
23 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
24 :ok
25 end
26
27 setup do: clear_config([:instance, :account_activation_required])
28
29 describe "service actors" do
30 test "returns updated invisible actor" do
31 uri = "#{Pleroma.Web.Endpoint.url()}/relay"
32 followers_uri = "#{uri}/followers"
33
34 insert(
35 :user,
36 %{
37 nickname: "relay",
38 invisible: false,
39 local: true,
40 ap_id: uri,
41 follower_address: followers_uri
42 }
43 )
44
45 actor = User.get_or_create_service_actor_by_ap_id(uri, "relay")
46 assert actor.invisible
47 end
48
49 test "returns relay user" do
50 uri = "#{Pleroma.Web.Endpoint.url()}/relay"
51 followers_uri = "#{uri}/followers"
52
53 assert %User{
54 nickname: "relay",
55 invisible: true,
56 local: true,
57 ap_id: ^uri,
58 follower_address: ^followers_uri
59 } = User.get_or_create_service_actor_by_ap_id(uri, "relay")
60
61 assert capture_log(fn ->
62 refute User.get_or_create_service_actor_by_ap_id("/relay", "relay")
63 end) =~ "Cannot create service actor:"
64 end
65
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")
70
71 assert %User{
72 nickname: "internal.fetch-test",
73 invisible: true,
74 local: true,
75 ap_id: ^uri,
76 follower_address: ^followers_uri
77 } = user
78
79 user2 = User.get_or_create_service_actor_by_ap_id(uri, "internal.fetch-test")
80 assert user.id == user2.id
81 end
82 end
83
84 describe "AP ID user relationships" do
85 setup do
86 {:ok, user: insert(:user)}
87 end
88
89 test "outgoing_relationships_ap_ids/1", %{user: user} do
90 rel_types = [:block, :mute, :notification_mute, :reblog_mute, :inverse_subscription]
91
92 ap_ids_by_rel =
93 Enum.into(
94 rel_types,
95 %{},
96 fn rel_type ->
97 rel_records =
98 insert_list(2, :user_relationship, %{source: user, relationship_type: rel_type})
99
100 ap_ids = Enum.map(rel_records, fn rr -> Repo.preload(rr, :target).target.ap_id end)
101 {rel_type, Enum.sort(ap_ids)}
102 end
103 )
104
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))
107
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))
110
111 assert ap_ids_by_rel[:notification_mute] ==
112 Enum.sort(User.notification_muted_users_ap_ids(user))
113
114 assert ap_ids_by_rel[:notification_mute] ==
115 Enum.sort(Enum.map(User.notification_muted_users(user), & &1.ap_id))
116
117 assert ap_ids_by_rel[:reblog_mute] == Enum.sort(User.reblog_muted_users_ap_ids(user))
118
119 assert ap_ids_by_rel[:reblog_mute] ==
120 Enum.sort(Enum.map(User.reblog_muted_users(user), & &1.ap_id))
121
122 assert ap_ids_by_rel[:inverse_subscription] == Enum.sort(User.subscriber_users_ap_ids(user))
123
124 assert ap_ids_by_rel[:inverse_subscription] ==
125 Enum.sort(Enum.map(User.subscriber_users(user), & &1.ap_id))
126
127 outgoing_relationships_ap_ids = User.outgoing_relationships_ap_ids(user, rel_types)
128
129 assert ap_ids_by_rel ==
130 Enum.into(outgoing_relationships_ap_ids, %{}, fn {k, v} -> {k, Enum.sort(v)} end)
131 end
132 end
133
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"])
138
139 assert "cool" in user.tags
140 assert "dude" in user.tags
141 end
142
143 test "untagging a user" do
144 user = insert(:user, %{tags: nil})
145 user = User.untag(user, ["cool", "dude"])
146
147 assert user.tags == []
148 end
149 end
150
151 test "ap_id returns the activity pub id for the user" do
152 user = UserBuilder.build()
153
154 expected_ap_id = "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
155
156 assert expected_ap_id == User.ap_id(user)
157 end
158
159 test "ap_followers returns the followers collection for the user" do
160 user = UserBuilder.build()
161
162 expected_followers_collection = "#{User.ap_id(user)}/followers"
163
164 assert expected_followers_collection == User.ap_followers(user)
165 end
166
167 test "ap_following returns the following collection for the user" do
168 user = UserBuilder.build()
169
170 expected_followers_collection = "#{User.ap_id(user)}/following"
171
172 assert expected_followers_collection == User.ap_following(user)
173 end
174
175 test "returns all pending follow requests" do
176 unlocked = insert(:user)
177 locked = insert(:user, locked: true)
178 follower = insert(:user)
179
180 CommonAPI.follow(follower, unlocked)
181 CommonAPI.follow(follower, locked)
182
183 assert [] = User.get_follow_requests(unlocked)
184 assert [activity] = User.get_follow_requests(locked)
185
186 assert activity
187 end
188
189 test "doesn't return already accepted or duplicate follow requests" do
190 locked = insert(:user, locked: true)
191 pending_follower = insert(:user)
192 accepted_follower = insert(:user)
193
194 CommonAPI.follow(pending_follower, locked)
195 CommonAPI.follow(pending_follower, locked)
196 CommonAPI.follow(accepted_follower, locked)
197
198 Pleroma.FollowingRelationship.update(accepted_follower, locked, :follow_accept)
199
200 assert [^pending_follower] = User.get_follow_requests(locked)
201 end
202
203 test "doesn't return follow requests for deactivated accounts" do
204 locked = insert(:user, locked: true)
205 pending_follower = insert(:user, %{deactivated: true})
206
207 CommonAPI.follow(pending_follower, locked)
208
209 assert true == pending_follower.deactivated
210 assert [] = User.get_follow_requests(locked)
211 end
212
213 test "clears follow requests when requester is blocked" do
214 followed = insert(:user, locked: true)
215 follower = insert(:user)
216
217 CommonAPI.follow(follower, followed)
218 assert [_activity] = User.get_follow_requests(followed)
219
220 {:ok, _user_relationship} = User.block(followed, follower)
221 assert [] = User.get_follow_requests(followed)
222 end
223
224 test "follow_all follows mutliple users" do
225 user = insert(:user)
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)
232
233 {:ok, _user_relationship} = User.block(user, blocked)
234 {:ok, _user_relationship} = User.block(reverse_blocked, user)
235
236 {:ok, user} = User.follow(user, followed_zero)
237
238 {:ok, user} = User.follow_all(user, [followed_one, followed_two, blocked, reverse_blocked])
239
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)
246 end
247
248 test "follow_all follows mutliple users without duplicating" do
249 user = insert(:user)
250 followed_zero = insert(:user)
251 followed_one = insert(:user)
252 followed_two = insert(:user)
253
254 {:ok, user} = User.follow_all(user, [followed_zero, followed_one])
255 assert length(User.following(user)) == 3
256
257 {:ok, user} = User.follow_all(user, [followed_one, followed_two])
258 assert length(User.following(user)) == 4
259 end
260
261 test "follow takes a user and another user" do
262 user = insert(:user)
263 followed = insert(:user)
264
265 {:ok, user} = User.follow(user, followed)
266
267 user = User.get_cached_by_id(user.id)
268 followed = User.get_cached_by_ap_id(followed.ap_id)
269
270 assert followed.follower_count == 1
271 assert user.following_count == 1
272
273 assert User.ap_followers(followed) in User.following(user)
274 end
275
276 test "can't follow a deactivated users" do
277 user = insert(:user)
278 followed = insert(:user, %{deactivated: true})
279
280 {:error, _} = User.follow(user, followed)
281 end
282
283 test "can't follow a user who blocked us" do
284 blocker = insert(:user)
285 blockee = insert(:user)
286
287 {:ok, _user_relationship} = User.block(blocker, blockee)
288
289 {:error, _} = User.follow(blockee, blocker)
290 end
291
292 test "can't subscribe to a user who blocked us" do
293 blocker = insert(:user)
294 blocked = insert(:user)
295
296 {:ok, _user_relationship} = User.block(blocker, blocked)
297
298 {:error, _} = User.subscribe(blocked, blocker)
299 end
300
301 test "local users do not automatically follow local locked accounts" do
302 follower = insert(:user, locked: true)
303 followed = insert(:user, locked: true)
304
305 {:ok, follower} = User.maybe_direct_follow(follower, followed)
306
307 refute User.following?(follower, followed)
308 end
309
310 describe "unfollow/2" do
311 setup do: clear_config([:instance, :external_user_synchronization])
312
313 test "unfollow with syncronizes external user" do
314 Pleroma.Config.put([:instance, :external_user_synchronization], true)
315
316 followed =
317 insert(:user,
318 nickname: "fuser1",
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"
322 )
323
324 user =
325 insert(:user, %{
326 local: false,
327 nickname: "fuser2",
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"
331 })
332
333 {:ok, user} = User.follow(user, followed, :follow_accept)
334
335 {:ok, user, _activity} = User.unfollow(user, followed)
336
337 user = User.get_cached_by_id(user.id)
338
339 assert User.following(user) == []
340 end
341
342 test "unfollow takes a user and another user" do
343 followed = insert(:user)
344 user = insert(:user)
345
346 {:ok, user} = User.follow(user, followed, :follow_accept)
347
348 assert User.following(user) == [user.follower_address, followed.follower_address]
349
350 {:ok, user, _activity} = User.unfollow(user, followed)
351
352 assert User.following(user) == [user.follower_address]
353 end
354
355 test "unfollow doesn't unfollow yourself" do
356 user = insert(:user)
357
358 {:error, _} = User.unfollow(user, user)
359
360 assert User.following(user) == [user.follower_address]
361 end
362 end
363
364 test "test if a user is following another user" do
365 followed = insert(:user)
366 user = insert(:user)
367 User.follow(user, followed, :follow_accept)
368
369 assert User.following?(user, followed)
370 refute User.following?(followed, user)
371 end
372
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)
378 end
379
380 describe "user registration" do
381 @full_user_data %{
382 bio: "A guy",
383 name: "my name",
384 nickname: "nick",
385 password: "test",
386 password_confirmation: "test",
387 email: "email@example.com"
388 }
389
390 setup do: clear_config([:instance, :autofollowed_nicknames])
391 setup do: clear_config([:welcome])
392 setup do: clear_config([:instance, :account_activation_required])
393
394 test "it autofollows accounts that are set for it" do
395 user = insert(:user)
396 remote_user = insert(:user, %{local: false})
397
398 Pleroma.Config.put([:instance, :autofollowed_nicknames], [
399 user.nickname,
400 remote_user.nickname
401 ])
402
403 cng = User.register_changeset(%User{}, @full_user_data)
404
405 {:ok, registered_user} = User.register(cng)
406
407 assert User.following?(registered_user, user)
408 refute User.following?(registered_user, remote_user)
409 end
410
411 test "it sends a welcome message if it is set" do
412 welcome_user = insert(:user)
413 Pleroma.Config.put([:welcome, :direct_message, :enabled], true)
414 Pleroma.Config.put([:welcome, :direct_message, :sender_nickname], welcome_user.nickname)
415 Pleroma.Config.put([:welcome, :direct_message, :message], "Hello, this is a direct message")
416
417 cng = User.register_changeset(%User{}, @full_user_data)
418 {:ok, registered_user} = User.register(cng)
419 ObanHelpers.perform_all()
420
421 activity = Repo.one(Pleroma.Activity)
422 assert registered_user.ap_id in activity.recipients
423 assert Object.normalize(activity).data["content"] =~ "direct message"
424 assert activity.actor == welcome_user.ap_id
425 end
426
427 test "it sends a welcome chat message if it is set" do
428 welcome_user = insert(:user)
429 Pleroma.Config.put([:welcome, :chat_message, :enabled], true)
430 Pleroma.Config.put([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
431 Pleroma.Config.put([:welcome, :chat_message, :message], "Hello, this is a chat message")
432
433 cng = User.register_changeset(%User{}, @full_user_data)
434 {:ok, registered_user} = User.register(cng)
435 ObanHelpers.perform_all()
436
437 activity = Repo.one(Pleroma.Activity)
438 assert registered_user.ap_id in activity.recipients
439 assert Object.normalize(activity).data["content"] =~ "chat message"
440 assert activity.actor == welcome_user.ap_id
441 end
442
443 setup do:
444 clear_config(:mrf_simple,
445 media_removal: [],
446 media_nsfw: [],
447 federated_timeline_removal: [],
448 report_removal: [],
449 reject: [],
450 followers_only: [],
451 accept: [],
452 avatar_removal: [],
453 banner_removal: [],
454 reject_deletes: []
455 )
456
457 setup do:
458 clear_config(:mrf,
459 policies: [
460 Pleroma.Web.ActivityPub.MRF.SimplePolicy
461 ]
462 )
463
464 test "it sends a welcome chat message when Simple policy applied to local instance" do
465 Pleroma.Config.put([:mrf_simple, :media_nsfw], ["localhost"])
466
467 welcome_user = insert(:user)
468 Pleroma.Config.put([:welcome, :chat_message, :enabled], true)
469 Pleroma.Config.put([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
470 Pleroma.Config.put([:welcome, :chat_message, :message], "Hello, this is a chat message")
471
472 cng = User.register_changeset(%User{}, @full_user_data)
473 {:ok, registered_user} = User.register(cng)
474 ObanHelpers.perform_all()
475
476 activity = Repo.one(Pleroma.Activity)
477 assert registered_user.ap_id in activity.recipients
478 assert Object.normalize(activity).data["content"] =~ "chat message"
479 assert activity.actor == welcome_user.ap_id
480 end
481
482 test "it sends a welcome email message if it is set" do
483 welcome_user = insert(:user)
484 Pleroma.Config.put([:welcome, :email, :enabled], true)
485 Pleroma.Config.put([:welcome, :email, :sender], welcome_user.email)
486
487 Pleroma.Config.put(
488 [:welcome, :email, :subject],
489 "Hello, welcome to cool site: <%= instance_name %>"
490 )
491
492 instance_name = Pleroma.Config.get([:instance, :name])
493
494 cng = User.register_changeset(%User{}, @full_user_data)
495 {:ok, registered_user} = User.register(cng)
496 ObanHelpers.perform_all()
497
498 assert_email_sent(
499 from: {instance_name, welcome_user.email},
500 to: {registered_user.name, registered_user.email},
501 subject: "Hello, welcome to cool site: #{instance_name}",
502 html_body: "Welcome to #{instance_name}"
503 )
504 end
505
506 test "it sends a confirm email" do
507 Pleroma.Config.put([:instance, :account_activation_required], true)
508
509 cng = User.register_changeset(%User{}, @full_user_data)
510 {:ok, registered_user} = User.register(cng)
511 ObanHelpers.perform_all()
512 assert_email_sent(Pleroma.Emails.UserEmail.account_confirmation_email(registered_user))
513 end
514
515 test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do
516 Pleroma.Config.put([:instance, :account_activation_required], true)
517
518 @full_user_data
519 |> Map.keys()
520 |> Enum.each(fn key ->
521 params = Map.delete(@full_user_data, key)
522 changeset = User.register_changeset(%User{}, params)
523
524 assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
525 end)
526 end
527
528 test "it requires an name, nickname and password, bio and email are optional when account_activation_required is disabled" do
529 Pleroma.Config.put([:instance, :account_activation_required], false)
530
531 @full_user_data
532 |> Map.keys()
533 |> Enum.each(fn key ->
534 params = Map.delete(@full_user_data, key)
535 changeset = User.register_changeset(%User{}, params)
536
537 assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid?
538 end)
539 end
540
541 test "it restricts certain nicknames" do
542 [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
543
544 assert is_bitstring(restricted_name)
545
546 params =
547 @full_user_data
548 |> Map.put(:nickname, restricted_name)
549
550 changeset = User.register_changeset(%User{}, params)
551
552 refute changeset.valid?
553 end
554
555 test "it blocks blacklisted email domains" do
556 clear_config([User, :email_blacklist], ["trolling.world"])
557
558 # Block with match
559 params = Map.put(@full_user_data, :email, "troll@trolling.world")
560 changeset = User.register_changeset(%User{}, params)
561 refute changeset.valid?
562
563 # Block with subdomain match
564 params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world")
565 changeset = User.register_changeset(%User{}, params)
566 refute changeset.valid?
567
568 # Pass with different domains that are similar
569 params = Map.put(@full_user_data, :email, "troll@gnomestrolling.world")
570 changeset = User.register_changeset(%User{}, params)
571 assert changeset.valid?
572
573 params = Map.put(@full_user_data, :email, "troll@trolling.world.us")
574 changeset = User.register_changeset(%User{}, params)
575 assert changeset.valid?
576 end
577
578 test "it sets the password_hash and ap_id" do
579 changeset = User.register_changeset(%User{}, @full_user_data)
580
581 assert changeset.valid?
582
583 assert is_binary(changeset.changes[:password_hash])
584 assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
585
586 assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
587 end
588
589 test "it sets the 'accepts_chat_messages' set to true" do
590 changeset = User.register_changeset(%User{}, @full_user_data)
591 assert changeset.valid?
592
593 {:ok, user} = Repo.insert(changeset)
594
595 assert user.accepts_chat_messages
596 end
597
598 test "it creates a confirmed user" do
599 changeset = User.register_changeset(%User{}, @full_user_data)
600 assert changeset.valid?
601
602 {:ok, user} = Repo.insert(changeset)
603
604 refute user.confirmation_pending
605 end
606 end
607
608 describe "user registration, with :account_activation_required" do
609 @full_user_data %{
610 bio: "A guy",
611 name: "my name",
612 nickname: "nick",
613 password: "test",
614 password_confirmation: "test",
615 email: "email@example.com"
616 }
617 setup do: clear_config([:instance, :account_activation_required], true)
618
619 test "it creates unconfirmed user" do
620 changeset = User.register_changeset(%User{}, @full_user_data)
621 assert changeset.valid?
622
623 {:ok, user} = Repo.insert(changeset)
624
625 assert user.confirmation_pending
626 assert user.confirmation_token
627 end
628
629 test "it creates confirmed user if :confirmed option is given" do
630 changeset = User.register_changeset(%User{}, @full_user_data, need_confirmation: false)
631 assert changeset.valid?
632
633 {:ok, user} = Repo.insert(changeset)
634
635 refute user.confirmation_pending
636 refute user.confirmation_token
637 end
638 end
639
640 describe "user registration, with :account_approval_required" do
641 @full_user_data %{
642 bio: "A guy",
643 name: "my name",
644 nickname: "nick",
645 password: "test",
646 password_confirmation: "test",
647 email: "email@example.com",
648 registration_reason: "I'm a cool guy :)"
649 }
650 setup do: clear_config([:instance, :account_approval_required], true)
651
652 test "it creates unapproved user" do
653 changeset = User.register_changeset(%User{}, @full_user_data)
654 assert changeset.valid?
655
656 {:ok, user} = Repo.insert(changeset)
657
658 assert user.approval_pending
659 assert user.registration_reason == "I'm a cool guy :)"
660 end
661
662 test "it restricts length of registration reason" do
663 reason_limit = Pleroma.Config.get([:instance, :registration_reason_length])
664
665 assert is_integer(reason_limit)
666
667 params =
668 @full_user_data
669 |> Map.put(
670 :registration_reason,
671 "Quia et nesciunt dolores numquam ipsam nisi sapiente soluta. Ullam repudiandae nisi quam porro officiis officiis ad. Consequatur animi velit ex quia. Odit voluptatem perferendis quia ut nisi. Dignissimos sit soluta atque aliquid dolorem ut dolorum ut. Labore voluptates iste iusto amet voluptatum earum. Ad fugit illum nam eos ut nemo. Pariatur ea fuga non aspernatur. Dignissimos debitis officia corporis est nisi ab et. Atque itaque alias eius voluptas minus. Accusamus numquam tempore occaecati in."
672 )
673
674 changeset = User.register_changeset(%User{}, params)
675
676 refute changeset.valid?
677 end
678 end
679
680 describe "get_or_fetch/1" do
681 test "gets an existing user by nickname" do
682 user = insert(:user)
683 {:ok, fetched_user} = User.get_or_fetch(user.nickname)
684
685 assert user == fetched_user
686 end
687
688 test "gets an existing user by ap_id" do
689 ap_id = "http://mastodon.example.org/users/admin"
690
691 user =
692 insert(
693 :user,
694 local: false,
695 nickname: "admin@mastodon.example.org",
696 ap_id: ap_id
697 )
698
699 {:ok, fetched_user} = User.get_or_fetch(ap_id)
700 freshed_user = refresh_record(user)
701 assert freshed_user == fetched_user
702 end
703 end
704
705 describe "fetching a user from nickname or trying to build one" do
706 test "gets an existing user" do
707 user = insert(:user)
708 {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
709
710 assert user == fetched_user
711 end
712
713 test "gets an existing user, case insensitive" do
714 user = insert(:user, nickname: "nick")
715 {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
716
717 assert user == fetched_user
718 end
719
720 test "gets an existing user by fully qualified nickname" do
721 user = insert(:user)
722
723 {:ok, fetched_user} =
724 User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
725
726 assert user == fetched_user
727 end
728
729 test "gets an existing user by fully qualified nickname, case insensitive" do
730 user = insert(:user, nickname: "nick")
731 casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
732
733 {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
734
735 assert user == fetched_user
736 end
737
738 @tag capture_log: true
739 test "returns nil if no user could be fetched" do
740 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
741 assert fetched_user == "not found nonexistant@social.heldscal.la"
742 end
743
744 test "returns nil for nonexistant local user" do
745 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
746 assert fetched_user == "not found nonexistant"
747 end
748
749 test "updates an existing user, if stale" do
750 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
751
752 orig_user =
753 insert(
754 :user,
755 local: false,
756 nickname: "admin@mastodon.example.org",
757 ap_id: "http://mastodon.example.org/users/admin",
758 last_refreshed_at: a_week_ago
759 )
760
761 assert orig_user.last_refreshed_at == a_week_ago
762
763 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
764
765 assert user.inbox
766
767 refute user.last_refreshed_at == orig_user.last_refreshed_at
768 end
769
770 test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
771 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
772
773 orig_user =
774 insert(
775 :user,
776 local: false,
777 nickname: "admin@mastodon.example.org",
778 ap_id: "http://mastodon.example.org/users/harinezumigari",
779 last_refreshed_at: a_week_ago
780 )
781
782 assert orig_user.last_refreshed_at == a_week_ago
783
784 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
785
786 assert user.inbox
787
788 refute user.id == orig_user.id
789
790 orig_user = User.get_by_id(orig_user.id)
791
792 assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
793 end
794
795 @tag capture_log: true
796 test "it returns the old user if stale, but unfetchable" do
797 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
798
799 orig_user =
800 insert(
801 :user,
802 local: false,
803 nickname: "admin@mastodon.example.org",
804 ap_id: "http://mastodon.example.org/users/raymoo",
805 last_refreshed_at: a_week_ago
806 )
807
808 assert orig_user.last_refreshed_at == a_week_ago
809
810 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/raymoo")
811
812 assert user.last_refreshed_at == orig_user.last_refreshed_at
813 end
814 end
815
816 test "returns an ap_id for a user" do
817 user = insert(:user)
818
819 assert User.ap_id(user) ==
820 Pleroma.Web.Router.Helpers.user_feed_url(
821 Pleroma.Web.Endpoint,
822 :feed_redirect,
823 user.nickname
824 )
825 end
826
827 test "returns an ap_followers link for a user" do
828 user = insert(:user)
829
830 assert User.ap_followers(user) ==
831 Pleroma.Web.Router.Helpers.user_feed_url(
832 Pleroma.Web.Endpoint,
833 :feed_redirect,
834 user.nickname
835 ) <> "/followers"
836 end
837
838 describe "remote user changeset" do
839 @valid_remote %{
840 bio: "hello",
841 name: "Someone",
842 nickname: "a@b.de",
843 ap_id: "http...",
844 avatar: %{some: "avatar"}
845 }
846 setup do: clear_config([:instance, :user_bio_length])
847 setup do: clear_config([:instance, :user_name_length])
848
849 test "it confirms validity" do
850 cs = User.remote_user_changeset(@valid_remote)
851 assert cs.valid?
852 end
853
854 test "it sets the follower_adress" do
855 cs = User.remote_user_changeset(@valid_remote)
856 # remote users get a fake local follower address
857 assert cs.changes.follower_address ==
858 User.ap_followers(%User{nickname: @valid_remote[:nickname]})
859 end
860
861 test "it enforces the fqn format for nicknames" do
862 cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})
863 assert Ecto.Changeset.get_field(cs, :local) == false
864 assert cs.changes.avatar
865 refute cs.valid?
866 end
867
868 test "it has required fields" do
869 [:ap_id]
870 |> Enum.each(fn field ->
871 cs = User.remote_user_changeset(Map.delete(@valid_remote, field))
872 refute cs.valid?
873 end)
874 end
875 end
876
877 describe "followers and friends" do
878 test "gets all followers for a given user" do
879 user = insert(:user)
880 follower_one = insert(:user)
881 follower_two = insert(:user)
882 not_follower = insert(:user)
883
884 {:ok, follower_one} = User.follow(follower_one, user)
885 {:ok, follower_two} = User.follow(follower_two, user)
886
887 res = User.get_followers(user)
888
889 assert Enum.member?(res, follower_one)
890 assert Enum.member?(res, follower_two)
891 refute Enum.member?(res, not_follower)
892 end
893
894 test "gets all friends (followed users) for a given user" do
895 user = insert(:user)
896 followed_one = insert(:user)
897 followed_two = insert(:user)
898 not_followed = insert(:user)
899
900 {:ok, user} = User.follow(user, followed_one)
901 {:ok, user} = User.follow(user, followed_two)
902
903 res = User.get_friends(user)
904
905 followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
906 followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
907 assert Enum.member?(res, followed_one)
908 assert Enum.member?(res, followed_two)
909 refute Enum.member?(res, not_followed)
910 end
911 end
912
913 describe "updating note and follower count" do
914 test "it sets the note_count property" do
915 note = insert(:note)
916
917 user = User.get_cached_by_ap_id(note.data["actor"])
918
919 assert user.note_count == 0
920
921 {:ok, user} = User.update_note_count(user)
922
923 assert user.note_count == 1
924 end
925
926 test "it increases the note_count property" do
927 note = insert(:note)
928 user = User.get_cached_by_ap_id(note.data["actor"])
929
930 assert user.note_count == 0
931
932 {:ok, user} = User.increase_note_count(user)
933
934 assert user.note_count == 1
935
936 {:ok, user} = User.increase_note_count(user)
937
938 assert user.note_count == 2
939 end
940
941 test "it decreases the note_count property" do
942 note = insert(:note)
943 user = User.get_cached_by_ap_id(note.data["actor"])
944
945 assert user.note_count == 0
946
947 {:ok, user} = User.increase_note_count(user)
948
949 assert user.note_count == 1
950
951 {:ok, user} = User.decrease_note_count(user)
952
953 assert user.note_count == 0
954
955 {:ok, user} = User.decrease_note_count(user)
956
957 assert user.note_count == 0
958 end
959
960 test "it sets the follower_count property" do
961 user = insert(:user)
962 follower = insert(:user)
963
964 User.follow(follower, user)
965
966 assert user.follower_count == 0
967
968 {:ok, user} = User.update_follower_count(user)
969
970 assert user.follower_count == 1
971 end
972 end
973
974 describe "follow_import" do
975 test "it imports user followings from list" do
976 [user1, user2, user3] = insert_list(3, :user)
977
978 identifiers = [
979 user2.ap_id,
980 user3.nickname
981 ]
982
983 {:ok, job} = User.follow_import(user1, identifiers)
984
985 assert {:ok, result} = ObanHelpers.perform(job)
986 assert is_list(result)
987 assert result == [user2, user3]
988 end
989 end
990
991 describe "mutes" do
992 test "it mutes people" do
993 user = insert(:user)
994 muted_user = insert(:user)
995
996 refute User.mutes?(user, muted_user)
997 refute User.muted_notifications?(user, muted_user)
998
999 {:ok, _user_relationships} = User.mute(user, muted_user)
1000
1001 assert User.mutes?(user, muted_user)
1002 assert User.muted_notifications?(user, muted_user)
1003 end
1004
1005 test "expiring" do
1006 user = insert(:user)
1007 muted_user = insert(:user)
1008
1009 {:ok, _user_relationships} = User.mute(user, muted_user, %{expires_in: 60})
1010 assert User.mutes?(user, muted_user)
1011
1012 worker = Pleroma.Workers.MuteExpireWorker
1013 args = %{"op" => "unmute_user", "muter_id" => user.id, "mutee_id" => muted_user.id}
1014
1015 assert_enqueued(
1016 worker: worker,
1017 args: args
1018 )
1019
1020 assert :ok = perform_job(worker, args)
1021
1022 refute User.mutes?(user, muted_user)
1023 refute User.muted_notifications?(user, muted_user)
1024 end
1025
1026 test "it unmutes users" do
1027 user = insert(:user)
1028 muted_user = insert(:user)
1029
1030 {:ok, _user_relationships} = User.mute(user, muted_user)
1031 {:ok, _user_mute} = User.unmute(user, muted_user)
1032
1033 refute User.mutes?(user, muted_user)
1034 refute User.muted_notifications?(user, muted_user)
1035 end
1036
1037 test "it mutes user without notifications" do
1038 user = insert(:user)
1039 muted_user = insert(:user)
1040
1041 refute User.mutes?(user, muted_user)
1042 refute User.muted_notifications?(user, muted_user)
1043
1044 {:ok, _user_relationships} = User.mute(user, muted_user, %{notifications: false})
1045
1046 assert User.mutes?(user, muted_user)
1047 refute User.muted_notifications?(user, muted_user)
1048 end
1049 end
1050
1051 describe "blocks" do
1052 test "it blocks people" do
1053 user = insert(:user)
1054 blocked_user = insert(:user)
1055
1056 refute User.blocks?(user, blocked_user)
1057
1058 {:ok, _user_relationship} = User.block(user, blocked_user)
1059
1060 assert User.blocks?(user, blocked_user)
1061 end
1062
1063 test "it unblocks users" do
1064 user = insert(:user)
1065 blocked_user = insert(:user)
1066
1067 {:ok, _user_relationship} = User.block(user, blocked_user)
1068 {:ok, _user_block} = User.unblock(user, blocked_user)
1069
1070 refute User.blocks?(user, blocked_user)
1071 end
1072
1073 test "blocks tear down cyclical follow relationships" do
1074 blocker = insert(:user)
1075 blocked = insert(:user)
1076
1077 {:ok, blocker} = User.follow(blocker, blocked)
1078 {:ok, blocked} = User.follow(blocked, blocker)
1079
1080 assert User.following?(blocker, blocked)
1081 assert User.following?(blocked, blocker)
1082
1083 {:ok, _user_relationship} = User.block(blocker, blocked)
1084 blocked = User.get_cached_by_id(blocked.id)
1085
1086 assert User.blocks?(blocker, blocked)
1087
1088 refute User.following?(blocker, blocked)
1089 refute User.following?(blocked, blocker)
1090 end
1091
1092 test "blocks tear down blocker->blocked follow relationships" do
1093 blocker = insert(:user)
1094 blocked = insert(:user)
1095
1096 {:ok, blocker} = User.follow(blocker, blocked)
1097
1098 assert User.following?(blocker, blocked)
1099 refute User.following?(blocked, blocker)
1100
1101 {:ok, _user_relationship} = User.block(blocker, blocked)
1102 blocked = User.get_cached_by_id(blocked.id)
1103
1104 assert User.blocks?(blocker, blocked)
1105
1106 refute User.following?(blocker, blocked)
1107 refute User.following?(blocked, blocker)
1108 end
1109
1110 test "blocks tear down blocked->blocker follow relationships" do
1111 blocker = insert(:user)
1112 blocked = insert(:user)
1113
1114 {:ok, blocked} = User.follow(blocked, blocker)
1115
1116 refute User.following?(blocker, blocked)
1117 assert User.following?(blocked, blocker)
1118
1119 {:ok, _user_relationship} = User.block(blocker, blocked)
1120 blocked = User.get_cached_by_id(blocked.id)
1121
1122 assert User.blocks?(blocker, blocked)
1123
1124 refute User.following?(blocker, blocked)
1125 refute User.following?(blocked, blocker)
1126 end
1127
1128 test "blocks tear down blocked->blocker subscription relationships" do
1129 blocker = insert(:user)
1130 blocked = insert(:user)
1131
1132 {:ok, _subscription} = User.subscribe(blocked, blocker)
1133
1134 assert User.subscribed_to?(blocked, blocker)
1135 refute User.subscribed_to?(blocker, blocked)
1136
1137 {:ok, _user_relationship} = User.block(blocker, blocked)
1138
1139 assert User.blocks?(blocker, blocked)
1140 refute User.subscribed_to?(blocker, blocked)
1141 refute User.subscribed_to?(blocked, blocker)
1142 end
1143 end
1144
1145 describe "domain blocking" do
1146 test "blocks domains" do
1147 user = insert(:user)
1148 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1149
1150 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1151
1152 assert User.blocks?(user, collateral_user)
1153 end
1154
1155 test "does not block domain with same end" do
1156 user = insert(:user)
1157
1158 collateral_user =
1159 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1160
1161 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1162
1163 refute User.blocks?(user, collateral_user)
1164 end
1165
1166 test "does not block domain with same end if wildcard added" do
1167 user = insert(:user)
1168
1169 collateral_user =
1170 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1171
1172 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1173
1174 refute User.blocks?(user, collateral_user)
1175 end
1176
1177 test "blocks domain with wildcard for subdomain" do
1178 user = insert(:user)
1179
1180 user_from_subdomain =
1181 insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
1182
1183 user_with_two_subdomains =
1184 insert(:user, %{
1185 ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
1186 })
1187
1188 user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1189
1190 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1191
1192 assert User.blocks?(user, user_from_subdomain)
1193 assert User.blocks?(user, user_with_two_subdomains)
1194 assert User.blocks?(user, user_domain)
1195 end
1196
1197 test "unblocks domains" do
1198 user = insert(:user)
1199 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1200
1201 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1202 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
1203
1204 refute User.blocks?(user, collateral_user)
1205 end
1206
1207 test "follows take precedence over domain blocks" do
1208 user = insert(:user)
1209 good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
1210
1211 {:ok, user} = User.block_domain(user, "meanies.social")
1212 {:ok, user} = User.follow(user, good_eggo)
1213
1214 refute User.blocks?(user, good_eggo)
1215 end
1216 end
1217
1218 describe "blocks_import" do
1219 test "it imports user blocks from list" do
1220 [user1, user2, user3] = insert_list(3, :user)
1221
1222 identifiers = [
1223 user2.ap_id,
1224 user3.nickname
1225 ]
1226
1227 {:ok, job} = User.blocks_import(user1, identifiers)
1228
1229 assert {:ok, result} = ObanHelpers.perform(job)
1230 assert is_list(result)
1231 assert result == [user2, user3]
1232 end
1233 end
1234
1235 describe "get_recipients_from_activity" do
1236 test "works for announces" do
1237 actor = insert(:user)
1238 user = insert(:user, local: true)
1239
1240 {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
1241 {:ok, announce} = CommonAPI.repeat(activity.id, user)
1242
1243 recipients = User.get_recipients_from_activity(announce)
1244
1245 assert user in recipients
1246 end
1247
1248 test "get recipients" do
1249 actor = insert(:user)
1250 user = insert(:user, local: true)
1251 user_two = insert(:user, local: false)
1252 addressed = insert(:user, local: true)
1253 addressed_remote = insert(:user, local: false)
1254
1255 {:ok, activity} =
1256 CommonAPI.post(actor, %{
1257 status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
1258 })
1259
1260 assert Enum.map([actor, addressed], & &1.ap_id) --
1261 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1262
1263 {:ok, user} = User.follow(user, actor)
1264 {:ok, _user_two} = User.follow(user_two, actor)
1265 recipients = User.get_recipients_from_activity(activity)
1266 assert length(recipients) == 3
1267 assert user in recipients
1268 assert addressed in recipients
1269 end
1270
1271 test "has following" do
1272 actor = insert(:user)
1273 user = insert(:user)
1274 user_two = insert(:user)
1275 addressed = insert(:user, local: true)
1276
1277 {:ok, activity} =
1278 CommonAPI.post(actor, %{
1279 status: "hey @#{addressed.nickname}"
1280 })
1281
1282 assert Enum.map([actor, addressed], & &1.ap_id) --
1283 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1284
1285 {:ok, _actor} = User.follow(actor, user)
1286 {:ok, _actor} = User.follow(actor, user_two)
1287 recipients = User.get_recipients_from_activity(activity)
1288 assert length(recipients) == 2
1289 assert addressed in recipients
1290 end
1291 end
1292
1293 describe ".deactivate" do
1294 test "can de-activate then re-activate a user" do
1295 user = insert(:user)
1296 assert false == user.deactivated
1297 {:ok, user} = User.deactivate(user)
1298 assert true == user.deactivated
1299 {:ok, user} = User.deactivate(user, false)
1300 assert false == user.deactivated
1301 end
1302
1303 test "hide a user from followers" do
1304 user = insert(:user)
1305 user2 = insert(:user)
1306
1307 {:ok, user} = User.follow(user, user2)
1308 {:ok, _user} = User.deactivate(user)
1309
1310 user2 = User.get_cached_by_id(user2.id)
1311
1312 assert user2.follower_count == 0
1313 assert [] = User.get_followers(user2)
1314 end
1315
1316 test "hide a user from friends" do
1317 user = insert(:user)
1318 user2 = insert(:user)
1319
1320 {:ok, user2} = User.follow(user2, user)
1321 assert user2.following_count == 1
1322 assert User.following_count(user2) == 1
1323
1324 {:ok, _user} = User.deactivate(user)
1325
1326 user2 = User.get_cached_by_id(user2.id)
1327
1328 assert refresh_record(user2).following_count == 0
1329 assert user2.following_count == 0
1330 assert User.following_count(user2) == 0
1331 assert [] = User.get_friends(user2)
1332 end
1333
1334 test "hide a user's statuses from timelines and notifications" do
1335 user = insert(:user)
1336 user2 = insert(:user)
1337
1338 {:ok, user2} = User.follow(user2, user)
1339
1340 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
1341
1342 activity = Repo.preload(activity, :bookmark)
1343
1344 [notification] = Pleroma.Notification.for_user(user2)
1345 assert notification.activity.id == activity.id
1346
1347 assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
1348
1349 assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
1350 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1351 user: user2
1352 })
1353
1354 {:ok, _user} = User.deactivate(user)
1355
1356 assert [] == ActivityPub.fetch_public_activities(%{})
1357 assert [] == Pleroma.Notification.for_user(user2)
1358
1359 assert [] ==
1360 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1361 user: user2
1362 })
1363 end
1364 end
1365
1366 describe "approve" do
1367 test "approves a user" do
1368 user = insert(:user, approval_pending: true)
1369 assert true == user.approval_pending
1370 {:ok, user} = User.approve(user)
1371 assert false == user.approval_pending
1372 end
1373
1374 test "approves a list of users" do
1375 unapproved_users = [
1376 insert(:user, approval_pending: true),
1377 insert(:user, approval_pending: true),
1378 insert(:user, approval_pending: true)
1379 ]
1380
1381 {:ok, users} = User.approve(unapproved_users)
1382
1383 assert Enum.count(users) == 3
1384
1385 Enum.each(users, fn user ->
1386 assert false == user.approval_pending
1387 end)
1388 end
1389 end
1390
1391 describe "delete" do
1392 setup do
1393 {:ok, user} = insert(:user) |> User.set_cache()
1394
1395 [user: user]
1396 end
1397
1398 setup do: clear_config([:instance, :federating])
1399
1400 test ".delete_user_activities deletes all create activities", %{user: user} do
1401 {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
1402
1403 User.delete_user_activities(user)
1404
1405 # TODO: Test removal favorites, repeats, delete activities.
1406 refute Activity.get_by_id(activity.id)
1407 end
1408
1409 test "it deactivates a user, all follow relationships and all activities", %{user: user} do
1410 follower = insert(:user)
1411 {:ok, follower} = User.follow(follower, user)
1412
1413 locked_user = insert(:user, name: "locked", locked: true)
1414 {:ok, _} = User.follow(user, locked_user, :follow_pending)
1415
1416 object = insert(:note, user: user)
1417 activity = insert(:note_activity, user: user, note: object)
1418
1419 object_two = insert(:note, user: follower)
1420 activity_two = insert(:note_activity, user: follower, note: object_two)
1421
1422 {:ok, like} = CommonAPI.favorite(user, activity_two.id)
1423 {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
1424 {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
1425
1426 {:ok, job} = User.delete(user)
1427 {:ok, _user} = ObanHelpers.perform(job)
1428
1429 follower = User.get_cached_by_id(follower.id)
1430
1431 refute User.following?(follower, user)
1432 assert %{deactivated: true} = User.get_by_id(user.id)
1433
1434 assert [] == User.get_follow_requests(locked_user)
1435
1436 user_activities =
1437 user.ap_id
1438 |> Activity.Queries.by_actor()
1439 |> Repo.all()
1440 |> Enum.map(fn act -> act.data["type"] end)
1441
1442 assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
1443
1444 refute Activity.get_by_id(activity.id)
1445 refute Activity.get_by_id(like.id)
1446 refute Activity.get_by_id(like_two.id)
1447 refute Activity.get_by_id(repeat.id)
1448 end
1449 end
1450
1451 describe "delete/1 when confirmation is pending" do
1452 setup do
1453 user = insert(:user, confirmation_pending: true)
1454 {:ok, user: user}
1455 end
1456
1457 test "deletes user from database when activation required", %{user: user} do
1458 clear_config([:instance, :account_activation_required], true)
1459
1460 {:ok, job} = User.delete(user)
1461 {:ok, _} = ObanHelpers.perform(job)
1462
1463 refute User.get_cached_by_id(user.id)
1464 refute User.get_by_id(user.id)
1465 end
1466
1467 test "deactivates user when activation is not required", %{user: user} do
1468 clear_config([:instance, :account_activation_required], false)
1469
1470 {:ok, job} = User.delete(user)
1471 {:ok, _} = ObanHelpers.perform(job)
1472
1473 assert %{deactivated: true} = User.get_cached_by_id(user.id)
1474 assert %{deactivated: true} = User.get_by_id(user.id)
1475 end
1476 end
1477
1478 test "delete/1 when approval is pending deletes the user" do
1479 user = insert(:user, approval_pending: true)
1480
1481 {:ok, job} = User.delete(user)
1482 {:ok, _} = ObanHelpers.perform(job)
1483
1484 refute User.get_cached_by_id(user.id)
1485 refute User.get_by_id(user.id)
1486 end
1487
1488 test "delete/1 purges a user when they wouldn't be fully deleted" do
1489 user =
1490 insert(:user, %{
1491 bio: "eyy lmao",
1492 name: "qqqqqqq",
1493 password_hash: "pdfk2$1b3n159001",
1494 keys: "RSA begin buplic key",
1495 public_key: "--PRIVATE KEYE--",
1496 avatar: %{"a" => "b"},
1497 tags: ["qqqqq"],
1498 banner: %{"a" => "b"},
1499 background: %{"a" => "b"},
1500 note_count: 9,
1501 follower_count: 9,
1502 following_count: 9001,
1503 locked: true,
1504 confirmation_pending: true,
1505 password_reset_pending: true,
1506 approval_pending: true,
1507 registration_reason: "ahhhhh",
1508 confirmation_token: "qqqq",
1509 domain_blocks: ["lain.com"],
1510 deactivated: true,
1511 ap_enabled: true,
1512 is_moderator: true,
1513 is_admin: true,
1514 mastofe_settings: %{"a" => "b"},
1515 mascot: %{"a" => "b"},
1516 emoji: %{"a" => "b"},
1517 pleroma_settings_store: %{"q" => "x"},
1518 fields: [%{"gg" => "qq"}],
1519 raw_fields: [%{"gg" => "qq"}],
1520 discoverable: true,
1521 also_known_as: ["https://lol.olo/users/loll"]
1522 })
1523
1524 {:ok, job} = User.delete(user)
1525 {:ok, _} = ObanHelpers.perform(job)
1526 user = User.get_by_id(user.id)
1527
1528 assert %User{
1529 bio: "",
1530 raw_bio: nil,
1531 email: nil,
1532 name: nil,
1533 password_hash: nil,
1534 keys: nil,
1535 public_key: nil,
1536 avatar: %{},
1537 tags: [],
1538 last_refreshed_at: nil,
1539 last_digest_emailed_at: nil,
1540 banner: %{},
1541 background: %{},
1542 note_count: 0,
1543 follower_count: 0,
1544 following_count: 0,
1545 locked: false,
1546 confirmation_pending: false,
1547 password_reset_pending: false,
1548 approval_pending: false,
1549 registration_reason: nil,
1550 confirmation_token: nil,
1551 domain_blocks: [],
1552 deactivated: true,
1553 ap_enabled: false,
1554 is_moderator: false,
1555 is_admin: false,
1556 mastofe_settings: nil,
1557 mascot: nil,
1558 emoji: %{},
1559 pleroma_settings_store: %{},
1560 fields: [],
1561 raw_fields: [],
1562 discoverable: false,
1563 also_known_as: []
1564 } = user
1565 end
1566
1567 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1568 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1569 end
1570
1571 describe "per-user rich-text filtering" do
1572 test "html_filter_policy returns default policies, when rich-text is enabled" do
1573 user = insert(:user)
1574
1575 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1576 end
1577
1578 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1579 user = insert(:user, no_rich_text: true)
1580
1581 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1582 end
1583 end
1584
1585 describe "caching" do
1586 test "invalidate_cache works" do
1587 user = insert(:user)
1588
1589 User.set_cache(user)
1590 User.invalidate_cache(user)
1591
1592 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1593 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1594 end
1595
1596 test "User.delete() plugs any possible zombie objects" do
1597 user = insert(:user)
1598
1599 {:ok, job} = User.delete(user)
1600 {:ok, _} = ObanHelpers.perform(job)
1601
1602 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1603
1604 assert cached_user != user
1605
1606 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1607
1608 assert cached_user != user
1609 end
1610 end
1611
1612 describe "account_status/1" do
1613 setup do: clear_config([:instance, :account_activation_required])
1614
1615 test "return confirmation_pending for unconfirm user" do
1616 Pleroma.Config.put([:instance, :account_activation_required], true)
1617 user = insert(:user, confirmation_pending: true)
1618 assert User.account_status(user) == :confirmation_pending
1619 end
1620
1621 test "return active for confirmed user" do
1622 Pleroma.Config.put([:instance, :account_activation_required], true)
1623 user = insert(:user, confirmation_pending: false)
1624 assert User.account_status(user) == :active
1625 end
1626
1627 test "return active for remote user" do
1628 user = insert(:user, local: false)
1629 assert User.account_status(user) == :active
1630 end
1631
1632 test "returns :password_reset_pending for user with reset password" do
1633 user = insert(:user, password_reset_pending: true)
1634 assert User.account_status(user) == :password_reset_pending
1635 end
1636
1637 test "returns :deactivated for deactivated user" do
1638 user = insert(:user, local: true, confirmation_pending: false, deactivated: true)
1639 assert User.account_status(user) == :deactivated
1640 end
1641
1642 test "returns :approval_pending for unapproved user" do
1643 user = insert(:user, local: true, approval_pending: true)
1644 assert User.account_status(user) == :approval_pending
1645
1646 user = insert(:user, local: true, confirmation_pending: true, approval_pending: true)
1647 assert User.account_status(user) == :approval_pending
1648 end
1649 end
1650
1651 describe "superuser?/1" do
1652 test "returns false for unprivileged users" do
1653 user = insert(:user, local: true)
1654
1655 refute User.superuser?(user)
1656 end
1657
1658 test "returns false for remote users" do
1659 user = insert(:user, local: false)
1660 remote_admin_user = insert(:user, local: false, is_admin: true)
1661
1662 refute User.superuser?(user)
1663 refute User.superuser?(remote_admin_user)
1664 end
1665
1666 test "returns true for local moderators" do
1667 user = insert(:user, local: true, is_moderator: true)
1668
1669 assert User.superuser?(user)
1670 end
1671
1672 test "returns true for local admins" do
1673 user = insert(:user, local: true, is_admin: true)
1674
1675 assert User.superuser?(user)
1676 end
1677 end
1678
1679 describe "invisible?/1" do
1680 test "returns true for an invisible user" do
1681 user = insert(:user, local: true, invisible: true)
1682
1683 assert User.invisible?(user)
1684 end
1685
1686 test "returns false for a non-invisible user" do
1687 user = insert(:user, local: true)
1688
1689 refute User.invisible?(user)
1690 end
1691 end
1692
1693 describe "visible_for/2" do
1694 test "returns true when the account is itself" do
1695 user = insert(:user, local: true)
1696
1697 assert User.visible_for(user, user) == :visible
1698 end
1699
1700 test "returns false when the account is unconfirmed and confirmation is required" do
1701 Pleroma.Config.put([:instance, :account_activation_required], true)
1702
1703 user = insert(:user, local: true, confirmation_pending: true)
1704 other_user = insert(:user, local: true)
1705
1706 refute User.visible_for(user, other_user) == :visible
1707 end
1708
1709 test "returns true when the account is unconfirmed and confirmation is required but the account is remote" do
1710 Pleroma.Config.put([:instance, :account_activation_required], true)
1711
1712 user = insert(:user, local: false, confirmation_pending: true)
1713 other_user = insert(:user, local: true)
1714
1715 assert User.visible_for(user, other_user) == :visible
1716 end
1717
1718 test "returns true when the account is unconfirmed and confirmation is not required" do
1719 user = insert(:user, local: true, confirmation_pending: true)
1720 other_user = insert(:user, local: true)
1721
1722 assert User.visible_for(user, other_user) == :visible
1723 end
1724
1725 test "returns true when the account is unconfirmed and being viewed by a privileged account (confirmation required)" do
1726 Pleroma.Config.put([:instance, :account_activation_required], true)
1727
1728 user = insert(:user, local: true, confirmation_pending: true)
1729 other_user = insert(:user, local: true, is_admin: true)
1730
1731 assert User.visible_for(user, other_user) == :visible
1732 end
1733 end
1734
1735 describe "parse_bio/2" do
1736 test "preserves hosts in user links text" do
1737 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1738 user = insert(:user)
1739 bio = "A.k.a. @nick@domain.com"
1740
1741 expected_text =
1742 ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
1743 remote_user.ap_id
1744 }" rel="ugc">@<span>nick@domain.com</span></a></span>)
1745
1746 assert expected_text == User.parse_bio(bio, user)
1747 end
1748
1749 test "Adds rel=me on linkbacked urls" do
1750 user = insert(:user, ap_id: "https://social.example.org/users/lain")
1751
1752 bio = "http://example.com/rel_me/null"
1753 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1754 assert expected_text == User.parse_bio(bio, user)
1755
1756 bio = "http://example.com/rel_me/link"
1757 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1758 assert expected_text == User.parse_bio(bio, user)
1759
1760 bio = "http://example.com/rel_me/anchor"
1761 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1762 assert expected_text == User.parse_bio(bio, user)
1763 end
1764 end
1765
1766 test "follower count is updated when a follower is blocked" do
1767 user = insert(:user)
1768 follower = insert(:user)
1769 follower2 = insert(:user)
1770 follower3 = insert(:user)
1771
1772 {:ok, follower} = User.follow(follower, user)
1773 {:ok, _follower2} = User.follow(follower2, user)
1774 {:ok, _follower3} = User.follow(follower3, user)
1775
1776 {:ok, _user_relationship} = User.block(user, follower)
1777 user = refresh_record(user)
1778
1779 assert user.follower_count == 2
1780 end
1781
1782 describe "list_inactive_users_query/1" do
1783 defp days_ago(days) do
1784 NaiveDateTime.add(
1785 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
1786 -days * 60 * 60 * 24,
1787 :second
1788 )
1789 end
1790
1791 test "Users are inactive by default" do
1792 total = 10
1793
1794 users =
1795 Enum.map(1..total, fn _ ->
1796 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1797 end)
1798
1799 inactive_users_ids =
1800 Pleroma.User.list_inactive_users_query()
1801 |> Pleroma.Repo.all()
1802 |> Enum.map(& &1.id)
1803
1804 Enum.each(users, fn user ->
1805 assert user.id in inactive_users_ids
1806 end)
1807 end
1808
1809 test "Only includes users who has no recent activity" do
1810 total = 10
1811
1812 users =
1813 Enum.map(1..total, fn _ ->
1814 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1815 end)
1816
1817 {inactive, active} = Enum.split(users, trunc(total / 2))
1818
1819 Enum.map(active, fn user ->
1820 to = Enum.random(users -- [user])
1821
1822 {:ok, _} =
1823 CommonAPI.post(user, %{
1824 status: "hey @#{to.nickname}"
1825 })
1826 end)
1827
1828 inactive_users_ids =
1829 Pleroma.User.list_inactive_users_query()
1830 |> Pleroma.Repo.all()
1831 |> Enum.map(& &1.id)
1832
1833 Enum.each(active, fn user ->
1834 refute user.id in inactive_users_ids
1835 end)
1836
1837 Enum.each(inactive, fn user ->
1838 assert user.id in inactive_users_ids
1839 end)
1840 end
1841
1842 test "Only includes users with no read notifications" do
1843 total = 10
1844
1845 users =
1846 Enum.map(1..total, fn _ ->
1847 insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
1848 end)
1849
1850 [sender | recipients] = users
1851 {inactive, active} = Enum.split(recipients, trunc(total / 2))
1852
1853 Enum.each(recipients, fn to ->
1854 {:ok, _} =
1855 CommonAPI.post(sender, %{
1856 status: "hey @#{to.nickname}"
1857 })
1858
1859 {:ok, _} =
1860 CommonAPI.post(sender, %{
1861 status: "hey again @#{to.nickname}"
1862 })
1863 end)
1864
1865 Enum.each(active, fn user ->
1866 [n1, _n2] = Pleroma.Notification.for_user(user)
1867 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
1868 end)
1869
1870 inactive_users_ids =
1871 Pleroma.User.list_inactive_users_query()
1872 |> Pleroma.Repo.all()
1873 |> Enum.map(& &1.id)
1874
1875 Enum.each(active, fn user ->
1876 refute user.id in inactive_users_ids
1877 end)
1878
1879 Enum.each(inactive, fn user ->
1880 assert user.id in inactive_users_ids
1881 end)
1882 end
1883 end
1884
1885 describe "toggle_confirmation/1" do
1886 test "if user is confirmed" do
1887 user = insert(:user, confirmation_pending: false)
1888 {:ok, user} = User.toggle_confirmation(user)
1889
1890 assert user.confirmation_pending
1891 assert user.confirmation_token
1892 end
1893
1894 test "if user is unconfirmed" do
1895 user = insert(:user, confirmation_pending: true, confirmation_token: "some token")
1896 {:ok, user} = User.toggle_confirmation(user)
1897
1898 refute user.confirmation_pending
1899 refute user.confirmation_token
1900 end
1901 end
1902
1903 describe "ensure_keys_present" do
1904 test "it creates keys for a user and stores them in info" do
1905 user = insert(:user)
1906 refute is_binary(user.keys)
1907 {:ok, user} = User.ensure_keys_present(user)
1908 assert is_binary(user.keys)
1909 end
1910
1911 test "it doesn't create keys if there already are some" do
1912 user = insert(:user, keys: "xxx")
1913 {:ok, user} = User.ensure_keys_present(user)
1914 assert user.keys == "xxx"
1915 end
1916 end
1917
1918 describe "get_ap_ids_by_nicknames" do
1919 test "it returns a list of AP ids for a given set of nicknames" do
1920 user = insert(:user)
1921 user_two = insert(:user)
1922
1923 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
1924 assert length(ap_ids) == 2
1925 assert user.ap_id in ap_ids
1926 assert user_two.ap_id in ap_ids
1927 end
1928 end
1929
1930 describe "sync followers count" do
1931 setup do
1932 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
1933 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
1934 insert(:user, local: true)
1935 insert(:user, local: false, deactivated: true)
1936 {:ok, user1: user1, user2: user2}
1937 end
1938
1939 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
1940 [fdb_user1] = User.external_users(limit: 1)
1941
1942 assert fdb_user1.ap_id
1943 assert fdb_user1.ap_id == user1.ap_id
1944 assert fdb_user1.id == user1.id
1945
1946 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
1947
1948 assert fdb_user2.ap_id
1949 assert fdb_user2.ap_id == user2.ap_id
1950 assert fdb_user2.id == user2.id
1951
1952 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
1953 end
1954 end
1955
1956 describe "is_internal_user?/1" do
1957 test "non-internal user returns false" do
1958 user = insert(:user)
1959 refute User.is_internal_user?(user)
1960 end
1961
1962 test "user with no nickname returns true" do
1963 user = insert(:user, %{nickname: nil})
1964 assert User.is_internal_user?(user)
1965 end
1966
1967 test "user with internal-prefixed nickname returns true" do
1968 user = insert(:user, %{nickname: "internal.test"})
1969 assert User.is_internal_user?(user)
1970 end
1971 end
1972
1973 describe "update_and_set_cache/1" do
1974 test "returns error when user is stale instead Ecto.StaleEntryError" do
1975 user = insert(:user)
1976
1977 changeset = Ecto.Changeset.change(user, bio: "test")
1978
1979 Repo.delete(user)
1980
1981 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
1982 User.update_and_set_cache(changeset)
1983 end
1984
1985 test "performs update cache if user updated" do
1986 user = insert(:user)
1987 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1988
1989 changeset = Ecto.Changeset.change(user, bio: "test-bio")
1990
1991 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
1992 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1993 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
1994 end
1995 end
1996
1997 describe "following/followers synchronization" do
1998 setup do: clear_config([:instance, :external_user_synchronization])
1999
2000 test "updates the counters normally on following/getting a follow when disabled" do
2001 Pleroma.Config.put([:instance, :external_user_synchronization], false)
2002 user = insert(:user)
2003
2004 other_user =
2005 insert(:user,
2006 local: false,
2007 follower_address: "http://localhost:4001/users/masto_closed/followers",
2008 following_address: "http://localhost:4001/users/masto_closed/following",
2009 ap_enabled: true
2010 )
2011
2012 assert other_user.following_count == 0
2013 assert other_user.follower_count == 0
2014
2015 {:ok, user} = Pleroma.User.follow(user, other_user)
2016 other_user = Pleroma.User.get_by_id(other_user.id)
2017
2018 assert user.following_count == 1
2019 assert other_user.follower_count == 1
2020 end
2021
2022 test "syncronizes the counters with the remote instance for the followed when enabled" do
2023 Pleroma.Config.put([:instance, :external_user_synchronization], false)
2024
2025 user = insert(:user)
2026
2027 other_user =
2028 insert(:user,
2029 local: false,
2030 follower_address: "http://localhost:4001/users/masto_closed/followers",
2031 following_address: "http://localhost:4001/users/masto_closed/following",
2032 ap_enabled: true
2033 )
2034
2035 assert other_user.following_count == 0
2036 assert other_user.follower_count == 0
2037
2038 Pleroma.Config.put([:instance, :external_user_synchronization], true)
2039 {:ok, _user} = User.follow(user, other_user)
2040 other_user = User.get_by_id(other_user.id)
2041
2042 assert other_user.follower_count == 437
2043 end
2044
2045 test "syncronizes the counters with the remote instance for the follower when enabled" do
2046 Pleroma.Config.put([:instance, :external_user_synchronization], false)
2047
2048 user = insert(:user)
2049
2050 other_user =
2051 insert(:user,
2052 local: false,
2053 follower_address: "http://localhost:4001/users/masto_closed/followers",
2054 following_address: "http://localhost:4001/users/masto_closed/following",
2055 ap_enabled: true
2056 )
2057
2058 assert other_user.following_count == 0
2059 assert other_user.follower_count == 0
2060
2061 Pleroma.Config.put([:instance, :external_user_synchronization], true)
2062 {:ok, other_user} = User.follow(other_user, user)
2063
2064 assert other_user.following_count == 152
2065 end
2066 end
2067
2068 describe "change_email/2" do
2069 setup do
2070 [user: insert(:user)]
2071 end
2072
2073 test "blank email returns error", %{user: user} do
2074 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
2075 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
2076 end
2077
2078 test "non unique email returns error", %{user: user} do
2079 %{email: email} = insert(:user)
2080
2081 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
2082 User.change_email(user, email)
2083 end
2084
2085 test "invalid email returns error", %{user: user} do
2086 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
2087 User.change_email(user, "cofe")
2088 end
2089
2090 test "changes email", %{user: user} do
2091 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
2092 end
2093 end
2094
2095 describe "get_cached_by_nickname_or_id" do
2096 setup do
2097 local_user = insert(:user)
2098 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
2099
2100 [local_user: local_user, remote_user: remote_user]
2101 end
2102
2103 setup do: clear_config([:instance, :limit_to_local_content])
2104
2105 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
2106 remote_user: remote_user
2107 } do
2108 Pleroma.Config.put([:instance, :limit_to_local_content], false)
2109 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2110
2111 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2112 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2113
2114 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2115 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2116 end
2117
2118 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
2119 %{remote_user: remote_user} do
2120 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2121 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2122 end
2123
2124 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
2125 %{remote_user: remote_user, local_user: local_user} do
2126 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2127 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
2128 end
2129
2130 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
2131 %{remote_user: remote_user} do
2132 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2133 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2134 end
2135
2136 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
2137 %{local_user: local_user} do
2138 Pleroma.Config.put([:instance, :limit_to_local_content], false)
2139 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2140
2141 Pleroma.Config.put([:instance, :limit_to_local_content], true)
2142 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2143
2144 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
2145 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2146 end
2147 end
2148
2149 describe "update_email_notifications/2" do
2150 setup do
2151 user = insert(:user, email_notifications: %{"digest" => true})
2152
2153 {:ok, user: user}
2154 end
2155
2156 test "Notifications are updated", %{user: user} do
2157 true = user.email_notifications["digest"]
2158 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
2159 assert result.email_notifications["digest"] == false
2160 end
2161 end
2162
2163 test "avatar fallback" do
2164 user = insert(:user)
2165 assert User.avatar_url(user) =~ "/images/avi.png"
2166
2167 clear_config([:assets, :default_user_avatar], "avatar.png")
2168
2169 user = User.get_cached_by_nickname_or_id(user.nickname)
2170 assert User.avatar_url(user) =~ "avatar.png"
2171
2172 assert User.avatar_url(user, no_default: true) == nil
2173 end
2174 end