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