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