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