Let pins federate
[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 mastofe_settings: %{"a" => "b"},
1635 mascot: %{"a" => "b"},
1636 emoji: %{"a" => "b"},
1637 pleroma_settings_store: %{"q" => "x"},
1638 fields: [%{"gg" => "qq"}],
1639 raw_fields: [%{"gg" => "qq"}],
1640 is_discoverable: true,
1641 also_known_as: ["https://lol.olo/users/loll"]
1642 })
1643
1644 {:ok, job} = User.delete(user)
1645 {:ok, _} = ObanHelpers.perform(job)
1646 user = User.get_by_id(user.id)
1647
1648 assert %User{
1649 bio: "",
1650 raw_bio: nil,
1651 email: nil,
1652 name: nil,
1653 password_hash: nil,
1654 keys: nil,
1655 public_key: nil,
1656 avatar: %{},
1657 tags: [],
1658 last_refreshed_at: nil,
1659 last_digest_emailed_at: nil,
1660 banner: %{},
1661 background: %{},
1662 note_count: 0,
1663 follower_count: 0,
1664 following_count: 0,
1665 is_locked: false,
1666 is_confirmed: true,
1667 password_reset_pending: false,
1668 is_approved: true,
1669 registration_reason: nil,
1670 confirmation_token: nil,
1671 domain_blocks: [],
1672 is_active: false,
1673 ap_enabled: false,
1674 is_moderator: false,
1675 is_admin: false,
1676 mastofe_settings: nil,
1677 mascot: nil,
1678 emoji: %{},
1679 pleroma_settings_store: %{},
1680 fields: [],
1681 raw_fields: [],
1682 is_discoverable: false,
1683 also_known_as: []
1684 } = user
1685 end
1686
1687 test "get_public_key_for_ap_id fetches a user that's not in the db" do
1688 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
1689 end
1690
1691 describe "per-user rich-text filtering" do
1692 test "html_filter_policy returns default policies, when rich-text is enabled" do
1693 user = insert(:user)
1694
1695 assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
1696 end
1697
1698 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
1699 user = insert(:user, no_rich_text: true)
1700
1701 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
1702 end
1703 end
1704
1705 describe "caching" do
1706 test "invalidate_cache works" do
1707 user = insert(:user)
1708
1709 User.set_cache(user)
1710 User.invalidate_cache(user)
1711
1712 {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1713 {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
1714 end
1715
1716 test "User.delete() plugs any possible zombie objects" do
1717 user = insert(:user)
1718
1719 {:ok, job} = User.delete(user)
1720 {:ok, _} = ObanHelpers.perform(job)
1721
1722 {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
1723
1724 assert cached_user != user
1725
1726 {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
1727
1728 assert cached_user != user
1729 end
1730 end
1731
1732 describe "account_status/1" do
1733 setup do: clear_config([:instance, :account_activation_required])
1734
1735 test "return confirmation_pending for unconfirm user" do
1736 clear_config([:instance, :account_activation_required], true)
1737 user = insert(:user, is_confirmed: false)
1738 assert User.account_status(user) == :confirmation_pending
1739 end
1740
1741 test "return active for confirmed user" do
1742 clear_config([:instance, :account_activation_required], true)
1743 user = insert(:user, is_confirmed: true)
1744 assert User.account_status(user) == :active
1745 end
1746
1747 test "return active for remote user" do
1748 user = insert(:user, local: false)
1749 assert User.account_status(user) == :active
1750 end
1751
1752 test "returns :password_reset_pending for user with reset password" do
1753 user = insert(:user, password_reset_pending: true)
1754 assert User.account_status(user) == :password_reset_pending
1755 end
1756
1757 test "returns :deactivated for deactivated user" do
1758 user = insert(:user, local: true, is_confirmed: true, is_active: false)
1759 assert User.account_status(user) == :deactivated
1760 end
1761
1762 test "returns :approval_pending for unapproved user" do
1763 user = insert(:user, local: true, is_approved: false)
1764 assert User.account_status(user) == :approval_pending
1765
1766 user = insert(:user, local: true, is_confirmed: false, is_approved: false)
1767 assert User.account_status(user) == :approval_pending
1768 end
1769 end
1770
1771 describe "superuser?/1" do
1772 test "returns false for unprivileged users" do
1773 user = insert(:user, local: true)
1774
1775 refute User.superuser?(user)
1776 end
1777
1778 test "returns false for remote users" do
1779 user = insert(:user, local: false)
1780 remote_admin_user = insert(:user, local: false, is_admin: true)
1781
1782 refute User.superuser?(user)
1783 refute User.superuser?(remote_admin_user)
1784 end
1785
1786 test "returns true for local moderators" do
1787 user = insert(:user, local: true, is_moderator: true)
1788
1789 assert User.superuser?(user)
1790 end
1791
1792 test "returns true for local admins" do
1793 user = insert(:user, local: true, is_admin: true)
1794
1795 assert User.superuser?(user)
1796 end
1797 end
1798
1799 describe "invisible?/1" do
1800 test "returns true for an invisible user" do
1801 user = insert(:user, local: true, invisible: true)
1802
1803 assert User.invisible?(user)
1804 end
1805
1806 test "returns false for a non-invisible user" do
1807 user = insert(:user, local: true)
1808
1809 refute User.invisible?(user)
1810 end
1811 end
1812
1813 describe "visible_for/2" do
1814 test "returns true when the account is itself" do
1815 user = insert(:user, local: true)
1816
1817 assert User.visible_for(user, user) == :visible
1818 end
1819
1820 test "returns false when the account is unconfirmed and confirmation is required" do
1821 clear_config([:instance, :account_activation_required], true)
1822
1823 user = insert(:user, local: true, is_confirmed: false)
1824 other_user = insert(:user, local: true)
1825
1826 refute User.visible_for(user, other_user) == :visible
1827 end
1828
1829 test "returns true when the account is unconfirmed and confirmation is required but the account is remote" do
1830 clear_config([:instance, :account_activation_required], true)
1831
1832 user = insert(:user, local: false, is_confirmed: false)
1833 other_user = insert(:user, local: true)
1834
1835 assert User.visible_for(user, other_user) == :visible
1836 end
1837
1838 test "returns true when the account is unconfirmed and being viewed by a privileged account (confirmation required)" do
1839 clear_config([:instance, :account_activation_required], true)
1840
1841 user = insert(:user, local: true, is_confirmed: false)
1842 other_user = insert(:user, local: true, is_admin: true)
1843
1844 assert User.visible_for(user, other_user) == :visible
1845 end
1846 end
1847
1848 describe "parse_bio/2" do
1849 test "preserves hosts in user links text" do
1850 remote_user = insert(:user, local: false, nickname: "nick@domain.com")
1851 user = insert(:user)
1852 bio = "A.k.a. @nick@domain.com"
1853
1854 expected_text =
1855 ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
1856 remote_user.ap_id
1857 }" rel="ugc">@<span>nick@domain.com</span></a></span>)
1858
1859 assert expected_text == User.parse_bio(bio, user)
1860 end
1861
1862 test "Adds rel=me on linkbacked urls" do
1863 user = insert(:user, ap_id: "https://social.example.org/users/lain")
1864
1865 bio = "http://example.com/rel_me/null"
1866 expected_text = "<a href=\"#{bio}\">#{bio}</a>"
1867 assert expected_text == User.parse_bio(bio, user)
1868
1869 bio = "http://example.com/rel_me/link"
1870 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1871 assert expected_text == User.parse_bio(bio, user)
1872
1873 bio = "http://example.com/rel_me/anchor"
1874 expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
1875 assert expected_text == User.parse_bio(bio, user)
1876 end
1877 end
1878
1879 test "follower count is updated when a follower is blocked" do
1880 user = insert(:user)
1881 follower = insert(:user)
1882 follower2 = insert(:user)
1883 follower3 = insert(:user)
1884
1885 {:ok, follower, user} = User.follow(follower, user)
1886 {:ok, _follower2, _user} = User.follow(follower2, user)
1887 {:ok, _follower3, _user} = User.follow(follower3, user)
1888
1889 {:ok, _user_relationship} = User.block(user, follower)
1890 user = refresh_record(user)
1891
1892 assert user.follower_count == 2
1893 end
1894
1895 describe "list_inactive_users_query/1" do
1896 defp days_ago(days) do
1897 NaiveDateTime.add(
1898 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
1899 -days * 60 * 60 * 24,
1900 :second
1901 )
1902 end
1903
1904 test "Users are inactive by default" do
1905 total = 10
1906
1907 users =
1908 Enum.map(1..total, fn _ ->
1909 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
1910 end)
1911
1912 inactive_users_ids =
1913 Pleroma.User.list_inactive_users_query()
1914 |> Pleroma.Repo.all()
1915 |> Enum.map(& &1.id)
1916
1917 Enum.each(users, fn user ->
1918 assert user.id in inactive_users_ids
1919 end)
1920 end
1921
1922 test "Only includes users who has no recent activity" do
1923 total = 10
1924
1925 users =
1926 Enum.map(1..total, fn _ ->
1927 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
1928 end)
1929
1930 {inactive, active} = Enum.split(users, trunc(total / 2))
1931
1932 Enum.map(active, fn user ->
1933 to = Enum.random(users -- [user])
1934
1935 {:ok, _} =
1936 CommonAPI.post(user, %{
1937 status: "hey @#{to.nickname}"
1938 })
1939 end)
1940
1941 inactive_users_ids =
1942 Pleroma.User.list_inactive_users_query()
1943 |> Pleroma.Repo.all()
1944 |> Enum.map(& &1.id)
1945
1946 Enum.each(active, fn user ->
1947 refute user.id in inactive_users_ids
1948 end)
1949
1950 Enum.each(inactive, fn user ->
1951 assert user.id in inactive_users_ids
1952 end)
1953 end
1954
1955 test "Only includes users with no read notifications" do
1956 total = 10
1957
1958 users =
1959 Enum.map(1..total, fn _ ->
1960 insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
1961 end)
1962
1963 [sender | recipients] = users
1964 {inactive, active} = Enum.split(recipients, trunc(total / 2))
1965
1966 Enum.each(recipients, fn to ->
1967 {:ok, _} =
1968 CommonAPI.post(sender, %{
1969 status: "hey @#{to.nickname}"
1970 })
1971
1972 {:ok, _} =
1973 CommonAPI.post(sender, %{
1974 status: "hey again @#{to.nickname}"
1975 })
1976 end)
1977
1978 Enum.each(active, fn user ->
1979 [n1, _n2] = Pleroma.Notification.for_user(user)
1980 {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
1981 end)
1982
1983 inactive_users_ids =
1984 Pleroma.User.list_inactive_users_query()
1985 |> Pleroma.Repo.all()
1986 |> Enum.map(& &1.id)
1987
1988 Enum.each(active, fn user ->
1989 refute user.id in inactive_users_ids
1990 end)
1991
1992 Enum.each(inactive, fn user ->
1993 assert user.id in inactive_users_ids
1994 end)
1995 end
1996 end
1997
1998 describe "ensure_keys_present" do
1999 test "it creates keys for a user and stores them in info" do
2000 user = insert(:user)
2001 refute is_binary(user.keys)
2002 {:ok, user} = User.ensure_keys_present(user)
2003 assert is_binary(user.keys)
2004 end
2005
2006 test "it doesn't create keys if there already are some" do
2007 user = insert(:user, keys: "xxx")
2008 {:ok, user} = User.ensure_keys_present(user)
2009 assert user.keys == "xxx"
2010 end
2011 end
2012
2013 describe "get_ap_ids_by_nicknames" do
2014 test "it returns a list of AP ids for a given set of nicknames" do
2015 user = insert(:user)
2016 user_two = insert(:user)
2017
2018 ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
2019 assert length(ap_ids) == 2
2020 assert user.ap_id in ap_ids
2021 assert user_two.ap_id in ap_ids
2022 end
2023 end
2024
2025 describe "sync followers count" do
2026 setup do
2027 user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
2028 user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
2029 insert(:user, local: true)
2030 insert(:user, local: false, is_active: false)
2031 {:ok, user1: user1, user2: user2}
2032 end
2033
2034 test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
2035 [fdb_user1] = User.external_users(limit: 1)
2036
2037 assert fdb_user1.ap_id
2038 assert fdb_user1.ap_id == user1.ap_id
2039 assert fdb_user1.id == user1.id
2040
2041 [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
2042
2043 assert fdb_user2.ap_id
2044 assert fdb_user2.ap_id == user2.ap_id
2045 assert fdb_user2.id == user2.id
2046
2047 assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
2048 end
2049 end
2050
2051 describe "is_internal_user?/1" do
2052 test "non-internal user returns false" do
2053 user = insert(:user)
2054 refute User.is_internal_user?(user)
2055 end
2056
2057 test "user with no nickname returns true" do
2058 user = insert(:user, %{nickname: nil})
2059 assert User.is_internal_user?(user)
2060 end
2061
2062 test "user with internal-prefixed nickname returns true" do
2063 user = insert(:user, %{nickname: "internal.test"})
2064 assert User.is_internal_user?(user)
2065 end
2066 end
2067
2068 describe "update_and_set_cache/1" do
2069 test "returns error when user is stale instead Ecto.StaleEntryError" do
2070 user = insert(:user)
2071
2072 changeset = Ecto.Changeset.change(user, bio: "test")
2073
2074 Repo.delete(user)
2075
2076 assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
2077 User.update_and_set_cache(changeset)
2078 end
2079
2080 test "performs update cache if user updated" do
2081 user = insert(:user)
2082 assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
2083
2084 changeset = Ecto.Changeset.change(user, bio: "test-bio")
2085
2086 assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
2087 assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
2088 assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
2089 end
2090 end
2091
2092 describe "following/followers synchronization" do
2093 setup do: clear_config([:instance, :external_user_synchronization])
2094
2095 test "updates the counters normally on following/getting a follow when disabled" do
2096 clear_config([:instance, :external_user_synchronization], false)
2097 user = insert(:user)
2098
2099 other_user =
2100 insert(:user,
2101 local: false,
2102 follower_address: "http://localhost:4001/users/masto_closed/followers",
2103 following_address: "http://localhost:4001/users/masto_closed/following",
2104 ap_enabled: true
2105 )
2106
2107 assert other_user.following_count == 0
2108 assert other_user.follower_count == 0
2109
2110 {:ok, user, other_user} = Pleroma.User.follow(user, other_user)
2111
2112 assert user.following_count == 1
2113 assert other_user.follower_count == 1
2114 end
2115
2116 test "syncronizes the counters with the remote instance for the followed when enabled" do
2117 clear_config([:instance, :external_user_synchronization], false)
2118
2119 user = insert(:user)
2120
2121 other_user =
2122 insert(:user,
2123 local: false,
2124 follower_address: "http://localhost:4001/users/masto_closed/followers",
2125 following_address: "http://localhost:4001/users/masto_closed/following",
2126 ap_enabled: true
2127 )
2128
2129 assert other_user.following_count == 0
2130 assert other_user.follower_count == 0
2131
2132 clear_config([:instance, :external_user_synchronization], true)
2133 {:ok, _user, other_user} = User.follow(user, other_user)
2134
2135 assert other_user.follower_count == 437
2136 end
2137
2138 test "syncronizes the counters with the remote instance for the follower when enabled" do
2139 clear_config([:instance, :external_user_synchronization], false)
2140
2141 user = insert(:user)
2142
2143 other_user =
2144 insert(:user,
2145 local: false,
2146 follower_address: "http://localhost:4001/users/masto_closed/followers",
2147 following_address: "http://localhost:4001/users/masto_closed/following",
2148 ap_enabled: true
2149 )
2150
2151 assert other_user.following_count == 0
2152 assert other_user.follower_count == 0
2153
2154 clear_config([:instance, :external_user_synchronization], true)
2155 {:ok, other_user, _user} = User.follow(other_user, user)
2156
2157 assert other_user.following_count == 152
2158 end
2159 end
2160
2161 describe "change_email/2" do
2162 setup do
2163 [user: insert(:user)]
2164 end
2165
2166 test "blank email returns error", %{user: user} do
2167 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
2168 assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
2169 end
2170
2171 test "non unique email returns error", %{user: user} do
2172 %{email: email} = insert(:user)
2173
2174 assert {:error, %{errors: [email: {"has already been taken", _}]}} =
2175 User.change_email(user, email)
2176 end
2177
2178 test "invalid email returns error", %{user: user} do
2179 assert {:error, %{errors: [email: {"has invalid format", _}]}} =
2180 User.change_email(user, "cofe")
2181 end
2182
2183 test "changes email", %{user: user} do
2184 assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
2185 end
2186 end
2187
2188 describe "get_cached_by_nickname_or_id" do
2189 setup do
2190 local_user = insert(:user)
2191 remote_user = insert(:user, nickname: "nickname@example.com", local: false)
2192
2193 [local_user: local_user, remote_user: remote_user]
2194 end
2195
2196 setup do: clear_config([:instance, :limit_to_local_content])
2197
2198 test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
2199 remote_user: remote_user
2200 } do
2201 clear_config([:instance, :limit_to_local_content], false)
2202 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2203
2204 clear_config([:instance, :limit_to_local_content], true)
2205 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2206
2207 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2208 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
2209 end
2210
2211 test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
2212 %{remote_user: remote_user} do
2213 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2214 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2215 end
2216
2217 test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
2218 %{remote_user: remote_user, local_user: local_user} do
2219 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2220 assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
2221 end
2222
2223 test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
2224 %{remote_user: remote_user} do
2225 clear_config([:instance, :limit_to_local_content], true)
2226 assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
2227 end
2228
2229 test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
2230 %{local_user: local_user} do
2231 clear_config([:instance, :limit_to_local_content], false)
2232 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2233
2234 clear_config([:instance, :limit_to_local_content], true)
2235 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2236
2237 clear_config([:instance, :limit_to_local_content], :unauthenticated)
2238 assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
2239 end
2240 end
2241
2242 describe "update_email_notifications/2" do
2243 setup do
2244 user = insert(:user, email_notifications: %{"digest" => true})
2245
2246 {:ok, user: user}
2247 end
2248
2249 test "Notifications are updated", %{user: user} do
2250 true = user.email_notifications["digest"]
2251 assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
2252 assert result.email_notifications["digest"] == false
2253 end
2254 end
2255
2256 describe "local_nickname/1" do
2257 test "returns nickname without host" do
2258 assert User.local_nickname("@mentioned") == "mentioned"
2259 assert User.local_nickname("a_local_nickname") == "a_local_nickname"
2260 assert User.local_nickname("nickname@host.com") == "nickname"
2261 end
2262 end
2263
2264 describe "full_nickname/1" do
2265 test "returns fully qualified nickname for local and remote users" do
2266 local_user =
2267 insert(:user, nickname: "local_user", ap_id: "https://somehost.com/users/local_user")
2268
2269 remote_user = insert(:user, nickname: "remote@host.com", local: false)
2270
2271 assert User.full_nickname(local_user) == "local_user@somehost.com"
2272 assert User.full_nickname(remote_user) == "remote@host.com"
2273 end
2274
2275 test "strips leading @ from mentions" do
2276 assert User.full_nickname("@mentioned") == "mentioned"
2277 assert User.full_nickname("@nickname@host.com") == "nickname@host.com"
2278 end
2279
2280 test "does not modify nicknames" do
2281 assert User.full_nickname("nickname") == "nickname"
2282 assert User.full_nickname("nickname@host.com") == "nickname@host.com"
2283 end
2284 end
2285
2286 test "avatar fallback" do
2287 user = insert(:user)
2288 assert User.avatar_url(user) =~ "/images/avi.png"
2289
2290 clear_config([:assets, :default_user_avatar], "avatar.png")
2291
2292 user = User.get_cached_by_nickname_or_id(user.nickname)
2293 assert User.avatar_url(user) =~ "avatar.png"
2294
2295 assert User.avatar_url(user, no_default: true) == nil
2296 end
2297
2298 test "get_host/1" do
2299 user = insert(:user, ap_id: "https://lain.com/users/lain", nickname: "lain")
2300 assert User.get_host(user) == "lain.com"
2301 end
2302
2303 test "update_last_active_at/1" do
2304 user = insert(:user)
2305 assert is_nil(user.last_active_at)
2306
2307 test_started_at = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
2308
2309 assert {:ok, user} = User.update_last_active_at(user)
2310
2311 assert user.last_active_at >= test_started_at
2312 assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
2313
2314 last_active_at =
2315 NaiveDateTime.utc_now()
2316 |> NaiveDateTime.add(-:timer.hours(24), :millisecond)
2317 |> NaiveDateTime.truncate(:second)
2318
2319 assert {:ok, user} =
2320 user
2321 |> cast(%{last_active_at: last_active_at}, [:last_active_at])
2322 |> User.update_and_set_cache()
2323
2324 assert user.last_active_at == last_active_at
2325 assert {:ok, user} = User.update_last_active_at(user)
2326 assert user.last_active_at >= test_started_at
2327 assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
2328 end
2329
2330 test "active_user_count/1" do
2331 insert(:user)
2332 insert(:user, %{local: false})
2333 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), weeks: -5)})
2334 insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), weeks: -3)})
2335 insert(:user, %{last_active_at: NaiveDateTime.utc_now()})
2336
2337 assert User.active_user_count() == 2
2338 assert User.active_user_count(6) == 3
2339 assert User.active_user_count(1) == 1
2340 end
2341
2342 describe "pins" do
2343 setup do
2344 user = insert(:user)
2345
2346 [user: user, object_id: object_id_from_created_activity(user)]
2347 end
2348
2349 test "unique pins", %{user: user, object_id: object_id} do
2350 assert {:ok, %{pinned_objects: %{^object_id => pinned_at1} = pins} = updated_user} =
2351 User.add_pinned_object_id(user, object_id)
2352
2353 assert Enum.count(pins) == 1
2354
2355 assert {:ok, %{pinned_objects: %{^object_id => pinned_at2} = pins}} =
2356 User.add_pinned_object_id(updated_user, object_id)
2357
2358 assert pinned_at1 == pinned_at2
2359
2360 assert Enum.count(pins) == 1
2361 end
2362
2363 test "respects max_pinned_statuses limit", %{user: user, object_id: object_id} do
2364 clear_config([:instance, :max_pinned_statuses], 1)
2365 {:ok, updated} = User.add_pinned_object_id(user, object_id)
2366
2367 object_id2 = object_id_from_created_activity(user)
2368
2369 {:error, %{errors: errors}} = User.add_pinned_object_id(updated, object_id2)
2370 assert Keyword.has_key?(errors, :pinned_objects)
2371 end
2372
2373 test "remove_pinned_object_id/2", %{user: user, object_id: object_id} do
2374 assert {:ok, updated} = User.add_pinned_object_id(user, object_id)
2375
2376 {:ok, after_remove} = User.remove_pinned_object_id(updated, object_id)
2377 assert after_remove.pinned_objects == %{}
2378 end
2379 end
2380
2381 defp object_id_from_created_activity(user) do
2382 %{id: id} = insert(:note_activity, user: user)
2383 %{object: %{data: %{"id" => object_id}}} = Activity.get_by_id_with_object(id)
2384 object_id
2385 end
2386 end