Remove Twemoji stuff from MastoFE
[akkoma] / test / pleroma / user_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 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, is_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, is_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, is_locked: true)
205 pending_follower = insert(:user, %{is_active: false})
206
207 CommonAPI.follow(pending_follower, locked)
208
209 refute pending_follower.is_active
210 assert [] = User.get_follow_requests(locked)
211 end
212
213 test "clears follow requests when requester is blocked" do
214 followed = insert(:user, is_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, followed_zero} = 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, followed} = 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, %{is_active: false})
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, is_locked: true)
303 followed = insert(:user, is_locked: true)
304
305 {:ok, follower, followed} = 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 clear_config([: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, followed} = 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, followed} = 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([:instance, :autofollowing_nicknames])
392 setup do: clear_config([:welcome])
393 setup do: clear_config([:instance, :account_activation_required])
394
395 test "it autofollows accounts that are set for it" do
396 user = insert(:user)
397 remote_user = insert(:user, %{local: false})
398
399 clear_config([:instance, :autofollowed_nicknames], [
400 user.nickname,
401 remote_user.nickname
402 ])
403
404 cng = User.register_changeset(%User{}, @full_user_data)
405
406 {:ok, registered_user} = User.register(cng)
407
408 assert User.following?(registered_user, user)
409 refute User.following?(registered_user, remote_user)
410 end
411
412 test "it adds automatic followers for new registered accounts" do
413 user1 = insert(:user)
414 user2 = insert(:user)
415
416 clear_config([:instance, :autofollowing_nicknames], [
417 user1.nickname,
418 user2.nickname
419 ])
420
421 cng = User.register_changeset(%User{}, @full_user_data)
422
423 {:ok, registered_user} = User.register(cng)
424
425 assert User.following?(user1, registered_user)
426 assert User.following?(user2, registered_user)
427 end
428
429 test "it sends a welcome message if it is set" do
430 welcome_user = insert(:user)
431 clear_config([:welcome, :direct_message, :enabled], true)
432 clear_config([:welcome, :direct_message, :sender_nickname], welcome_user.nickname)
433 clear_config([:welcome, :direct_message, :message], "Hello, this is a direct message")
434
435 cng = User.register_changeset(%User{}, @full_user_data)
436 {:ok, registered_user} = User.register(cng)
437 ObanHelpers.perform_all()
438
439 activity = Repo.one(Pleroma.Activity)
440 assert registered_user.ap_id in activity.recipients
441 assert Object.normalize(activity, fetch: false).data["content"] =~ "direct message"
442 assert activity.actor == welcome_user.ap_id
443 end
444
445 test "it sends a welcome chat message if it is set" do
446 welcome_user = insert(:user)
447 clear_config([:welcome, :chat_message, :enabled], true)
448 clear_config([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
449 clear_config([:welcome, :chat_message, :message], "Hello, this is a chat message")
450
451 cng = User.register_changeset(%User{}, @full_user_data)
452 {:ok, registered_user} = User.register(cng)
453 ObanHelpers.perform_all()
454
455 activity = Repo.one(Pleroma.Activity)
456 assert registered_user.ap_id in activity.recipients
457 assert Object.normalize(activity, fetch: false).data["content"] =~ "chat message"
458 assert activity.actor == welcome_user.ap_id
459 end
460
461 setup do:
462 clear_config(:mrf_simple,
463 media_removal: [],
464 media_nsfw: [],
465 federated_timeline_removal: [],
466 report_removal: [],
467 reject: [],
468 followers_only: [],
469 accept: [],
470 avatar_removal: [],
471 banner_removal: [],
472 reject_deletes: []
473 )
474
475 setup do:
476 clear_config(:mrf,
477 policies: [
478 Pleroma.Web.ActivityPub.MRF.SimplePolicy
479 ]
480 )
481
482 test "it sends a welcome chat message when Simple policy applied to local instance" do
483 clear_config([:mrf_simple, :media_nsfw], ["localhost"])
484
485 welcome_user = insert(:user)
486 clear_config([:welcome, :chat_message, :enabled], true)
487 clear_config([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
488 clear_config([:welcome, :chat_message, :message], "Hello, this is a chat message")
489
490 cng = User.register_changeset(%User{}, @full_user_data)
491 {:ok, registered_user} = User.register(cng)
492 ObanHelpers.perform_all()
493
494 activity = Repo.one(Pleroma.Activity)
495 assert registered_user.ap_id in activity.recipients
496 assert Object.normalize(activity, fetch: false).data["content"] =~ "chat message"
497 assert activity.actor == welcome_user.ap_id
498 end
499
500 test "it sends a welcome email message if it is set" do
501 welcome_user = insert(:user)
502 clear_config([:welcome, :email, :enabled], true)
503 clear_config([:welcome, :email, :sender], welcome_user.email)
504
505 clear_config(
506 [:welcome, :email, :subject],
507 "Hello, welcome to cool site: <%= instance_name %>"
508 )
509
510 instance_name = Pleroma.Config.get([:instance, :name])
511
512 cng = User.register_changeset(%User{}, @full_user_data)
513 {:ok, registered_user} = User.register(cng)
514 ObanHelpers.perform_all()
515
516 assert_email_sent(
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}"
521 )
522 end
523
524 test "it sends a confirm email" do
525 clear_config([:instance, :account_activation_required], true)
526
527 cng = User.register_changeset(%User{}, @full_user_data)
528 {:ok, registered_user} = User.register(cng)
529 ObanHelpers.perform_all()
530
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()
536 end
537
538 test "sends a pending approval email" do
539 clear_config([:instance, :account_approval_required], true)
540
541 {:ok, user} =
542 User.register_changeset(%User{}, @full_user_data)
543 |> User.register()
544
545 ObanHelpers.perform_all()
546
547 assert_email_sent(
548 from: Pleroma.Config.Helpers.sender(),
549 to: {user.name, user.email},
550 subject: "Your account is awaiting approval"
551 )
552 end
553
554 test "it sends a registration confirmed email if no others will be sent" do
555 clear_config([:welcome, :email, :enabled], false)
556 clear_config([:instance, :account_activation_required], false)
557 clear_config([:instance, :account_approval_required], false)
558
559 {:ok, user} =
560 User.register_changeset(%User{}, @full_user_data)
561 |> User.register()
562
563 ObanHelpers.perform_all()
564
565 instance_name = Pleroma.Config.get([:instance, :name])
566 sender = Pleroma.Config.get([:instance, :notify_email])
567
568 assert_email_sent(
569 from: {instance_name, sender},
570 to: {user.name, user.email},
571 subject: "Account registered on #{instance_name}"
572 )
573 end
574
575 test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do
576 clear_config([:instance, :account_activation_required], true)
577
578 @full_user_data
579 |> Map.keys()
580 |> Enum.each(fn key ->
581 params = Map.delete(@full_user_data, key)
582 changeset = User.register_changeset(%User{}, params)
583
584 assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
585 end)
586 end
587
588 test "it requires an name, nickname and password, bio and email are optional when account_activation_required is disabled" do
589 clear_config([:instance, :account_activation_required], false)
590
591 @full_user_data
592 |> Map.keys()
593 |> Enum.each(fn key ->
594 params = Map.delete(@full_user_data, key)
595 changeset = User.register_changeset(%User{}, params)
596
597 assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid?
598 end)
599 end
600
601 test "it restricts certain nicknames" do
602 [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
603
604 assert is_bitstring(restricted_name)
605
606 params =
607 @full_user_data
608 |> Map.put(:nickname, restricted_name)
609
610 changeset = User.register_changeset(%User{}, params)
611
612 refute changeset.valid?
613 end
614
615 test "it blocks blacklisted email domains" do
616 clear_config([User, :email_blacklist], ["trolling.world"])
617
618 # Block with match
619 params = Map.put(@full_user_data, :email, "troll@trolling.world")
620 changeset = User.register_changeset(%User{}, params)
621 refute changeset.valid?
622
623 # Block with subdomain match
624 params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world")
625 changeset = User.register_changeset(%User{}, params)
626 refute changeset.valid?
627
628 # Pass with different domains that are similar
629 params = Map.put(@full_user_data, :email, "troll@gnomestrolling.world")
630 changeset = User.register_changeset(%User{}, params)
631 assert changeset.valid?
632
633 params = Map.put(@full_user_data, :email, "troll@trolling.world.us")
634 changeset = User.register_changeset(%User{}, params)
635 assert changeset.valid?
636 end
637
638 test "it sets the password_hash and ap_id" do
639 changeset = User.register_changeset(%User{}, @full_user_data)
640
641 assert changeset.valid?
642
643 assert is_binary(changeset.changes[:password_hash])
644 assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
645
646 assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
647 end
648
649 test "it sets the 'accepts_chat_messages' set to true" do
650 changeset = User.register_changeset(%User{}, @full_user_data)
651 assert changeset.valid?
652
653 {:ok, user} = Repo.insert(changeset)
654
655 assert user.accepts_chat_messages
656 end
657
658 test "it creates a confirmed user" do
659 changeset = User.register_changeset(%User{}, @full_user_data)
660 assert changeset.valid?
661
662 {:ok, user} = Repo.insert(changeset)
663
664 assert user.is_confirmed
665 end
666 end
667
668 describe "user registration, with :account_activation_required" do
669 @full_user_data %{
670 bio: "A guy",
671 name: "my name",
672 nickname: "nick",
673 password: "test",
674 password_confirmation: "test",
675 email: "email@example.com"
676 }
677 setup do: clear_config([:instance, :account_activation_required], true)
678
679 test "it creates unconfirmed user" do
680 changeset = User.register_changeset(%User{}, @full_user_data)
681 assert changeset.valid?
682
683 {:ok, user} = Repo.insert(changeset)
684
685 refute user.is_confirmed
686 assert user.confirmation_token
687 end
688
689 test "it creates confirmed user if :confirmed option is given" do
690 changeset = User.register_changeset(%User{}, @full_user_data, confirmed: true)
691 assert changeset.valid?
692
693 {:ok, user} = Repo.insert(changeset)
694
695 assert user.is_confirmed
696 refute user.confirmation_token
697 end
698 end
699
700 describe "user registration, with :account_approval_required" do
701 @full_user_data %{
702 bio: "A guy",
703 name: "my name",
704 nickname: "nick",
705 password: "test",
706 password_confirmation: "test",
707 email: "email@example.com",
708 registration_reason: "I'm a cool guy :)"
709 }
710 setup do: clear_config([:instance, :account_approval_required], true)
711
712 test "it creates unapproved user" do
713 changeset = User.register_changeset(%User{}, @full_user_data)
714 assert changeset.valid?
715
716 {:ok, user} = Repo.insert(changeset)
717
718 refute user.is_approved
719 assert user.registration_reason == "I'm a cool guy :)"
720 end
721
722 test "it restricts length of registration reason" do
723 reason_limit = Pleroma.Config.get([:instance, :registration_reason_length])
724
725 assert is_integer(reason_limit)
726
727 params =
728 @full_user_data
729 |> Map.put(
730 :registration_reason,
731 "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."
732 )
733
734 changeset = User.register_changeset(%User{}, params)
735
736 refute changeset.valid?
737 end
738 end
739
740 describe "get_or_fetch/1" do
741 test "gets an existing user by nickname" do
742 user = insert(:user)
743 {:ok, fetched_user} = User.get_or_fetch(user.nickname)
744
745 assert user == fetched_user
746 end
747
748 test "gets an existing user by ap_id" do
749 ap_id = "http://mastodon.example.org/users/admin"
750
751 user =
752 insert(
753 :user,
754 local: false,
755 nickname: "admin@mastodon.example.org",
756 ap_id: ap_id
757 )
758
759 {:ok, fetched_user} = User.get_or_fetch(ap_id)
760 freshed_user = refresh_record(user)
761 assert freshed_user == fetched_user
762 end
763 end
764
765 describe "fetching a user from nickname or trying to build one" do
766 test "gets an existing user" do
767 user = insert(:user)
768 {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
769
770 assert user == fetched_user
771 end
772
773 test "gets an existing user, case insensitive" do
774 user = insert(:user, nickname: "nick")
775 {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
776
777 assert user == fetched_user
778 end
779
780 test "gets an existing user by fully qualified nickname" do
781 user = insert(:user)
782
783 {:ok, fetched_user} =
784 User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
785
786 assert user == fetched_user
787 end
788
789 test "gets an existing user by fully qualified nickname, case insensitive" do
790 user = insert(:user, nickname: "nick")
791 casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
792
793 {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
794
795 assert user == fetched_user
796 end
797
798 @tag capture_log: true
799 test "returns nil if no user could be fetched" do
800 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
801 assert fetched_user == "not found nonexistant@social.heldscal.la"
802 end
803
804 test "returns nil for nonexistant local user" do
805 {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
806 assert fetched_user == "not found nonexistant"
807 end
808
809 test "updates an existing user, if stale" do
810 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
811
812 orig_user =
813 insert(
814 :user,
815 local: false,
816 nickname: "admin@mastodon.example.org",
817 ap_id: "http://mastodon.example.org/users/admin",
818 last_refreshed_at: a_week_ago
819 )
820
821 assert orig_user.last_refreshed_at == a_week_ago
822
823 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
824
825 assert user.inbox
826
827 refute user.last_refreshed_at == orig_user.last_refreshed_at
828 end
829
830 test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
831 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
832
833 orig_user =
834 insert(
835 :user,
836 local: false,
837 nickname: "admin@mastodon.example.org",
838 ap_id: "http://mastodon.example.org/users/harinezumigari",
839 last_refreshed_at: a_week_ago
840 )
841
842 assert orig_user.last_refreshed_at == a_week_ago
843
844 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
845
846 assert user.inbox
847
848 refute user.id == orig_user.id
849
850 orig_user = User.get_by_id(orig_user.id)
851
852 assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
853 end
854
855 @tag capture_log: true
856 test "it returns the old user if stale, but unfetchable" do
857 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
858
859 orig_user =
860 insert(
861 :user,
862 local: false,
863 nickname: "admin@mastodon.example.org",
864 ap_id: "http://mastodon.example.org/users/raymoo",
865 last_refreshed_at: a_week_ago
866 )
867
868 assert orig_user.last_refreshed_at == a_week_ago
869
870 {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/raymoo")
871
872 assert user.last_refreshed_at == orig_user.last_refreshed_at
873 end
874 end
875
876 test "returns an ap_id for a user" do
877 user = insert(:user)
878
879 assert User.ap_id(user) ==
880 Pleroma.Web.Router.Helpers.user_feed_url(
881 Pleroma.Web.Endpoint,
882 :feed_redirect,
883 user.nickname
884 )
885 end
886
887 test "returns an ap_followers link for a user" do
888 user = insert(:user)
889
890 assert User.ap_followers(user) ==
891 Pleroma.Web.Router.Helpers.user_feed_url(
892 Pleroma.Web.Endpoint,
893 :feed_redirect,
894 user.nickname
895 ) <> "/followers"
896 end
897
898 describe "remote user changeset" do
899 @valid_remote %{
900 bio: "hello",
901 name: "Someone",
902 nickname: "a@b.de",
903 ap_id: "http...",
904 avatar: %{some: "avatar"}
905 }
906 setup do: clear_config([:instance, :user_bio_length])
907 setup do: clear_config([:instance, :user_name_length])
908
909 test "it confirms validity" do
910 cs = User.remote_user_changeset(@valid_remote)
911 assert cs.valid?
912 end
913
914 test "it sets the follower_adress" do
915 cs = User.remote_user_changeset(@valid_remote)
916 # remote users get a fake local follower address
917 assert cs.changes.follower_address ==
918 User.ap_followers(%User{nickname: @valid_remote[:nickname]})
919 end
920
921 test "it enforces the fqn format for nicknames" do
922 cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})
923 assert Ecto.Changeset.get_field(cs, :local) == false
924 assert cs.changes.avatar
925 refute cs.valid?
926 end
927
928 test "it has required fields" do
929 [:ap_id]
930 |> Enum.each(fn field ->
931 cs = User.remote_user_changeset(Map.delete(@valid_remote, field))
932 refute cs.valid?
933 end)
934 end
935
936 test "it is invalid given a local user" do
937 user = insert(:user)
938 cs = User.remote_user_changeset(user, %{name: "tom from myspace"})
939
940 refute cs.valid?
941 end
942 end
943
944 describe "followers and friends" do
945 test "gets all followers for a given user" do
946 user = insert(:user)
947 follower_one = insert(:user)
948 follower_two = insert(:user)
949 not_follower = insert(:user)
950
951 {:ok, follower_one, user} = User.follow(follower_one, user)
952 {:ok, follower_two, user} = User.follow(follower_two, user)
953
954 res = User.get_followers(user)
955
956 assert Enum.member?(res, follower_one)
957 assert Enum.member?(res, follower_two)
958 refute Enum.member?(res, not_follower)
959 end
960
961 test "gets all friends (followed users) for a given user" do
962 user = insert(:user)
963 followed_one = insert(:user)
964 followed_two = insert(:user)
965 not_followed = insert(:user)
966
967 {:ok, user, followed_one} = User.follow(user, followed_one)
968 {:ok, user, followed_two} = User.follow(user, followed_two)
969
970 res = User.get_friends(user)
971
972 followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
973 followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
974 assert Enum.member?(res, followed_one)
975 assert Enum.member?(res, followed_two)
976 refute Enum.member?(res, not_followed)
977 end
978 end
979
980 describe "updating note and follower count" do
981 test "it sets the note_count property" do
982 note = insert(:note)
983
984 user = User.get_cached_by_ap_id(note.data["actor"])
985
986 assert user.note_count == 0
987
988 {:ok, user} = User.update_note_count(user)
989
990 assert user.note_count == 1
991 end
992
993 test "it increases the note_count property" do
994 note = insert(:note)
995 user = User.get_cached_by_ap_id(note.data["actor"])
996
997 assert user.note_count == 0
998
999 {:ok, user} = User.increase_note_count(user)
1000
1001 assert user.note_count == 1
1002
1003 {:ok, user} = User.increase_note_count(user)
1004
1005 assert user.note_count == 2
1006 end
1007
1008 test "it decreases the note_count property" do
1009 note = insert(:note)
1010 user = User.get_cached_by_ap_id(note.data["actor"])
1011
1012 assert user.note_count == 0
1013
1014 {:ok, user} = User.increase_note_count(user)
1015
1016 assert user.note_count == 1
1017
1018 {:ok, user} = User.decrease_note_count(user)
1019
1020 assert user.note_count == 0
1021
1022 {:ok, user} = User.decrease_note_count(user)
1023
1024 assert user.note_count == 0
1025 end
1026
1027 test "it sets the follower_count property" do
1028 user = insert(:user)
1029 follower = insert(:user)
1030
1031 User.follow(follower, user)
1032
1033 assert user.follower_count == 0
1034
1035 {:ok, user} = User.update_follower_count(user)
1036
1037 assert user.follower_count == 1
1038 end
1039 end
1040
1041 describe "mutes" do
1042 test "it mutes people" do
1043 user = insert(:user)
1044 muted_user = insert(:user)
1045
1046 refute User.mutes?(user, muted_user)
1047 refute User.muted_notifications?(user, muted_user)
1048
1049 {:ok, _user_relationships} = User.mute(user, muted_user)
1050
1051 assert User.mutes?(user, muted_user)
1052 assert User.muted_notifications?(user, muted_user)
1053 end
1054
1055 test "expiring" do
1056 user = insert(:user)
1057 muted_user = insert(:user)
1058
1059 {:ok, _user_relationships} = User.mute(user, muted_user, %{expires_in: 60})
1060 assert User.mutes?(user, muted_user)
1061
1062 worker = Pleroma.Workers.MuteExpireWorker
1063 args = %{"op" => "unmute_user", "muter_id" => user.id, "mutee_id" => muted_user.id}
1064
1065 assert_enqueued(
1066 worker: worker,
1067 args: args
1068 )
1069
1070 assert :ok = perform_job(worker, args)
1071
1072 refute User.mutes?(user, muted_user)
1073 refute User.muted_notifications?(user, muted_user)
1074 end
1075
1076 test "it unmutes users" do
1077 user = insert(:user)
1078 muted_user = insert(:user)
1079
1080 {:ok, _user_relationships} = User.mute(user, muted_user)
1081 {:ok, _user_mute} = User.unmute(user, muted_user)
1082
1083 refute User.mutes?(user, muted_user)
1084 refute User.muted_notifications?(user, muted_user)
1085 end
1086
1087 test "it unmutes users by id" do
1088 user = insert(:user)
1089 muted_user = insert(:user)
1090
1091 {:ok, _user_relationships} = User.mute(user, muted_user)
1092 {:ok, _user_mute} = User.unmute(user.id, muted_user.id)
1093
1094 refute User.mutes?(user, muted_user)
1095 refute User.muted_notifications?(user, muted_user)
1096 end
1097
1098 test "it mutes user without notifications" do
1099 user = insert(:user)
1100 muted_user = insert(:user)
1101
1102 refute User.mutes?(user, muted_user)
1103 refute User.muted_notifications?(user, muted_user)
1104
1105 {:ok, _user_relationships} = User.mute(user, muted_user, %{notifications: false})
1106
1107 assert User.mutes?(user, muted_user)
1108 refute User.muted_notifications?(user, muted_user)
1109 end
1110 end
1111
1112 describe "blocks" do
1113 test "it blocks people" do
1114 user = insert(:user)
1115 blocked_user = insert(:user)
1116
1117 refute User.blocks?(user, blocked_user)
1118
1119 {:ok, _user_relationship} = User.block(user, blocked_user)
1120
1121 assert User.blocks?(user, blocked_user)
1122 end
1123
1124 test "it unblocks users" do
1125 user = insert(:user)
1126 blocked_user = insert(:user)
1127
1128 {:ok, _user_relationship} = User.block(user, blocked_user)
1129 {:ok, _user_block} = User.unblock(user, blocked_user)
1130
1131 refute User.blocks?(user, blocked_user)
1132 end
1133
1134 test "blocks tear down cyclical follow relationships" do
1135 blocker = insert(:user)
1136 blocked = insert(:user)
1137
1138 {:ok, blocker, blocked} = User.follow(blocker, blocked)
1139 {:ok, blocked, blocker} = User.follow(blocked, blocker)
1140
1141 assert User.following?(blocker, blocked)
1142 assert User.following?(blocked, blocker)
1143
1144 {:ok, _user_relationship} = User.block(blocker, blocked)
1145 blocked = User.get_cached_by_id(blocked.id)
1146
1147 assert User.blocks?(blocker, blocked)
1148
1149 refute User.following?(blocker, blocked)
1150 refute User.following?(blocked, blocker)
1151 end
1152
1153 test "blocks tear down blocker->blocked follow relationships" do
1154 blocker = insert(:user)
1155 blocked = insert(:user)
1156
1157 {:ok, blocker, blocked} = User.follow(blocker, blocked)
1158
1159 assert User.following?(blocker, blocked)
1160 refute User.following?(blocked, blocker)
1161
1162 {:ok, _user_relationship} = User.block(blocker, blocked)
1163 blocked = User.get_cached_by_id(blocked.id)
1164
1165 assert User.blocks?(blocker, blocked)
1166
1167 refute User.following?(blocker, blocked)
1168 refute User.following?(blocked, blocker)
1169 end
1170
1171 test "blocks tear down blocked->blocker follow relationships" do
1172 blocker = insert(:user)
1173 blocked = insert(:user)
1174
1175 {:ok, blocked, blocker} = User.follow(blocked, blocker)
1176
1177 refute User.following?(blocker, blocked)
1178 assert User.following?(blocked, blocker)
1179
1180 {:ok, _user_relationship} = User.block(blocker, blocked)
1181 blocked = User.get_cached_by_id(blocked.id)
1182
1183 assert User.blocks?(blocker, blocked)
1184
1185 refute User.following?(blocker, blocked)
1186 refute User.following?(blocked, blocker)
1187 end
1188
1189 test "blocks tear down blocked->blocker subscription relationships" do
1190 blocker = insert(:user)
1191 blocked = insert(:user)
1192
1193 {:ok, _subscription} = User.subscribe(blocked, blocker)
1194
1195 assert User.subscribed_to?(blocked, blocker)
1196 refute User.subscribed_to?(blocker, blocked)
1197
1198 {:ok, _user_relationship} = User.block(blocker, blocked)
1199
1200 assert User.blocks?(blocker, blocked)
1201 refute User.subscribed_to?(blocker, blocked)
1202 refute User.subscribed_to?(blocked, blocker)
1203 end
1204 end
1205
1206 describe "domain blocking" do
1207 test "blocks domains" do
1208 user = insert(:user)
1209 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1210
1211 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1212
1213 assert User.blocks?(user, collateral_user)
1214 end
1215
1216 test "does not block domain with same end" do
1217 user = insert(:user)
1218
1219 collateral_user =
1220 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1221
1222 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1223
1224 refute User.blocks?(user, collateral_user)
1225 end
1226
1227 test "does not block domain with same end if wildcard added" do
1228 user = insert(:user)
1229
1230 collateral_user =
1231 insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
1232
1233 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1234
1235 refute User.blocks?(user, collateral_user)
1236 end
1237
1238 test "blocks domain with wildcard for subdomain" do
1239 user = insert(:user)
1240
1241 user_from_subdomain =
1242 insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
1243
1244 user_with_two_subdomains =
1245 insert(:user, %{
1246 ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
1247 })
1248
1249 user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1250
1251 {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
1252
1253 assert User.blocks?(user, user_from_subdomain)
1254 assert User.blocks?(user, user_with_two_subdomains)
1255 assert User.blocks?(user, user_domain)
1256 end
1257
1258 test "unblocks domains" do
1259 user = insert(:user)
1260 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
1261
1262 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
1263 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
1264
1265 refute User.blocks?(user, collateral_user)
1266 end
1267
1268 test "follows take precedence over domain blocks" do
1269 user = insert(:user)
1270 good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
1271
1272 {:ok, user} = User.block_domain(user, "meanies.social")
1273 {:ok, user, good_eggo} = User.follow(user, good_eggo)
1274
1275 refute User.blocks?(user, good_eggo)
1276 end
1277 end
1278
1279 describe "get_recipients_from_activity" do
1280 test "works for announces" do
1281 actor = insert(:user)
1282 user = insert(:user, local: true)
1283
1284 {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
1285 {:ok, announce} = CommonAPI.repeat(activity.id, user)
1286
1287 recipients = User.get_recipients_from_activity(announce)
1288
1289 assert user in recipients
1290 end
1291
1292 test "get recipients" do
1293 actor = insert(:user)
1294 user = insert(:user, local: true)
1295 user_two = insert(:user, local: false)
1296 addressed = insert(:user, local: true)
1297 addressed_remote = insert(:user, local: false)
1298
1299 {:ok, activity} =
1300 CommonAPI.post(actor, %{
1301 status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
1302 })
1303
1304 assert Enum.map([actor, addressed], & &1.ap_id) --
1305 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1306
1307 {:ok, user, actor} = User.follow(user, actor)
1308 {:ok, _user_two, _actor} = User.follow(user_two, actor)
1309 recipients = User.get_recipients_from_activity(activity)
1310 assert length(recipients) == 3
1311 assert user in recipients
1312 assert addressed in recipients
1313 end
1314
1315 test "has following" do
1316 actor = insert(:user)
1317 user = insert(:user)
1318 user_two = insert(:user)
1319 addressed = insert(:user, local: true)
1320
1321 {:ok, activity} =
1322 CommonAPI.post(actor, %{
1323 status: "hey @#{addressed.nickname}"
1324 })
1325
1326 assert Enum.map([actor, addressed], & &1.ap_id) --
1327 Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
1328
1329 {:ok, _actor, _user} = User.follow(actor, user)
1330 {:ok, _actor, _user_two} = User.follow(actor, user_two)
1331 recipients = User.get_recipients_from_activity(activity)
1332 assert length(recipients) == 2
1333 assert addressed in recipients
1334 end
1335 end
1336
1337 describe ".set_activation" do
1338 test "can de-activate then re-activate a user" do
1339 user = insert(:user)
1340 assert user.is_active
1341 {:ok, user} = User.set_activation(user, false)
1342 refute user.is_active
1343 {:ok, user} = User.set_activation(user, true)
1344 assert user.is_active
1345 end
1346
1347 test "hide a user from followers" do
1348 user = insert(:user)
1349 user2 = insert(:user)
1350
1351 {:ok, user, user2} = User.follow(user, user2)
1352 {:ok, _user} = User.set_activation(user, false)
1353
1354 user2 = User.get_cached_by_id(user2.id)
1355
1356 assert user2.follower_count == 0
1357 assert [] = User.get_followers(user2)
1358 end
1359
1360 test "hide a user from friends" do
1361 user = insert(:user)
1362 user2 = insert(:user)
1363
1364 {:ok, user2, user} = User.follow(user2, user)
1365 assert user2.following_count == 1
1366 assert User.following_count(user2) == 1
1367
1368 {:ok, _user} = User.set_activation(user, false)
1369
1370 user2 = User.get_cached_by_id(user2.id)
1371
1372 assert refresh_record(user2).following_count == 0
1373 assert user2.following_count == 0
1374 assert User.following_count(user2) == 0
1375 assert [] = User.get_friends(user2)
1376 end
1377
1378 test "hide a user's statuses from timelines and notifications" do
1379 user = insert(:user)
1380 user2 = insert(:user)
1381
1382 {:ok, user2, user} = User.follow(user2, user)
1383
1384 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
1385
1386 activity = Repo.preload(activity, :bookmark)
1387
1388 [notification] = Pleroma.Notification.for_user(user2)
1389 assert notification.activity.id == activity.id
1390
1391 assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
1392
1393 assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
1394 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1395 user: user2
1396 })
1397
1398 {:ok, _user} = User.set_activation(user, false)
1399
1400 assert [] == ActivityPub.fetch_public_activities(%{})
1401 assert [] == Pleroma.Notification.for_user(user2)
1402
1403 assert [] ==
1404 ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
1405 user: user2
1406 })
1407 end
1408 end
1409
1410 describe "approve" do
1411 test "approves a user" do
1412 user = insert(:user, is_approved: false)
1413 refute user.is_approved
1414 {:ok, user} = User.approve(user)
1415 assert user.is_approved
1416 end
1417
1418 test "approves a list of users" do
1419 unapproved_users = [
1420 insert(:user, is_approved: false),
1421 insert(:user, is_approved: false),
1422 insert(:user, is_approved: false)
1423 ]
1424
1425 {:ok, users} = User.approve(unapproved_users)
1426
1427 assert Enum.count(users) == 3
1428
1429 Enum.each(users, fn user ->
1430 assert user.is_approved
1431 end)
1432 end
1433
1434 test "it sends welcome email if it is set" do
1435 clear_config([:welcome, :email, :enabled], true)
1436 clear_config([:welcome, :email, :sender], "tester@test.me")
1437
1438 user = insert(:user, is_approved: false)
1439 welcome_user = insert(:user, email: "tester@test.me")
1440 instance_name = Pleroma.Config.get([:instance, :name])
1441
1442 User.approve(user)
1443
1444 ObanHelpers.perform_all()
1445
1446 assert_email_sent(
1447 from: {instance_name, welcome_user.email},
1448 to: {user.name, user.email},
1449 html_body: "Welcome to #{instance_name}"
1450 )
1451 end
1452
1453 test "approving an approved user does not trigger post-register actions" do
1454 clear_config([:welcome, :email, :enabled], true)
1455
1456 user = insert(:user, is_approved: true)
1457 User.approve(user)
1458
1459 ObanHelpers.perform_all()
1460
1461 assert_no_email_sent()
1462 end
1463 end
1464
1465 describe "confirm" do
1466 test "confirms a user" do
1467 user = insert(:user, is_confirmed: false)
1468 refute user.is_confirmed
1469 {:ok, user} = User.confirm(user)
1470 assert user.is_confirmed
1471 end
1472
1473 test "confirms a list of users" do
1474 unconfirmed_users = [
1475 insert(:user, is_confirmed: false),
1476 insert(:user, is_confirmed: false),
1477 insert(:user, is_confirmed: false)
1478 ]
1479
1480 {:ok, users} = User.confirm(unconfirmed_users)
1481
1482 assert Enum.count(users) == 3
1483
1484 Enum.each(users, fn user ->
1485 assert user.is_confirmed
1486 end)
1487 end
1488
1489 test "sends approval emails when `is_approved: false`" do
1490 admin = insert(:user, is_admin: true)
1491 user = insert(:user, is_confirmed: false, is_approved: false)
1492 User.confirm(user)
1493
1494 ObanHelpers.perform_all()
1495
1496 user_email = Pleroma.Emails.UserEmail.approval_pending_email(user)
1497 admin_email = Pleroma.Emails.AdminEmail.new_unapproved_registration(admin, user)
1498
1499 notify_email = Pleroma.Config.get([:instance, :notify_email])
1500 instance_name = Pleroma.Config.get([:instance, :name])
1501
1502 # User approval email
1503 assert_email_sent(
1504 from: {instance_name, notify_email},
1505 to: {user.name, user.email},
1506 html_body: user_email.html_body
1507 )
1508
1509 # Admin email
1510 assert_email_sent(
1511 from: {instance_name, notify_email},
1512 to: {admin.name, admin.email},
1513 html_body: admin_email.html_body
1514 )
1515 end
1516
1517 test "confirming a confirmed user does not trigger post-register actions" do
1518 user = insert(:user, is_confirmed: true, is_approved: false)
1519 User.confirm(user)
1520
1521 ObanHelpers.perform_all()
1522
1523 assert_no_email_sent()
1524 end
1525 end
1526
1527 describe "delete" do
1528 setup do
1529 {:ok, user} = insert(:user) |> User.set_cache()
1530
1531 [user: user]
1532 end
1533
1534 setup do: clear_config([:instance, :federating])
1535
1536 test ".delete_user_activities deletes all create activities", %{user: user} do
1537 {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
1538
1539 User.delete_user_activities(user)
1540
1541 # TODO: Test removal favorites, repeats, delete activities.
1542 refute Activity.get_by_id(activity.id)
1543 end
1544
1545 test "it deactivates a user, all follow relationships and all activities", %{user: user} do
1546 follower = insert(:user)
1547 {:ok, follower, user} = User.follow(follower, user)
1548
1549 locked_user = insert(:user, name: "locked", is_locked: true)
1550 {:ok, _, _} = User.follow(user, locked_user, :follow_pending)
1551
1552 object = insert(:note, user: user)
1553 activity = insert(:note_activity, user: user, note: object)
1554
1555 object_two = insert(:note, user: follower)
1556 activity_two = insert(:note_activity, user: follower, note: object_two)
1557
1558 {:ok, like} = CommonAPI.favorite(user, activity_two.id)
1559 {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
1560 {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
1561
1562 {:ok, job} = User.delete(user)
1563 {:ok, _user} = ObanHelpers.perform(job)
1564
1565 follower = User.get_cached_by_id(follower.id)
1566
1567 refute User.following?(follower, user)
1568 assert %{is_active: false} = User.get_by_id(user.id)
1569
1570 assert [] == User.get_follow_requests(locked_user)
1571
1572 user_activities =
1573 user.ap_id
1574 |> Activity.Queries.by_actor()
1575 |> Repo.all()
1576 |> Enum.map(fn act -> act.data["type"] end)
1577
1578 assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
1579
1580 refute Activity.get_by_id(activity.id)
1581 refute Activity.get_by_id(like.id)
1582 refute Activity.get_by_id(like_two.id)
1583 refute Activity.get_by_id(repeat.id)
1584 end
1585 end
1586
1587 test "delete/1 when confirmation is pending deletes the user" do
1588 clear_config([:instance, :account_activation_required], true)
1589 user = insert(:user, is_confirmed: false)
1590
1591 {:ok, job} = User.delete(user)
1592 {:ok, _} = ObanHelpers.perform(job)
1593
1594 refute User.get_cached_by_id(user.id)
1595 refute User.get_by_id(user.id)
1596 end
1597
1598 test "delete/1 when approval is pending deletes the user" do
1599 user = insert(:user, is_approved: false)
1600
1601 {:ok, job} = User.delete(user)
1602 {:ok, _} = ObanHelpers.perform(job)
1603
1604 refute User.get_cached_by_id(user.id)
1605 refute User.get_by_id(user.id)
1606 end
1607
1608 test "delete/1 purges a user when they wouldn't be fully deleted" do
1609 user =
1610 insert(:user, %{
1611 bio: "eyy lmao",
1612 name: "qqqqqqq",
1613 password_hash: "pdfk2$1b3n159001",
1614 keys: "RSA begin buplic key",
1615 public_key: "--PRIVATE KEYE--",
1616 avatar: %{"a" => "b"},
1617 tags: ["qqqqq"],
1618 banner: %{"a" => "b"},
1619 background: %{"a" => "b"},
1620 note_count: 9,
1621 follower_count: 9,
1622 following_count: 9001,
1623 is_locked: true,
1624 is_confirmed: false,
1625 password_reset_pending: true,
1626 is_approved: false,
1627 registration_reason: "ahhhhh",
1628 confirmation_token: "qqqq",
1629 domain_blocks: ["lain.com"],
1630 is_active: false,
1631 ap_enabled: true,
1632 is_moderator: true,
1633 is_admin: true,
1634 mascot: %{"a" => "b"},
1635 emoji: %{"a" => "b"},
1636 pleroma_settings_store: %{"q" => "x"},
1637 fields: [%{"gg" => "qq"}],
1638 raw_fields: [%{"gg" => "qq"}],
1639 is_discoverable: true,
1640 also_known_as: ["https://lol.olo/users/loll"]
1641 })
1642
1643 {:ok, job} = User.delete(user)
1644 {:ok, _} = ObanHelpers.perform(job)
1645 user = User.get_by_id(user.id)
1646
1647 assert %User{
1648 bio: "",
1649 raw_bio: nil,
1650 email: nil,
1651 name: nil,
1652 password_hash: nil,
1653 keys: nil,
1654 public_key: nil,
1655 avatar: %{},
1656 tags: [],
1657 last_refreshed_at: nil,
1658 last_digest_emailed_at: nil,
1659 banner: %{},
1660 background: %{},
1661 note_count: 0,
1662 follower_count: 0,
1663 following_count: 0,
1664 is_locked: false,
1665 is_confirmed: true,
1666 password_reset_pending: false,
1667 is_approved: true,
1668 registration_reason: nil,
1669 confirmation_token: nil,
1670 domain_blocks: [],
1671 is_active: false,
1672 ap_enabled: false,
1673 is_moderator: false,
1674 is_admin: false,
1675 mascot: nil,
1676 emoji: %{},
1677 pleroma_settings_store: %{},
1678 fields: [],
1679 raw_fields: [],
1680 is_discoverable: false,
1681 also_known_as: []
1682 } = user
1683 end
1684
1685 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1686 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1687 end
1688
1689 describe "per-user rich-text filtering" do
1690 test "html_filter_policy returns default policies, when rich-text is enabled" do
1691 user = insert(:user)
1692
1693 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1694 end
1695
1696 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1697 user = insert(:user, no_rich_text: true)
1698
1699 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1700 end
1701 end
1702
1703 describe "caching" do
1704 test "invalidate_cache works" do
1705 user = insert(:user)
1706
1707 User.set_cache(user)
1708 User.invalidate_cache(user)
1709
1710 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1711 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1712 end
1713
1714 test "User.delete() plugs any possible zombie objects" do
1715 user = insert(:user)
1716
1717 {:ok, job} = User.delete(user)
1718 {:ok, _} = ObanHelpers.perform(job)
1719
1720 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1721
1722 assert cached_user != user
1723
1724 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1725
1726 assert cached_user != user
1727 end
1728 end
1729
1730 describe "account_status/1" do
1731 setup do: clear_config([:instance, :account_activation_required])
1732
1733 test "return confirmation_pending for unconfirm user" do
1734 clear_config([:instance, :account_activation_required], true)
1735 user = insert(:user, is_confirmed: false)
1736 assert User.account_status(user) == :confirmation_pending
1737 end
1738
1739 test "return active for confirmed user" do
1740 clear_config([:instance, :account_activation_required], true)
1741 user = insert(:user, is_confirmed: true)
1742 assert User.account_status(user) == :active
1743 end
1744
1745 test "return active for remote user" do
1746 user = insert(:user, local: false)
1747 assert User.account_status(user) == :active
1748 end
1749
1750 test "returns :password_reset_pending for user with reset password" do
1751 user = insert(:user, password_reset_pending: true)
1752 assert User.account_status(user) == :password_reset_pending
1753 end
1754
1755 test "returns :deactivated for deactivated user" do
1756 user = insert(:user, local: true, is_confirmed: true, is_active: false)
1757 assert User.account_status(user) == :deactivated
1758 end
1759
1760 test "returns :approval_pending for unapproved user" do
1761 user = insert(:user, local: true, is_approved: false)
1762 assert User.account_status(user) == :approval_pending
1763
1764 user = insert(:user, local: true, is_confirmed: false, is_approved: false)
1765 assert User.account_status(user) == :approval_pending
1766 end
1767 end
1768
1769 describe "superuser?/1" do
1770 test "returns false for unprivileged users" do
1771 user = insert(:user, local: true)
1772
1773 refute User.superuser?(user)
1774 end
1775
1776 test "returns false for remote users" do
1777 user = insert(:user, local: false)
1778 remote_admin_user = insert(:user, local: false, is_admin: true)
1779
1780 refute User.superuser?(user)
1781 refute User.superuser?(remote_admin_user)
1782 end
1783
1784 test "returns true for local moderators" do
1785 user = insert(:user, local: true, is_moderator: true)
1786
1787 assert User.superuser?(user)
1788 end
1789
1790 test "returns true for local admins" do
1791 user = insert(:user, local: true, is_admin: true)
1792
1793 assert User.superuser?(user)
1794 end
1795 end
1796
1797 describe "invisible?/1" do
1798 test "returns true for an invisible user" do
1799 user = insert(:user, local: true, invisible: true)
1800
1801 assert User.invisible?(user)
1802 end
1803
1804 test "returns false for a non-invisible user" do
1805 user = insert(:user, local: true)
1806
1807 refute User.invisible?(user)
1808 end
1809 end
1810
1811 describe "visible_for/2" do
1812 test "returns true when the account is itself" do
1813 user = insert(:user, local: true)
1814
1815 assert User.visible_for(user, user) == :visible
1816 end
1817
1818 test "returns false when the account is unconfirmed and confirmation is required" do
1819 clear_config([:instance, :account_activation_required], true)
1820
1821 user = insert(:user, local: true, is_confirmed: false)
1822 other_user = insert(:user, local: true)
1823
1824 refute User.visible_for(user, other_user) == :visible
1825 end
1826
1827 test "returns true when the account is unconfirmed and confirmation is required but the account is remote" do
1828 clear_config([:instance, :account_activation_required], true)
1829
1830 user = insert(:user, local: false, is_confirmed: false)
1831 other_user = insert(:user, local: true)
1832
1833 assert User.visible_for(user, other_user) == :visible
1834 end
1835
1836 test "returns true when the account is unconfirmed and being viewed by a privileged account (confirmation required)" do
1837 clear_config([:instance, :account_activation_required], true)
1838
1839 user = insert(:user, local: true, is_confirmed: false)
1840 other_user = insert(:user, local: true, is_admin: true)
1841
1842 assert User.visible_for(user, other_user) == :visible
1843 end
1844 end
1845
1846 describe "parse_bio/2" do
1847 test "preserves hosts in user links text" do
1848 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1849 user = insert(:user)
1850 bio = "A.k.a. @nick@domain.com"
1851
1852 expected_text =
1853 ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
1854 remote_user.ap_id
1855 }" rel="ugc">@<span>nick@domain.com</span></a></span>)
1856
1857 assert expected_text == User.parse_bio(bio, user)
1858 end
1859
1860 test "Adds rel=me on linkbacked urls" do
1861 user = insert(:user, ap_id: "https://social.example.org/users/lain")
1862
1863 bio = "http://example.com/rel_me/null"
1864 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1865 assert expected_text == User.parse_bio(bio, user)
1866
1867 bio = "http://example.com/rel_me/link"
1868 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1869 assert expected_text == User.parse_bio(bio, user)
1870
1871 bio = "http://example.com/rel_me/anchor"
1872 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1873 assert expected_text == User.parse_bio(bio, user)
1874 end
1875 end
1876
1877 test "follower count is updated when a follower is blocked" do
1878 user = insert(:user)
1879 follower = insert(:user)
1880 follower2 = insert(:user)
1881 follower3 = insert(:user)
1882
1883 {:ok, follower, user} = User.follow(follower, user)
1884 {:ok, _follower2, _user} = User.follow(follower2, user)
1885 {:ok, _follower3, _user} = User.follow(follower3, user)
1886
1887 {:ok, _user_relationship} = User.block(user, follower)
1888 user = refresh_record(user)
1889
1890 assert user.follower_count == 2
1891 end
1892
1893 describe "list_inactive_users_query/1" do
1894 defp days_ago(days) do
1895 NaiveDateTime.add(
1896 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
1897 -days * 60 * 60 * 24,
1898 :second
1899 )
1900 end
1901
1902 test "Users are inactive by default" do
1903 total = 10
1904
1905 users =
1906 Enum.map(1..total, fn _ ->
1907 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
1908 end)
1909
1910 inactive_users_ids =
1911 Pleroma.User.list_inactive_users_query()
1912 |> Pleroma.Repo.all()
1913 |> Enum.map(& &1.id)
1914
1915 Enum.each(users, fn user ->
1916 assert user.id in inactive_users_ids
1917 end)
1918 end
1919
1920 test "Only includes users who has no recent activity" do
1921 total = 10
1922
1923 users =
1924 Enum.map(1..total, fn _ ->
1925 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
1926 end)
1927
1928 {inactive, active} = Enum.split(users, trunc(total / 2))
1929
1930 Enum.map(active, fn user ->
1931 to = Enum.random(users -- [user])
1932
1933 {:ok, _} =
1934 CommonAPI.post(user, %{
1935 status: "hey @#{to.nickname}"
1936 })
1937 end)
1938
1939 inactive_users_ids =
1940 Pleroma.User.list_inactive_users_query()
1941 |> Pleroma.Repo.all()
1942 |> Enum.map(& &1.id)
1943
1944 Enum.each(active, fn user ->
1945 refute user.id in inactive_users_ids
1946 end)
1947
1948 Enum.each(inactive, fn user ->
1949 assert user.id in inactive_users_ids
1950 end)
1951 end
1952
1953 test "Only includes users with no read notifications" do
1954 total = 10
1955
1956 users =
1957 Enum.map(1..total, fn _ ->
1958 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
1959 end)
1960
1961 [sender | recipients] = users
1962 {inactive, active} = Enum.split(recipients, trunc(total / 2))
1963
1964 Enum.each(recipients, fn to ->
1965 {:ok, _} =
1966 CommonAPI.post(sender, %{
1967 status: "hey @#{to.nickname}"
1968 })
1969
1970 {:ok, _} =
1971 CommonAPI.post(sender, %{
1972 status: "hey again @#{to.nickname}"
1973 })
1974 end)
1975
1976 Enum.each(active, fn user ->
1977 [n1, _n2] = Pleroma.Notification.for_user(user)
1978 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
1979 end)
1980
1981 inactive_users_ids =
1982 Pleroma.User.list_inactive_users_query()
1983 |> Pleroma.Repo.all()
1984 |> Enum.map(& &1.id)
1985
1986 Enum.each(active, fn user ->
1987 refute user.id in inactive_users_ids
1988 end)
1989
1990 Enum.each(inactive, fn user ->
1991 assert user.id in inactive_users_ids
1992 end)
1993 end
1994 end
1995
1996 describe "ensure_keys_present" do
1997 test "it creates keys for a user and stores them in info" do
1998 user = insert(:user)
1999 refute is_binary(user.keys)
2000 {:ok, user} = User.ensure_keys_present(user)
2001 assert is_binary(user.keys)
2002 end
2003
2004 test "it doesn't create keys if there already are some" do
2005 user = insert(:user, keys: "xxx")
2006 {:ok, user} = User.ensure_keys_present(user)
2007 assert user.keys == "xxx"
2008 end
2009 end
2010
2011 describe "get_ap_ids_by_nicknames" do
2012 test "it returns a list of AP ids for a given set of nicknames" do
2013 user = insert(:user)
2014 user_two = insert(:user)
2015
2016 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
2017 assert length(ap_ids) == 2
2018 assert user.ap_id in ap_ids
2019 assert user_two.ap_id in ap_ids
2020 end
2021 end
2022
2023 describe "sync followers count" do
2024 setup do
2025 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
2026 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
2027 insert(:user, local: true)
2028 insert(:user, local: false, is_active: false)
2029 {:ok, user1: user1, user2: user2}
2030 end
2031
2032 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
2033 [fdb_user1] = User.external_users(limit: 1)
2034
2035 assert fdb_user1.ap_id
2036 assert fdb_user1.ap_id == user1.ap_id
2037 assert fdb_user1.id == user1.id
2038
2039 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
2040
2041 assert fdb_user2.ap_id
2042 assert fdb_user2.ap_id == user2.ap_id
2043 assert fdb_user2.id == user2.id
2044
2045 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
2046 end
2047 end
2048
2049 describe "is_internal_user?/1" do
2050 test "non-internal user returns false" do
2051 user = insert(:user)
2052 refute User.is_internal_user?(user)
2053 end
2054
2055 test "user with no nickname returns true" do
2056 user = insert(:user, %{nickname: nil})
2057 assert User.is_internal_user?(user)
2058 end
2059
2060 test "user with internal-prefixed nickname returns true" do
2061 user = insert(:user, %{nickname: "internal.test"})
2062 assert User.is_internal_user?(user)
2063 end
2064 end
2065
2066 describe "update_and_set_cache/1" do
2067 test "returns error when user is stale instead Ecto.StaleEntryError" do
2068 user = insert(:user)
2069
2070 changeset = Ecto.Changeset.change(user, bio: "test")
2071
2072 Repo.delete(user)
2073
2074 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
2075 User.update_and_set_cache(changeset)
2076 end
2077
2078 test "performs update cache if user updated" do
2079 user = insert(:user)
2080 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
2081
2082 changeset = Ecto.Changeset.change(user, bio: "test-bio")
2083
2084 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
2085 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
2086 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
2087 end
2088 end
2089
2090 describe "following/followers synchronization" do
2091 setup do: clear_config([:instance, :external_user_synchronization])
2092
2093 test "updates the counters normally on following/getting a follow when disabled" do
2094 clear_config([:instance, :external_user_synchronization], false)
2095 user = insert(:user)
2096
2097 other_user =
2098 insert(:user,
2099 local: false,
2100 follower_address: "http://localhost:4001/users/masto_closed/followers",
2101 following_address: "http://localhost:4001/users/masto_closed/following",
2102 ap_enabled: true
2103 )
2104
2105 assert other_user.following_count == 0
2106 assert other_user.follower_count == 0
2107
2108 {:ok, user, other_user} = Pleroma.User.follow(user, other_user)
2109
2110 assert user.following_count == 1
2111 assert other_user.follower_count == 1
2112 end
2113
2114 test "syncronizes the counters with the remote instance for the followed when enabled" do
2115 clear_config([:instance, :external_user_synchronization], false)
2116
2117 user = insert(:user)
2118
2119 other_user =
2120 insert(:user,
2121 local: false,
2122 follower_address: "http://localhost:4001/users/masto_closed/followers",
2123 following_address: "http://localhost:4001/users/masto_closed/following",
2124 ap_enabled: true
2125 )
2126
2127 assert other_user.following_count == 0
2128 assert other_user.follower_count == 0
2129
2130 clear_config([:instance, :external_user_synchronization], true)
2131 {:ok, _user, other_user} = User.follow(user, other_user)
2132
2133 assert other_user.follower_count == 437
2134 end
2135
2136 test "syncronizes the counters with the remote instance for the follower when enabled" do
2137 clear_config([:instance, :external_user_synchronization], false)
2138
2139 user = insert(:user)
2140
2141 other_user =
2142 insert(:user,
2143 local: false,
2144 follower_address: "http://localhost:4001/users/masto_closed/followers",
2145 following_address: "http://localhost:4001/users/masto_closed/following",
2146 ap_enabled: true
2147 )
2148
2149 assert other_user.following_count == 0
2150 assert other_user.follower_count == 0
2151
2152 clear_config([:instance, :external_user_synchronization], true)
2153 {:ok, other_user, _user} = User.follow(other_user, user)
2154
2155 assert other_user.following_count == 152
2156 end
2157 end
2158
2159 describe "change_email/2" do
2160 setup do
2161 [user: insert(:user)]
2162 end
2163
2164 test "blank email returns error", %{user: user} do
2165 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
2166 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
2167 end
2168
2169 test "non unique email returns error", %{user: user} do
2170 %{email: email} = insert(:user)
2171
2172 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
2173 User.change_email(user, email)
2174 end
2175
2176 test "invalid email returns error", %{user: user} do
2177 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
2178 User.change_email(user, "cofe")
2179 end
2180
2181 test "changes email", %{user: user} do
2182 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
2183 end
2184 end
2185
2186 describe "get_cached_by_nickname_or_id" do
2187 setup do
2188 local_user = insert(:user)
2189 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
2190
2191 [local_user: local_user, remote_user: remote_user]
2192 end
2193
2194 setup do: clear_config([:instance, :limit_to_local_content])
2195
2196 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
2197 remote_user: remote_user
2198 } do
2199 clear_config([:instance, :limit_to_local_content], false)
2200 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2201
2202 clear_config([:instance, :limit_to_local_content], true)
2203 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2204
2205 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2206 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2207 end
2208
2209 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
2210 %{remote_user: remote_user} do
2211 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2212 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2213 end
2214
2215 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
2216 %{remote_user: remote_user, local_user: local_user} do
2217 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2218 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
2219 end
2220
2221 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
2222 %{remote_user: remote_user} do
2223 clear_config([:instance, :limit_to_local_content], true)
2224 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2225 end
2226
2227 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
2228 %{local_user: local_user} do
2229 clear_config([:instance, :limit_to_local_content], false)
2230 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2231
2232 clear_config([:instance, :limit_to_local_content], true)
2233 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2234
2235 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2236 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2237 end
2238 end
2239
2240 describe "update_email_notifications/2" do
2241 setup do
2242 user = insert(:user, email_notifications: %{"digest" => true})
2243
2244 {:ok, user: user}
2245 end
2246
2247 test "Notifications are updated", %{user: user} do
2248 true = user.email_notifications["digest"]
2249 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
2250 assert result.email_notifications["digest"] == false
2251 end
2252 end
2253
2254 describe "local_nickname/1" do
2255 test "returns nickname without host" do
2256 assert User.local_nickname("@mentioned") == "mentioned"
2257 assert User.local_nickname("a_local_nickname") == "a_local_nickname"
2258 assert User.local_nickname("nickname@host.com") == "nickname"
2259 end
2260 end
2261
2262 describe "full_nickname/1" do
2263 test "returns fully qualified nickname for local and remote users" do
2264 local_user =
2265 insert(:user, nickname: "local_user", ap_id: "https://somehost.com/users/local_user")
2266
2267 remote_user = insert(:user, nickname: "remote@host.com", local: false)
2268
2269 assert User.full_nickname(local_user) == "local_user@somehost.com"
2270 assert User.full_nickname(remote_user) == "remote@host.com"
2271 end
2272
2273 test "strips leading @ from mentions" do
2274 assert User.full_nickname("@mentioned") == "mentioned"
2275 assert User.full_nickname("@nickname@host.com") == "nickname@host.com"
2276 end
2277
2278 test "does not modify nicknames" do
2279 assert User.full_nickname("nickname") == "nickname"
2280 assert User.full_nickname("nickname@host.com") == "nickname@host.com"
2281 end
2282 end
2283
2284 test "avatar fallback" do
2285 user = insert(:user)
2286 assert User.avatar_url(user) =~ "/images/avi.png"
2287
2288 clear_config([:assets, :default_user_avatar], "avatar.png")
2289
2290 user = User.get_cached_by_nickname_or_id(user.nickname)
2291 assert User.avatar_url(user) =~ "avatar.png"
2292
2293 assert User.avatar_url(user, no_default: true) == nil
2294 end
2295
2296 test "get_host/1" do
2297 user = insert(:user, ap_id: "https://lain.com/users/lain", nickname: "lain")
2298 assert User.get_host(user) == "lain.com"
2299 end
2300
2301 test "update_last_active_at/1" do
2302 user = insert(:user)
2303 assert is_nil(user.last_active_at)
2304
2305 test_started_at = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
2306
2307 assert {:ok, user} = User.update_last_active_at(user)
2308
2309 assert user.last_active_at >= test_started_at
2310 assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
2311
2312 last_active_at =
2313 NaiveDateTime.utc_now()
2314 |> NaiveDateTime.add(-:timer.hours(24), :millisecond)
2315 |> NaiveDateTime.truncate(:second)
2316
2317 assert {:ok, user} =
2318 user
2319 |> cast(%{last_active_at: last_active_at}, [:last_active_at])
2320 |> User.update_and_set_cache()
2321
2322 assert user.last_active_at == last_active_at
2323 assert {:ok, user} = User.update_last_active_at(user)
2324 assert user.last_active_at >= test_started_at
2325 assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
2326 end
2327
2328 test "active_user_count/1" do
2329 insert(:user)
2330 insert(:user, %{local: false})
2331 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), weeks: -5)})
2332 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), weeks: -3)})
2333 insert(:user, %{last_active_at: NaiveDateTime.utc_now()})
2334
2335 assert User.active_user_count() == 2
2336 assert User.active_user_count(6) == 3
2337 assert User.active_user_count(1) == 1
2338 end
2339 end