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