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