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